#include "define.h"
#include <obdefs.h>                /* OBJECT DEFINTIONS              */
#include <gemdefs.h>               /* GEM DEFINITIONS                */
#include <osbind.h>                /* BIOS/GEMDOS/XBIOS FUNCTIONS    */
#include <vdibind.h>               /* VDI DECLERATIONS AND BINDINGS  */
#include <aesbind.h>               /* BINDINGS FOR AES               */
#include "cled.h"                  /* RESOURCE FILE CODES            */
#include "window.h"                /* WINDOW RECORD STRUCTURE        */

extern int hidden;
extern int handle;
extern unsigned char data[3][40];

/****************************************************************************
SUBROUTINE  :  hide/show               VERSION  : 1.0   
AUTHOR      :  ROBERT ALLEY            DATE     :  
DESCRIPTION :  hide or show the mouse pointer
LOGIC USED  :  STEP 1.  If not hidden hide or vice versa.
RETURNS     :  none.
PARAMETERS  :  none.
VARIABLES   :  none.
CONSTANTS   :  none.
REQD. FILES :  None.
REQD. SUBPG.:  none.
NOTES       :  Documented as one to save space.
USAGE       :  hide(); / show();
****************************************************************************/
hide()
   {
   if (!hidden)
      {
      v_hide_c(handle);
      hidden=1;
      }
   }
show()
   {
   if (hidden)
      {
      v_show_c(handle,0);
      hidden=0;
      }
   }

/****************************************************************************
SUBROUTINE  :  check_res               VERSION  : 1.0   
AUTHOR      :  ROBERT ALLEY            DATE     :  
DESCRIPTION :  check the res we are in and abort if not ok
LOGIC USED  :  STEP 1.  Get the current screen res, if not high or medium,
                        form alert box telling user we cant run in other
                        resolutions, exit program.
RETURNS     :  none.
PARAMETERS  :  none.
VARIABLES   :  res         I        Resolution code.
CONSTANTS   :  none.
REQD. FILES :  None.
REQD. SUBPG.:  None.
NOTES       :  None.
USAGE       :  check_res();
****************************************************************************/
check_res()
{
   int res;
 
  res=Getrez();
   if ((res!=2) && (res!=1)) {
      form_alert(1,"[0][This program only  |  works in Hi/MED-res. |   Terminating.   ][OK]");
      exit(1);
   }
}

/****************************************************************************
SUBROUTINE  :  gem_on                  VERSION  : 1.0   
AUTHOR      :  ROBERT ALLEY            DATE     :  
DESCRIPTION :  Start up GEM
LOGIC USED  :  STEP 1.  Get applicvation ID number, open screen as physical
                        workstation.  Open virtual workstation.
RETURNS     :  none.
PARAMETERS  :  nnoe.
VARIABLES   :  none.
CONSTANTS   :  none.
REQD. FILES :  None.
REQD. SUBPG.:  open_vwork
NOTES       :  None.
USAGE       :  gem_on();
****************************************************************************/
gem_on()
{
   extern int gl_wchar,gl_hchar,gl_wbox,gl_hbox;
   extern int phys_handle;
   extern int gl_apid;

   gl_apid=appl_init();
   phys_handle=graf_handle(&gl_wchar,&gl_hchar,&gl_wbox,&gl_hbox);
   open_vwork();

}

/****************************************************************************
SUBROUTINE  :  gem_off                 VERSION  : 1.01
AUTHOR      :  ROBERT ALLEY            DATE     : 31/05/90
DESCRIPTION :  Finish with GEM
LOGIC USED  :  STEP 1.  Close the virtual workstation, exit application.
RETURNS     :  none.
PARAMETERS  :  none.
VARIABLES   :  none.
CONSTANTS   :  none.
REQD. FILES :  None.
REQD. SUBPG.:  none.
NOTES       :  Added () after appl_exit call.
USAGE       :  gem_off();
****************************************************************************/
gem_off()
{
   v_clsvwk(handle);
   appl_exit();
}

/****************************************************************************
SUBROUTINE  :  open_vwork              VERSION  : 1.0   
AUTHOR      :  ROBERT ALLEY            DATE     :  
DESCRIPTION :  Open a virtual workstation
LOGIC USED  :  STEP 1.  Loop through the worksation parameters, initialising
                        them to 1.  Set work_in[10] to 2 (ie. rect. co-ords)
                        Copy physical workstation handle.  Open virtual
                        workstation.
RETURNS     :  none.
PARAMETERS  :  none.
VARIABLES   :  i           I        Loop counter
CONSTANTS   :  none.
REQD. FILES :  None.
REQD. SUBPG.:  none. 
NOTES       :  None.
USAGE       :  open_vwork();
****************************************************************************/
open_vwork()
{

   extern int work_in[11];                 /* Input to GSX parameter array     */
   extern int work_out[57];                /* Output from GSX parameter array  */
   extern int phys_handle;
   
   int i;
   
   for(i=0;i<10;work_in[i++]=1);
   work_in[10]=2;
   handle=phys_handle;
   v_opnvwk(work_in,&handle,work_out);
}

/****************************************************************************
SUBROUTINE  :  open_window             VERSION  : 2.1   
AUTHOR      :  ROBERT ALLEY            DATE     : 28/3/90 
DESCRIPTION :  Open a screen window.
LOGIC USED  :  STEP 1.  If window is allready open send an application 
                        message to top it.  If window isnt yet created
                        create it.  If window was just created or was
                        closed then set the window name.  Draw a growing 
                        box.  Open the window, get the inner co-ordinates. 
RETURNS     :        I     0=window opened, -1=couldnt open.
PARAMETERS  :  wind        *WINDOW  Pointer to window structure.
VARIABLES   :  none.
CONSTANTS   :  none.
REQD. FILES :  None.
REQD. SUBPG.:  None.
NOTES       :  None.
USAGE       :  open_window(&window);
****************************************************************************/
int open_window(wind)
struct WINDOW *wind;
{
   extern int gl_wbox,gl_hbox;
   extern int gl_apid;
   short msg[8];

   
   if (wind->open == 1) {
      msg[0]=WM_TOPPED;
      msg[1]=gl_apid;
      msg[2]=0;
      msg[3]=wind->handle;
      msg[4]=0;
      msg[5]=0;
      msg[6]=0;
      msg[7]=0;
      appl_write( gl_apid, 16, msg);
    }
   if (wind->open == -1) /* If window not yet created, do it */
      wind->handle=wind_create(wind->kind,wind->fullx,wind->fully,wind->fullw,wind->fullh);
   if ( ((wind->open == -1 ) && (wind->handle >= 0)) || (wind->open==0)) {
      wind_set(wind->handle, WF_NAME,wind->title,0,0);
      graf_growbox(wind->outx+wind->outw/2,wind->outy+wind->outh/2,gl_wbox,gl_hbox,wind->outx,wind->outy,wind->outw,wind->outh);
      wind_open(wind->handle,wind->outx,wind->outy,wind->outw,wind->outh);
      wind_get(wind->handle,WF_WORKXYWH,&wind->inx,&wind->iny,&wind->inw,&wind->inh);
      wind->open=1;
   }
   if (wind->handle >= 0) return(0);
   else return(-1);
}

/****************************************************************************
SUBROUTINE  :  plot                    VERSION  : 1.0   
AUTHOR      :  ROBERT ALLEY            DATE     :  
DESCRIPTION :  Draw or erase a graphic box.
LOGIC USED  :  STEP 1.  Hide the mouse, set interior and style types (solid)
                        if mode=1 (ie. draw) set colour to 1, if mode=2 set
                        colour to zero.  Draw a box in given area.  Show the
                        mouse.
RETURNS     :  none.
PARAMETERS  :  mode        I        Mode to draw in, 1=draw, 2=erase
               box         I*4      Co-ords to draw box at.
VARIABLES   :  None.
CONSTANTS   :  None.
REQD. FILES :  None.
REQD. SUBPG.:  None.
NOTES       :  None.
USAGE       :  plot(mode,box);
****************************************************************************/
plot(mode,box)
int mode,box[4];
{
   hide();
   vsf_interior(handle,2);
   vsf_style(handle,8);

   if (mode==1)
      vsf_color(handle,1);
   if (mode==2) 
      vsf_color(handle,0);
   v_bar(handle,box);
   show();
}

/****************************************************************************
SUBROUTINE  :  clear_window            VERSION  : 1.0   
AUTHOR      :  ROBERT ALLEY            DATE     :  
DESCRIPTION :  Clear the given window 
LOGIC USED  :  STEP 1.  Hide the mouse.  Set up drawing mode to solid box in
                        background colour.  Copy window interior co-ords into
                        temp, draw box over window.  Show the mouse.
RETURNS     :  None.
PARAMETERS  :  wind        *WINDOW  Pointer to window structure
VARIABLES   :  temp        I*4      Temp holder for co-ords.
CONSTANTS   :  None.
REQD. FILES :  None.
REQD. SUBPG.:  None. 
NOTES       :  None.
USAGE       :  clear_window(&window_struct);
****************************************************************************/
clear_window(wind)
struct WINDOW *wind;
{
   int temp[4];

   hide();
   vsf_interior(handle,2);
   vsf_style(handle,8);
   vsf_color(handle,0);
   temp[0]=wind->inx;
   temp[1]=wind->iny;
   temp[2]=wind->inx+wind->inw-1;
   temp[3]=wind->iny+wind->inh-1;
   v_bar(handle,temp);
   show();
}

/****************************************************************************
SUBROUTINE  :  load_rsrc               VERSION  : 1.0   
AUTHOR      :  ROBERT ALLEY            DATE     :  
DESCRIPTION :  Load the resource file from disk
LOGIC USED  :  STEP 1.  Load the resource file from disk, if unable to then
                        form an alert, exit program.
RETURNS     :  None.
PARAMETERS  :  None.
VARIABLES   :  None.
CONSTANTS   :  None.
REQD. FILES :  None.
REQD. SUBPG.:  None.
NOTES       :  None.
USAGE       :  load-rsrc(); 
****************************************************************************/
load_rsrc()
{
   if (!rsrc_load("cled.rsc")) {
      form_alert(1, "[0][Cannot find cled.rsc file|Terminating ...][OK]");
      exit(1);
   }
}

/****************************************************************************
SUBROUTINE  :  do_dialog               VERSION  : 1.0   
AUTHOR      :  ROBERT ALLEY            DATE     :  
DESCRIPTION :  form and handle a dialog
LOGIC USED  :  STEP 1.  Get co-ords of centred dialog, reserve space for
                        dialog, draw it, handle input, remove dialog and
                        free up space.
RETURNS     :  None.
PARAMETERS  :  dialog      *OBJECT  Pointer to dialog to form
VARIABLES   :  cx-h        I        Centred co-ords.
CONSTANTS   :  None.
REQD. FILES :  None.
REQD. SUBPG.:  None.
NOTES       :  None.
USAGE       :  do_dialog(&ialog);
****************************************************************************/
do_dialog(dialog)
   OBJECT *dialog;
{
   int cx, cy, cw, ch;

   form_center(dialog, &cx, &cy, &cw, &ch);
   form_dial(FMD_START, 0,0,0,0,cx, cy, cw, ch);
   objc_draw(dialog, 0, 10, cx, cy, cw, ch);
   form_do(dialog, 0);
   form_dial(FMD_FINISH, 0,0,0,0,cx, cy, cw, ch);
}

/****************************************************************************
SUBROUTINE  :  scrollv                 VERSION  : 1.0   
AUTHOR      :  ROBERT ALLEY            DATE     : 24/3/90
DESCRIPTION :  Vertically scroll contents of graphic window.
LOGIC USED  :  STEP 1.
RETURNS     :  none.
PARAMETERS  :  wind        &WINDOW   Pointer to window structure of graph 
                                     window
               dir         I         Direction to scroll, 1=down, 2=up
VARIABLES   :  la,lb       I         Loop counters
               last        SI*3*40   Array to hold bits that are rolled over.
CONSTANTS   :  None.
REQD. FILES :  None.
REQD. SUBPG.:  send_redraw
NOTES       :  None.
USAGE       :  scrollv(WINDOW *,int);
****************************************************************************/
scrollv(wind,dir)
struct WINDOW *wind;
int dir;
{
   int la,lb;
   short int last[3][40];

   if (dir==1) {
      for (la=0;la<40;la++) {
         if ((data[2][la]& 1)!=0) last[0][la]=128; 
         else last[0][la]=0;
         if ((data[1][la]& 1)!=0) last[2][la]=128; 
         else last[2][la]=0;
         if ((data[0][la]& 1)!=0) last[1][la]=128; 
         else last[1][la]=0;
      }
   }
   else {
      for (la=0;la<40;la++) {
         if ((data[2][la]& 128)!=0) last[1][la]=1; 
         else last[1][la]=0;
         if ((data[1][la]& 128)!=0) last[0][la]=1; 
         else last[0][la]=0;
         if ((data[0][la]& 128)!=0) last[2][la]=1; 
         else last[2][la]=0;
      }
   }

   for (la=0;la<3;la++)
      for (lb=0;lb<40;lb++) {
         if (dir==1) data[la][lb]/=2;
         else data[la][lb]*=2;
         data[la][lb]|=last[la][lb];
      }
   send_redraw(wind);
}

/****************************************************************************
SUBROUTINE  :  scrollh                 VERSION  : 1.0   
AUTHOR      :  ROBERT ALLEY            DATE     : 24/03/90
DESCRIPTION :  Scroll contents of graphic window horizontally
LOGIC USED  :  STEP 1.
RETURNS     :  none.
PARAMETERS  :  wind        &WINDOW   Pointer to window structure of graph 
                                     window
               dir         I         Direction to scroll, 1=right, 2=left
VARIABLES   :  la,lb       I         Loop counters
               temp        I         Holds bytes that are rolled over.
CONSTANTS   :  None.
REQD. FILES :  None.
REQD. SUBPG.:  send_redraw
NOTES       :  None.
USAGE       :  scrollh(WINDOW *,int);
****************************************************************************/
scrollh(wind,dir)
struct WINDOW *wind;
int dir;
{
   int la,lb;
   int temp;

   if (dir==1) {
      for (la=0;la<3;la++) {
         for (lb=39;lb>0;lb--) {
            if (lb==39) temp=data[la][lb];
            data[la][lb]=data[la][lb-1];
         }
         data[la][0]=temp;
      }
   }
   else {
      for (la=0;la<3;la++) {
         for (lb=0;lb<39;lb++) {
            if (lb==0) temp=data[la][lb];
            data[la][lb]=data[la][lb+1];
         }
         data[la][39]=temp;
      }
   }
   send_redraw(wind);
}

mirror(wind)
struct WINDOW *wind;
{
   int temp;
   int row,col;

   for (row=0;row<3;row++)
      for (col=0;col<20;col++) {
         temp=data[row][col];
         data[row][col]=data[row][39-col];
         data[row][39-col]=temp;
      }
   send_redraw(wind);
}

/****************************************************************************
SUBROUTINE  :  send_redraw             VERSION  : 1.0
AUTHOR      :  ROBERT ALLEY            DATE     : 24/03/90
DESCRIPTION :  Send a redraw message for the given window
LOGIC USED  :  STEP 1.  Put redraw code, application ID no., 0 (indicates
                        message is standard 16 bytes), window handle and
                        window dimension in message array.  Send message
                        to application.
RETURNS     :  none.
PARAMETERS  :  wind        &WINDOW  Pointer to window struct of window to
                                    redraw.
VARIABLES   :  msg         I*8      Message buffer array.
CONSTANTS   :  None.
REQD. FILES :  None.
REQD. SUBPG.:  None.
NOTES       :  None.
USAGE       :  send_redraw(&WINDOW);
****************************************************************************/
send_redraw(wind)
struct WINDOW *wind;
{
   extern int gl_apid;

   short msg[8];

   msg[0]=WM_REDRAW;
   msg[1]=gl_apid;
   msg[2]=0;
   msg[3]=wind->handle;
   msg[4]=wind->inx;
   msg[5]=wind->iny;
   msg[6]=wind->inw;
   msg[7]=wind->inh;
   appl_write( gl_apid, 16, msg);
}

