/*
 * Name   : 3DWorkRnd
 * Desc   : A small WIMP program to show how to work
 *          around the 3D slabbed icon fault in RISC OS
 *          3.10
 * Author : James Bye, Acorn Technical Support
 * Date   : 29th September 1992
 *
 *
 *
 * **********************************************
 * * Disclaimer                                 *
 * * ----------                                 *
 * *                                            *
 * * The software is provided "as is" Acorn     *
 * * Computers Limited ("Acorn") makes no       *
 * * warranty, express or implied, of the       *
 * * merchantability of this software or its    *
 * * fitness for any particular purpose. In no  *
 * * circumstances shall Acorn be liable for any*
 * * damage, loss of profits, or any indirect or*
 * * consequential loss arising out of the use  *
 * * of this software or inability to use this  *
 * * software, even if Acorn has been advised of*
 * * the possibility of such loss.              *
 * **********************************************
 *
 */

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

#include "wimp.h"
#include "wimpt.h"
#include "win.h"
#include "event.h"
#include "baricon.h"
#include "res.h"
#include "resspr.h"
#include "menu.h"
#include "template.h"
#include "dbox.h"
#include "werr.h" 
#include "visdelay.h"
#include "saveas.h"
#include "bbc.h"
#include "swis.h"

/************************************************************
 * Definitions and static variables                         *
 ************************************************************/

#define i_MyWindow_DragButton  2
#define i_MyWindow_Quit        3

static wimp_w my_window;

                                                     
/************************************************************
 * Static functions                                         *
 ************************************************************/


/*
 * process unknown events 
 */

static BOOL unknown_event_processor ( wimp_eventstr *e, void *handle )
{                         
wimp_mousestr m;

  handle = handle;

  /*-- check for desired event and then process them --*/

  switch(e->e)
  {
    case wimp_EUSERDRAG : /*-- the user has released the mouse button after --*/
                          /*-- the drag                                     --*/

                          wimpt_complain(wimp_get_point_info(&m));
                          werr(0,"Drag finished (window handle = %d icon handle = %d",
                                        m.w,m.i);

                          /*-- let RISC_OSLib know we have processed this event --*/

                          return(TRUE);
                          break;
  }
 
  /*-- if we were not interested in the event then we have --*/
  /*-- inform RISC_OSLib that we haven't                   --*/

  return(FALSE);
}



/*
 * process button events from the window
 */

static void process_button_events ( wimp_mousestr m, wimp_bbits bbits )
{                                                                    
  /*-- check that only the desired icon has been pressed --*/

  if(m.i == i_MyWindow_DragButton)
  {
    wimp_dragstr dr;
    wimp_wstate  state;
    wimp_icon icon;
    wimp_w w = my_window;
    int x_limit,y_limit,screen_x0,screen_y0,mouse_x,mouse_y,x0,y0,x1,y1;

      /*-- calculate screen limits --*/

      x_limit = bbc_vduvar(bbc_XWindLimit) << bbc_vduvar(bbc_XEigFactor);
      y_limit = bbc_vduvar(bbc_YWindLimit) << bbc_vduvar(bbc_YEigFactor);

      /*-- store pointer position --*/

      mouse_x = m.x;
      mouse_y = m.y;

      /*-- get the screen origin --*/

      wimpt_complain(wimp_get_wind_state(w,&state));
      screen_x0 = state.o.box.x0 - state.o.x;
      screen_y0 = state.o.box.y1 - state.o.y;

      /*-- get initial icon position --*/
                           
      wimpt_complain(wimp_get_icon_info(w,m.i,&icon));
      x0 = screen_x0 + icon.box.x0;
      x1 = screen_x0 + icon.box.x1;
      y0 = screen_y0 + icon.box.y0;
      y1 = screen_y0 + icon.box.y1;

      /*-- set up the drag boxes --*/

      dr.window = w;
      dr.type   = wimp_USER_FIXED; /*-- we want a fixed box drag --*/
      dr.box.x0 = x0;
      dr.box.y0 = y0;
      dr.box.x1 = x1;
      dr.box.y1 = y1;
      dr.parent.x0 = x0 - mouse_x;
      dr.parent.y0 = y0 - mouse_y;
      dr.parent.x1 = x1 - mouse_x + x_limit; 
      dr.parent.y1 = y1 - mouse_y + y_limit;

      /*-- start the drag --*/

      wimpt_complain(wimp_drag_box(&dr));

      /*-- attach an unknown event processor so that we can catch --*/
      /*-- the drag when it finishes                              --*/

      win_add_unknown_event_processor(unknown_event_processor,NULL);
  }                             
  else
  { /*-- this is the bit that we need to workaround --*/
                                      

    if(m.i == i_MyWindow_Quit) /*-- was quit button hit --*/
    {
      _kernel_swi_regs r;
      event_setmask(0); /*-- set event mask to 0                 --*/
      do /*-- read mouse state until buttons are released --*/
      {
        _kernel_swi(OS_Mouse,&r,&r);
        event_process();  /*-- give wimp chance to sort itself out --*/
      } while(r.r[2] != 0);
      exit(0); /*-- we can now exit safely!!! --*/      
    }
  }
}



/*
 * event handler for the window
 */

static void  window_events ( wimp_eventstr *e, void *handle )
{
  handle = handle;

  /*-- check the wimp event and proccess it if neccessary --*/

  switch(e->e)
  {
     case wimp_EREDRAW  :  /*-- our window is 'auto-redraw' so ignore --*/
                           break;                  
     case wimp_ECLOSE   :  /*-- the end is here !! --*/
                           wimpt_complain(wimp_close_wind(e->data.o.w));
                           win_activedec();
                           break;             
     case wimp_EOPEN    :  /*-- open the window --*/
                           wimpt_complain(wimp_open_wind(&e->data.o));
                           break;                   
     case wimp_EBUT     :  /*-- process button events --*/
                           process_button_events(e->data.but.m,e->data.but.b);
                           break;   
     default            :  break;
  }
}



/************************************************************
 * External functions                                       *
 ************************************************************/

/* 
 * the main C function
 * (inits the wimp, creates menus and dbox's etc....)
 */

int main ( void )     
{                     
wimp_wind *wind;
wimp_wstate state;


  /*-- init ourselves with the wimp etc... --*/

  wimpt_init("3dWorkRnd");
  res_init("3dWorkRnd");
  resspr_init();
  template_init();    
  win_activeinc();

  /*-- create and open the window --*/

  wind = template_syshandle("window");                  /*-- get our window definition --*/
  wimpt_complain(wimp_create_wind(wind,&my_window));    /*-- create the window         --*/
  wimpt_complain(wimp_get_wind_state(my_window,&state));/*-- get the state             --*/
  wimpt_complain(wimp_open_wind(&state.o));             /*-- open the window           --*/

  /*-- register an event handler for the window --*/

  win_register_event_handler(my_window,window_events,NULL);

  /*-- loop on events forever...... --*/

  while(TRUE)
   event_process();
 
  return(0);
}

/*-- end of source --*/
