/******************************************************************************/
/***                                                                        ***/
/***  Main                                                                  ***/
/***                                                                        ***/
/***  Module of the !Example program, for the "Software Protection Scheme". ***/
/***                                                                        ***/
/***  Contains the main program control.                                    ***/
/***                                                                        ***/
/***                                                                        ***/
/***                                                                        ***/
/***  Written by N.Critchell, Acorn Computers                   April 1992  ***/
/***                                                                        ***/
/******************************************************************************/

 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>

 #include "wimpt.h"
 #include "res.h"
 #include "resspr.h"
 #include "baricon.h"
 #include "event.h"
 #include "win.h"
 #include "template.h"
 #include "dbox.h"
 #include "txt.h"
 #include "flex.h"
 #include "werr.h"
 #include "bbc.h"

 #include "Example.h"
 #include "SP.h"                        /* SP Scheme include file */




static char     *icon_menu_name = "SPexample";
static char     *icon_menu_options = ">Info,Quit";
static menu      icon_menu;
static menu      icon_menu2;
static wimp_w    main_window_handle;
static char     *window_def_name = "MainWindow";
static BOOL      already_open = FALSE;
static int       original_idle_event_claimer;
static wimp_i    SP_icon_handle;
static wimp_w    SP_win_handle;


/******************************************************************************/
/***                                                                        ***/
/***  main()                                                                ***/
/***                                                                        ***/
/***  This is the first section of code which is executed, this routine     ***/
/***  ensures that the following is performed.                              ***/
/***                                                                        ***/
/******************************************************************************/

int main()
        {
        initialise_resources();
        if (initialise_app(SoftwareProtectionScheme((int *) &SP_win_handle)))
            {
            while(TRUE) event_process();
            }
        else
            {
            werr(FALSE, "Can not start the '!SPexample' application.");
            }
        exit(0);
        }



/******************************************************************************/
/***                                                                        ***/
/***  initialise_resources()                                                ***/
/***                                                                        ***/
/***  Initialises all the window manger tasks required for this application.***/
/***  If an error occurs in the initialisation the routine returns FALSE    ***/
/***  otherwise TRUE is returned.                                           ***/
/***                                                                        ***/
/******************************************************************************/

void initialise_resources()
    {
    wimpt_init("'Software Protection Scheme' !Example");              /* init WIMP name etc                           */
    res_init("SPexample");                                            /* how to find application resources            */
    resspr_init();                                                    /* load application icons                       */
    flex_init();
    template_init();                                                  /* init the templates                           */
    dbox_init();
    }



/******************************************************************************/
/***                                                                        ***/
/***  initialise_app()                                                      ***/
/***                                                                        ***/
/***  Initialises all the window manger tasks required for this application.***/
/***  If an error occurs in the initialisation the routine returns FALSE    ***/
/***  otherwise TRUE is returned.                                           ***/
/***                                                                        ***/
/******************************************************************************/

BOOL initialise_app(int SP_window)
    {
    baricon("!SPexample", (int)resspr_area(), icon_selected_event);

    if (SP_window == TRUE)
        {
        SP_icon_handle = baricon("error", (int)resspr_area(), icon_selected_event);
        }

    /****************************************************************************/
    /** Define the Icons menus & attach an event when a menu option is slected **/
    /****************************************************************************/

    if ((icon_menu = menu_new(icon_menu_name, icon_menu_options)) == NULL) return(FALSE);
    if ((icon_menu2 = menu_new(icon_menu_name, ">Info")) == NULL) return(FALSE);
    if (!event_attachmenumaker(win_ICONBAR, make_menu_event, icon_menu_selected_event, 0)) return(FALSE);    
    return(TRUE);
    }









/******************************************************************************/
/***                                                                        ***/
/***  icon_selected_event()                                                 ***/
/***                                                                        ***/
/***  This routine is called by the WIMP manager whenever the icon on the   ***/
/***  icon bar has been selected.                                           ***/
/***                                                                        ***/
/******************************************************************************/

void icon_selected_event(wimp_i icon)
    {
    wimp_wind    *main_window_definition_ptr;
    wimp_wstate   window_state;
    wimp_eventstr *last_event;

    icon = icon;
    last_event = wimpt_last_event();
    icon = last_event->data.but.m.i;


    if (icon == SP_icon_handle)
        {
        wimpt_complain(wimp_get_wind_state(SP_win_handle, &window_state));
        window_state.o.behind = -1;
        wimpt_noerr(wimp_open_wind(&window_state.o));
        }
    else
        { 
        if (already_open == FALSE)
            {
            already_open = TRUE;
            
            main_window_definition_ptr = template_syshandle(window_def_name);

            wimpt_complain(wimp_create_wind(main_window_definition_ptr, &main_window_handle));

            wimpt_complain(wimp_get_wind_state(main_window_handle, &window_state));
            wimpt_noerr(wimp_open_wind(&window_state.o));


            win_register_event_handler(main_window_handle, main_window_event_occured, 0);

            event_setmask(0);
            original_idle_event_claimer = win_idle_event_claimer();
            win_claim_idle_events(main_window_handle);
            win_claim_unknown_events(main_window_handle);
            }
        else
            {
            wimpt_complain(wimp_get_wind_state(main_window_handle, &window_state));
            window_state.o.behind = -1;
            wimpt_noerr(wimp_open_wind(&window_state.o));
            }
        }
    }





/******************************************************************************/
/***                                                                        ***/
/***  make_menu_event()                                                     ***/
/***                                                                        ***/
/***  This routine is called by the WIMP manager whenever a menu option     ***/
/***  from the icon has been selected.                                      ***/
/***                                                                        ***/
/******************************************************************************/

menu make_menu_event(void *handle)
    {
    wimp_eventstr *last_event;

    handle = handle;

    last_event = wimpt_last_event();

    if (last_event->data.but.m.i == SP_icon_handle) return(icon_menu2);
    else return(icon_menu);
    }




/******************************************************************************/
/***                                                                        ***/
/***  icon_menu_selected_event()                                            ***/
/***                                                                        ***/
/***  This routine is called by the WIMP manager whenever a menu option     ***/
/***  from the icon has been selected.                                      ***/
/***                                                                        ***/
/******************************************************************************/

void icon_menu_selected_event(void *handle, char *hit)
    {
    handle = handle;
        
    switch(hit[0])
        {
        case 1:
            display_info_dbox();
            break;

        case 2:
            exit(0);
            break;

        default:
            werr(FALSE, "Unknown option was selected, try again!");
            break;
        }

    }



/******************************************************************************/
/***                                                                        ***/
/***  main_window_event_occured()                                           ***/
/***                                                                        ***/
/***  This routine is called by the WIMP manager whenever a menu option     ***/
/***  from the icon has been selected.                                      ***/
/***                                                                        ***/
/******************************************************************************/

void main_window_event_occured(wimp_eventstr *e, void *handle)
    {
    int            more;
    wimp_redrawstr r;      
    handle = handle;

 
    switch(e->e)
        {
        case wimp_EREDRAW:

            r.w = e->data.o.w; 
            wimpt_noerr(wimp_redraw_wind(&r, &more));
            while (more)
                {
                wimp_get_rectangle(&r, &more);                  /* just go through the motions */
                }
            break;

        case wimp_EOPEN:
            wimpt_noerr(wimp_open_wind(&e->data.o));
            break;

        case wimp_ECLOSE:
            win_claim_idle_events(original_idle_event_claimer);
            wimpt_noerr(wimp_close_wind(e->data.o.w));
            already_open = FALSE;  
            break;

        case wimp_ENULL:
            draw_new_triangle(main_window_handle);
            break;

        default:
            break;
 
        }
    }




/******************************************************************************/
/***                                                                        ***/
/***  display_info_dbox()                                                   ***/
/***                                                                        ***/
/***  This routine will display a dialogue box containing information       ***/
/***  relating to the program.                                              ***/
/***                                                                        ***/
/***  The definition of this dialogue box can be found in the template file ***/
/***  under the name of "SPinfo".                                           ***/
/***                                                                        ***/
/******************************************************************************/
                                                                   
void display_info_dbox()
        {
        dbox info_dbox_handle;

        if ((info_dbox_handle = dbox_new("SPinfo")) != NULL)
            {
            dbox_setfield(info_dbox_handle, 12, Reg_Number); 
            dbox_setfield(info_dbox_handle, 11, LicenceType); 
            dbox_show(info_dbox_handle);
            dbox_fillin(info_dbox_handle);

            dbox_dispose(&info_dbox_handle);
            }
        else
            {
            werr(FALSE, "Can not display the Information");
            }
        }






/******************************************************************************/
/***                                                                        ***/
/***  calc_triangle_info()                                                  ***/
/***                                                                        ***/
/***  This routine will fill the given triangle structure with a random set ***/
/***  of values. The triangles will always fit into the given window.       ***/
/***                                                                        ***/
/***                                                                        ***/
/******************************************************************************/
                                                                                
void calc_triangle_info(wimp_w win_handle, triangle *tri)
    {
    wimp_winfo window_information;
    int x_size, y_size;

    window_information.w = win_handle;
    wimp_get_wind_info(&window_information);

    x_size = (window_information.info.box.x1 - window_information.info.box.x0 - 16);
    y_size = (window_information.info.box.y1 - window_information.info.box.y0 - 16);
    if (x_size >1000 || x_size<10) x_size = 100;
    if (y_size >1000 || y_size<10) y_size = 100;

    tri ->apex1.x_point = rand() % x_size;
    tri ->apex1.y_point = rand() % y_size;

    tri ->apex2.x_point = rand() % x_size;
    tri ->apex2.y_point = rand() % y_size;

    tri ->apex3.x_point = rand() % x_size;
    tri ->apex3.y_point = rand() % y_size;

    tri ->colour = (rand() % 255) +1;
    }




/******************************************************************************/
/***                                                                        ***/
/***  draw_new_triangle()                                                   ***/
/***                                                                        ***/
/***  This routine will attempt to draw a new triangle, however if the      ***/
/***  window is partly covered only part of the triangle is drawn.          ***/
/***                                                                        ***/
/***                                                                        ***/
/******************************************************************************/

void draw_new_triangle(wimp_w win_handle)
    {
    wimp_redrawstr  redraw_area;
    wimp_winfo window_information;
    triangle        tri;
    BOOL            more = 0;

    calc_triangle_info(win_handle, &tri);

    window_information.w = win_handle;
    wimp_get_wind_info(&window_information);

    redraw_area.w = win_handle;
    redraw_area.box.x0 = 0;
    redraw_area.box.y0 = window_information.info.box.y0 - window_information.info.box.y1;
    redraw_area.box.x1 = window_information.info.box.x1 - window_information.info.box.x0;
    redraw_area.box.y1 = 0;

    wimp_update_wind(&redraw_area, &more);        
    while(more)
        {
        draw_current_triangle(win_handle, &tri);
        wimp_get_rectangle(&redraw_area, &more);
        }   

    }



/******************************************************************************/
/***                                                                        ***/
/***  draw_current_triangle()                                               ***/
/***                                                                        ***/
/***  This routine will redraw all the information in the window.           ***/
/***                                                                        ***/
/***                                                                        ***/
/******************************************************************************/
                                                                                
void draw_current_triangle(wimp_w win_handle, triangle *tri)
    {
    wimp_winfo window_information;
    int x_pos, y_pos;

    window_information.w = win_handle;
    wimp_get_wind_info(&window_information);

    x_pos = window_information.info.box.x0 + 8;
    y_pos = window_information.info.box.y0 + 8;

    bbc_gcol(0, tri ->colour); 
    bbc_move(x_pos + tri ->apex1.x_point, y_pos + tri ->apex1.y_point);
    bbc_move(x_pos + tri ->apex2.x_point, y_pos + tri ->apex2.y_point);
    bbc_plot(85, x_pos + tri ->apex3.x_point, y_pos + tri ->apex3.y_point);
    }




