home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 3 Comm / 03-Comm.zip / CKPM5X_S.ZIP / CKOPM2.C < prev    next >
C/C++ Source or Header  |  1990-05-18  |  63KB  |  1,988 lines

  1. /******************************************************************************
  2. File name:  ckopm2.c     Rev: 01  Date: 07-Dec-89 Programmer: C.P.Armstrong
  3.  
  4. File title: Functions called from the PM thread
  5.  
  6. Contents:   
  7.  
  8. Modification History:
  9.     01  07-Dec-89   C.P.Armstrong   created
  10.     02  29-Jan-90   C.P.Armstrong   Various mods to the pc functions. 
  11.                                     Inter-thread AVIO functions moved to this 
  12.                                     file to ease ckopm1 compiling.
  13.     03  11-Feb-90   C.P.Armstrong   More functionality added to the pc_ 
  14.                                     functions.
  15.     04  12-Feb-90   C.P.Armstrong   killpm() changed
  16. ******************************************************************************/
  17. #define INCL_DOS
  18. #define INCL_WIN
  19. #define INCL_GPI    
  20. #define INCL_AVIO
  21. #define INCL_VIO
  22. #include <OS2.h>
  23. #include <string.h>
  24. #include <stdio.h>
  25. #include <stdarg.h>
  26. #include <malloc.h>
  27. #include "ckopm.h"
  28. #include "ckotek.h"
  29. #include "ckokey.h"
  30.  
  31. #define LBSZ 81
  32. #define KEYBUFFERSIZE        128
  33.  
  34.  
  35. //unsigned char linebuf[LBSZ];
  36.  
  37.  
  38. /* Keyboard buffering variables */
  39. int keybuffer[KEYBUFFERSIZE];  /* The buffer for the key presses */
  40. int keybuffer_size=KEYBUFFERSIZE;   /* The buffer size */
  41. int far next_put_pos=0;        /* Offset of next character into buffer */
  42. int far next_get_pos=0;        /* Offset of next character from buffer */
  43. ULONG far kbdovr_sem=0;       /* Keyboard buffer is in overflow condition */
  44.  
  45.  
  46. void Tek_ginencode();
  47. int get_paste_char(void);
  48.  
  49. /******************************************************************************
  50. Function:       clrgwind()
  51.  
  52. Description:    Clears the graphics window
  53.  
  54. Syntax:         void clrgwind()
  55.  
  56. Returns:        nothing
  57.  
  58. Mods:           30-Nov-89 C.P.Armstrong created
  59.  
  60. ******************************************************************************/
  61. void clrgwind()
  62.     {
  63.     extern HWND hwndGraph;
  64.     
  65.     WinPostMsg(hwndGraph,WM_USER,MPFROM2SHORT(0,0),MPFROMCHAR('c'));
  66.     }
  67.  
  68.  
  69. ///******************************************************************************
  70. //Function:       vWndSize()
  71. //
  72. //Description:    Provides access to the Vio screen size params for functions
  73. //                which can't get at them directly (i.e. compiled with FORTRAN
  74. //                conventions etc.).  The size is in number of Vio characters.
  75. //
  76. //Syntax:         vWndSize(width,height)
  77. //                    int * width;  # of columns
  78. //                    int * height; # of rows.
  79. //
  80. //Returns:        nothing
  81. //
  82. //Mods:           28-Nov-89 C.P.Armstrong created
  83. //
  84. //******************************************************************************/
  85. //
  86. //void vWndSize(width,height)
  87. //    int * width;  /* # of columns */
  88. //    int * height; /* # of rows. */
  89. //    {
  90. //    extern int scrwidth;
  91. //    extern int scrheight;
  92. //    
  93. //    *width = scrwidth;
  94. //    *height = scrheight;
  95. //    
  96. //    return;
  97. //    }
  98. //
  99. /******************************************************************************
  100. Function:       killpm()
  101.  
  102. Description:    Shuts down the PM message queue thread.  If this thread does
  103.                 not shut down the whole program after 5s then killpm() does
  104.                 it.  
  105.  
  106. Syntax:         void killpm()
  107.  
  108. Returns:        nothing
  109.  
  110. Mods:           28-Nov-89 C.P.Armstrong created
  111.                 12-Feb-90 C.P.Armstrong modified for use with kermit.  Does not
  112.                                         wait after sending the kill message.
  113.                                         The PM thread is modified to kill only
  114.                                         it's thread.
  115.                 25-Feb-90 C.P.Armstrong Function waits for the PM thread to die
  116.                                         before returning.
  117.  
  118. ******************************************************************************/
  119. void killpm()
  120.     {
  121.     extern HWND cdecl hwndTFrame;
  122.     extern ULONG pm_die_sem;
  123.  
  124.     if(DosSemSet(&pm_die_sem)==0) /* This fails the PM thread has  */
  125.         {                         /* already started to exit       */
  126.         WinPostMsg(hwndTFrame,WM_DESTROY,MPFROM2SHORT(0,0),MPFROM2SHORT(0,0));
  127.         WinPostMsg(hwndTFrame,WM_QUIT   ,MPFROM2SHORT(0,0),MPFROM2SHORT(0,0));
  128.         DosSemWait(&pm_die_sem,5000L);
  129.         }
  130.     }
  131.  
  132. /******************************************************************************
  133. Function:       pltnow()
  134.  
  135. Description:    Changes the flag used to cause immediate update of the screen
  136.                 on sending a point to be plotted.
  137.                 Set value to 1 for immediate updating, 0 if the update can
  138.                 wait until a whole load of points have been sent.
  139.                 
  140.                 Manet as a convenient interface for FORTRAN programs. 
  141.  
  142. Syntax:         void fortran pltnow( value );
  143.                     int * value;  To update or not
  144.  
  145. Returns:        nothing
  146.  
  147. Mods:           30-Nov-89 C.P.Armstrong
  148.  
  149. ******************************************************************************/
  150.  
  151. void fortran pltnow( value )
  152.     int * value;  /* To update or not */
  153.     {
  154.     extern char cdecl immediate_update;
  155.  
  156.     immediate_update= (char) *value;
  157.     }
  158.  
  159. /******************************************************************************
  160. Function:       pm_err()
  161.  
  162. Description:    Displays a message box containing a string indicating the
  163.                 nature of the error.
  164.  
  165. Syntax:         void pm_msg(title,message)
  166.                     char * message;  Text to display in box;
  167.  
  168. Returns:        nothing
  169.  
  170. Mods:           05-Dec-89 C.P.Armstrong created
  171.  
  172. ******************************************************************************/
  173.  
  174. void pm_msg(title,message)
  175.     char * title;
  176.     char * message;  /* Text to display in box; */
  177.     {
  178.     USHORT idWin;
  179.     USHORT flst;
  180.     HWND cur_wind;
  181.  
  182.     flst = MB_OK|MB_ICONEXCLAMATION;
  183.     cur_wind = WinQueryActiveWindow(HWND_DESKTOP, FALSE);
  184.     WinMessageBox(HWND_DESKTOP, cur_wind, message, title,0,flst);
  185.     
  186.     return;
  187.     }
  188.  
  189. void pm_err(message)
  190.     char * message;
  191.     {
  192.     pm_msg("Error!!",message);
  193.     }
  194.  
  195. /******************************************************************************
  196. Function:       dbprintf()
  197.  
  198. Description:    Prints a window message box containing debugging information.
  199.                 This must only be called from the PM thread.
  200.  
  201. Syntax:         void dbprintf(format,...)
  202.                     const char *;  Format string
  203.  
  204. Returns:        nothing
  205.  
  206. Mods:           06-Dec-89 C.P.Armstrong created
  207.  
  208. ******************************************************************************/
  209. void dbprintf(format,...)
  210.     const char * format;  /* Format string */
  211.     {
  212.     extern char debugmsg;
  213.     va_list varg_ptr;
  214.     char * bufp;  /* Buffer for the formatted string */
  215.     static FILE * dbh;
  216.  
  217. //    return;
  218.  
  219.     va_start(varg_ptr,format);   /* Get start of optional argument list*/    
  220.                        
  221.  
  222.     if((bufp = (char *) malloc(512))==NULL) 
  223.         {
  224.         pm_err("I think you are running out of memory");
  225.         return;
  226.         }
  227.         
  228.     vsprintf(bufp, format, varg_ptr);
  229.     if(debugmsg<1)
  230.         {
  231.         if(dbh==NULL)
  232.             dbh = fopen("debug","w");
  233.         fprintf(dbh,"%s",bufp);
  234.         fflush(dbh);
  235.         }
  236.     else
  237.         pm_msg("Debug Info",bufp);
  238.     
  239.     free(bufp);
  240.     return;
  241.     }
  242.  
  243.  
  244.  
  245. /******************************************************************************
  246. Function:       pc_interp()
  247.  
  248. Description:    Interprets the plot commands sent from the main thread to the
  249.                 PM thread.
  250.  
  251. Syntax:         void pc_interp(pc,swp,mode,hps)
  252.                     struct plot_command pc;  The plot command to interpret
  253.                     PSWP swp;                Dimension and coords of window to 
  254.                                              plot in
  255.                     char mode;               0 text, 1 no text
  256.                     HPS hps;                 Handle to the PS.
  257.  
  258. Returns:        nothing
  259.  
  260. Mods:           13-Dec-89 C.P.Armstrong created
  261.                 12-Jan-90 C.P.Armstrong Function must now be passed a pointer
  262.                                         to an SWP structure.  For some reason 
  263.                                         passing structures does not work in with
  264.                                         IDA - it works with Kermit. Perhaps a
  265.                                         problem with mixed languages.
  266.                 14-Jan-90 C.P.Armstrong Poly line support added.  Uses ptl.x
  267.                                         to store the pointer to an array of
  268.                                         POINTLs.
  269.                 11-Feb-90 C.P.Armstrong Point plot mode and set line type added.
  270. ******************************************************************************/
  271. void pc_interp(pc,swp,mode,hps)
  272.     struct plot_command pc;  /* The plot command to interpret */
  273.     PSWP swp;                /* Dimension and coords of window to plot in */
  274.     char mode;  
  275.     HPS hps;                 /* Handle to the PS. */
  276.     {
  277.     POINTL ptl;
  278.     PPOINTL ptlc;
  279.     PPOINTL ptlo;
  280.     char far * pso;
  281.     int i;
  282.  
  283.     switch(pc.c)
  284.         {
  285.         case 'm':       /* Means do a move */
  286.             ptl.x = pc.ptl.x * swp->cx / MAXXRES;
  287.             ptl.y = pc.ptl.y * swp->cy / MAXYRES;
  288.             GpiMove(hps, &ptl);
  289.             break;
  290.         case 'd':
  291.             ptl.x = pc.ptl.x * swp->cx / MAXXRES;
  292.             ptl.y = pc.ptl.y * swp->cy / MAXYRES;
  293.             GpiLine(hps,&ptl);
  294.             break;
  295.         case 'p':
  296.             ptl.x = pc.ptl.x * swp->cx / MAXXRES;
  297.             ptl.y = pc.ptl.y * swp->cy / MAXYRES;
  298.             GpiMarker(hps,&ptl);
  299.             break;
  300.         case 'l':
  301.             GpiSetLineType(hps,ptl.x);
  302.             break;
  303.         case 's':
  304.             if(mode<1)
  305.                 {
  306.                 pso = (char far *) pc.ptl.x;
  307.                 GpiCharString(hps, (long) strlen(pso),pso);
  308.                 }
  309.             break;
  310.  
  311.         case 'y':  /* Polyline drawing mode */
  312.             /* Allocate memory for scaled copy of array */
  313.             ptlc = (PPOINTL) malloc(sizeof(POINTL)*(int)pc.ptl.y);
  314.             ptlo = (PPOINTL) pc.ptl.x;
  315.             
  316.             /* fill copy with scaled values */
  317.             for(i=0;i< (int)pc.ptl.y;i++)
  318.                 {
  319.                 ptlc[i].x = ptlo[i].x * swp->cx / MAXXRES;
  320.                 ptlc[i].y = ptlo[i].y * swp->cy / MAXYRES;
  321.                 }
  322.  
  323.             GpiPolyLine(hps,pc.ptl.y,ptlc);
  324.             free(ptlc);
  325.             break;
  326.         default:
  327.             break;
  328.         }
  329.     return;
  330.     }
  331.  
  332.  
  333. /******************************************************************************
  334. Function:       pc_delete()
  335.  
  336. Description:    Deletes the plot command linked lists starting from the 
  337.                 root command - freeing any reserved string space on the way.
  338.  
  339. Syntax:         void pc_delete(pctop)
  340.                     struct plot_command * pctop; First item in linked list
  341.  
  342. Returns:        nothing
  343.  
  344. Mods:           13-Dec-89 C.P.Armstrong created
  345.                 14-Jan-90 C.P.Armstrong Polyline support added
  346.  
  347. ******************************************************************************/
  348.  
  349. void pc_delete(pctop)
  350.     struct plot_command * pctop; /* First item in linked list */
  351.     {
  352.     struct plot_command * pcc;
  353.     struct plot_command * pclast;
  354.  
  355.     pcc = pctop;
  356.     do
  357.         {
  358.         /* Free any string space first */
  359.         if(pcc->c=='s' || pcc->c=='y')
  360.             free( (void *) (pcc->ptl.x) );
  361.         
  362.         pclast=pcc;              /* Record current address */
  363.         pcc = pcc->next;         /* Point to the next command */
  364.         
  365.         if(pclast!=pctop)        /* Delete previous command if not the root */
  366.             free( (void far *) pclast);
  367.         }
  368.     while(pcc!=NULL);
  369.     
  370.     /* Reset pctop values to start values */
  371.     pctop->c='\0';
  372.     pctop->next=NULL;
  373.  
  374.     return;
  375.     }
  376.  
  377.  
  378. /******************************************************************************
  379. Function:       pc_save()
  380.  
  381. Description:    Adds a new plot command to the linked list of plot commands
  382.  
  383. Syntax:         struct plot_command * pc_save( pc,mp1,mp2 )
  384.                     struct plot_command pc;  current last plot command in list
  385.                     MPARAM mp1;     Parameter 1 as passed to window routine
  386.                     MPARAM mp2;     Parameter 2 as passed to window routine
  387.  
  388. Returns:        pointer to the new plot command.
  389.  
  390. Mods:           14-Jan-90 C.P.Armstrong created
  391.                 11-Feb-90 C.P.Armstrong Handling for plotting and setting line
  392.                                         types
  393.  
  394. ******************************************************************************/
  395.  
  396. struct plot_command * pc_save( pcurrent,mp1,mp2 )
  397.     struct plot_command * pcurrent;  /* current last plot command in list */
  398.     MPARAM mp1;     /* Parameter 1 as passed to window routine */
  399.     MPARAM mp2;     /* Parameter 2 as passed to window routine */
  400.     {
  401.     struct plot_command * pcold;
  402.     char far * psi;                 /* pointer to a string from mp */
  403.     char new_command=0;
  404.     char c;
  405.     
  406.     c = CHAR1FROMMP(mp2);
  407.  
  408.     /* Allocate space for a new plot command */
  409.     pcold = pcurrent;
  410.     if((pcurrent->next==NULL) && (c!='\0'))  /* Check it's not the first in */ 
  411.         {                                    /* list */
  412.         pcurrent->next = 
  413.             (struct plot_command *) malloc(sizeof(struct plot_command));
  414.         pcurrent=pcurrent->next;
  415.         pcurrent->next=NULL;
  416.         new_command=1;
  417.         }
  418.  
  419.     /* pcurrent is new command unless it's the first entry in the list */
  420.     /* which does not need to be allocated as it is always present.    */
  421.     pcurrent->c = c;
  422.  
  423.     switch(c)
  424.         {
  425.         case 's':
  426.             /* Make up the pointer to the string */
  427.             psi = (char far *) PVOIDFROMMP(mp1);     
  428.  
  429.             /* Store string */
  430.             pcurrent->ptl.x = (LONG) malloc(strlen(psi)+1);  
  431.             strcpy((char*)pcurrent->ptl.x, psi);
  432.             break;
  433.         case 'y':
  434.             /* make up the pointer to the pointl structure */
  435.             /* This assumes that the function building the POINTL array */
  436.             /* will not destroy it.  Only pc_delete should free the     */
  437.             /* memory allocated for the array.                          */
  438.             pcurrent->ptl.x = (ULONG) PVOIDFROMMP(mp1);
  439.             /* Save the number of POINTLs */
  440.             pcurrent->ptl.y = (ULONG) SHORT2FROMMP(mp2);
  441.             break;
  442.  
  443.         case 'm':
  444.         case 'd':
  445.         case 'p':
  446.             pcurrent->ptl.x = (LONG) SHORT1FROMMP(mp1);
  447.             pcurrent->ptl.y = (LONG) SHORT2FROMMP(mp1);
  448.             break;
  449.         case 'l':
  450.             pcurrent->ptl.x = LONGFROMMP(mp1);
  451.             break;
  452.         default:
  453.             /* If it's not one of those we'd better get rid of it! */
  454.             /* but only if it's a new command */
  455.             if(new_command)
  456.                 {
  457.                 free(pcurrent);
  458.                 pcurrent=pcold;
  459.                 }
  460.             break;
  461.         }
  462.      
  463.     return(pcurrent);
  464.     }
  465.  
  466. /* This GIN mode handling routines come next */
  467.  
  468. ULONG gin_wait_sem=0;
  469. ULONG gin_received_sem=0;
  470. CHAR  gin_mode=0;
  471.  
  472. LONG mouse_adj_xpos;
  473. LONG mouse_adj_ypos;
  474. CHAR gin_c;
  475. /******************************************************************************
  476. Function:       SetPMGinMode()
  477.  
  478. Description:    Puts the GPI window into graphic inupt mode a la Tektronix
  479.  
  480. Syntax:         void SetPMGinMode(hwnd,mode)
  481.                     HWND hwnd;    Handle to window
  482.                     MPARAM mode;  Open or close GIN mode
  483.  
  484. Returns:        nothing
  485.  
  486. Mods:           26-Jan-90 C.P.Armstrong created
  487.  
  488. ******************************************************************************/
  489. void SetPMGinMode(hwnd,mode,hptr)
  490.     HWND hwnd;    /* Handle to window */
  491.     MPARAM mode;  /* Open or close GIN mode */
  492.     HPOINTER hptr;
  493.     {
  494.     extern CHAR gin_mode;
  495.     
  496.     if(mode==(MPARAM)1)     /* Enter GIN mode */
  497.         {
  498.         /* Change pointer to a cross */
  499.         WinSetPointer(HWND_DESKTOP, hptr);
  500.         gin_mode=1;
  501.         }
  502.     else
  503.         {
  504.         /* Change pointer back to normal */
  505.         WinSetPointer(HWND_DESKTOP, WinQuerySysPointer(HWND_DESKTOP,SPTR_ARROW,
  506.                 FALSE));
  507.         gin_mode=0;
  508.         }
  509.     }
  510.                     
  511. /******************************************************************************
  512. Function:       DoPMTekGin()
  513.  
  514. Description:    Sends the coordinates of the mouse when a button was pressed
  515.                 to the waiting thread - if GIN mode has been selected.
  516.                 The coords returned are scaled up to those used by
  517.                 the plot routines in the thread.
  518.                 
  519.                 The mouse coords are scaled and then converted to Tektronix
  520.                 values. A string consisting of the coords, the character pressed
  521.                 and the GIN terminator are then inserted into the inter thread 
  522.                 keyboard buffer.  
  523.  
  524. Syntax:         int DoPMTekGin(hwnd, pmsg)
  525.                     HWND hwnd;   Window handle
  526.                     USHORT * pmsg;   Message sent to window (contains mouse coords).
  527.  
  528. Returns:        1 if we were in GIN mode
  529.                 0 if not in GIN mode.
  530.  
  531. Mods:           01-Feb-90 C.P.Armstrong Based on DoPMGin, no semaphores, string
  532.                                         inserted into keyboard buffer etc.
  533. ******************************************************************************/
  534. int DoPMTekGin(hwnd, pmsg)
  535.     HWND hwnd;      /* Window handle */
  536.     USHORT* pmsg;   /* Message sent to window (contains mouse coords). */
  537.     {
  538.     extern CHAR  gin_mode;
  539.     extern LONG mouse_adj_xpos;
  540.     extern LONG mouse_adj_ypos; 
  541.     extern CHAR gin_c;
  542.     extern char gin_terminator;
  543.     extern char mouse_but1;
  544.     extern char mouse_but2;
  545.     extern char mouse_but3;
  546.  
  547.     
  548.     SWP swp;
  549.     POINTL pointerpos;
  550.     char ginbuf[7];
  551.  
  552.     if(gin_mode!=1)
  553.         return(0);
  554.     
  555.     if(*pmsg==WM_CHAR)
  556.         {
  557.         WinQueryPointerPos(HWND_DESKTOP,&pointerpos);
  558.         WinMapWindowPoints(HWND_DESKTOP,hwnd,&pointerpos,1);
  559.         mouse_adj_xpos = pointerpos.x;
  560.         mouse_adj_ypos = pointerpos.y;
  561.         gin_c = (CHAR) CHARMSG(pmsg)->chr;
  562.         }
  563.      else
  564.         {
  565.         /* Get the window position of the mouse */
  566.         mouse_adj_xpos = MOUSEMSG(pmsg)->x;
  567.         mouse_adj_ypos = MOUSEMSG(pmsg)->y;
  568.         /* On our Vax sending a non character, VK_BUTTON1, screws things up */
  569.         switch(*pmsg)
  570.             {
  571.             case WM_BUTTON1DOWN: gin_c = mouse_but1; break;
  572.             case WM_BUTTON2DOWN: gin_c = mouse_but2; break;
  573.             case WM_BUTTON3DOWN: gin_c = mouse_but3; break;
  574.             default:        gin_c = ' ';
  575.             }
  576.         }
  577.  
  578.     /* Get the window size */
  579.     WinQueryWindowPos(hwnd,&swp);    
  580.  
  581.     /* Scale up the mouse position */
  582.     mouse_adj_xpos = mouse_adj_xpos * MAXXRES / swp.cx ;
  583.     mouse_adj_ypos = mouse_adj_ypos * MAXYRES / swp.cy ;
  584.  
  585.     /* Build the Tek cursor address string */
  586.     Tek_ginencode((int)mouse_adj_xpos,(int)mouse_adj_ypos,gin_c,
  587.         gin_terminator,ginbuf);
  588.     
  589.     /* Insert it into the buffer */
  590.     buff_strins(ginbuf);
  591.  
  592.     return(1);
  593.     }
  594.     
  595.     
  596. /******************************************************************************
  597. Function:       TestPMGinMode()
  598.  
  599. Description:    Test to see if GINmode is selected or not.
  600.  
  601. Syntax:         BOOL TestPMGinMode()
  602.  
  603. Returns:        1 if in GIN mode
  604.                 0 if in "normal" mode
  605.  
  606. Mods:           27-Jan-90 C.P.Armstrong created
  607.  
  608. ******************************************************************************/
  609. BOOL TestPMGinMode()
  610.     {
  611.     extern CHAR  gin_mode;
  612.     return( gin_mode );
  613.     }
  614.     
  615. /******************************************************************************
  616. Function:       SetGinMode()
  617.  
  618. Description:    This is used by the none PM thread to enable/disable the 
  619.                 graphic input mode.
  620.  
  621. Syntax:         void SetGinMode(hwnd,mode)
  622.                     HWND hwnd;  WIndow handling the GIN
  623.                     int  mode;  Enable=1/disable=0 GIN mode
  624.  
  625. Returns:        nothing
  626.  
  627. Mods:           29-Jan-90 C.P.Armstrong created
  628.  
  629. ******************************************************************************/
  630. void SetGinMode(hwnd,mode)
  631.     HWND hwnd;  /* Window handling GIN mode */
  632.     int  mode;
  633.     {
  634.     WinPostMsg(hwnd,WM_GIN,(MPARAM)mode,0);
  635.     return;
  636.     }
  637.  
  638. /******************************************************************************
  639. Function:       GetGinCoords()
  640.  
  641. Description:    Gets GIN information for the non PM thread.  GIN mode input
  642.                 is terminated if the user presses a mouse button or the 
  643.                 keyboard.
  644.  
  645. Syntax:         void GetGinCoords(xpos,ypos,ch)
  646.                     int* xpos;      Adjusted X pos of cursor
  647.                     int* ypos;      Adjusted Y position
  648.                     char* ch;       Character pressed to terminate input
  649.  
  650. Returns:        nothing
  651.  
  652. Mods:           29-Jan-90 C.P.Armstrong created
  653.  
  654. ******************************************************************************/
  655. void cdecl GetGinCoords(xpos,ypos,ch)
  656.     int* xpos;
  657.     int* ypos;
  658.     char* ch;
  659.     {
  660.     extern ULONG gin_received_sem;
  661.     extern ULONG gin_wait_sem;
  662.     extern LONG  mouse_adj_xpos;
  663.     extern LONG  mouse_adj_ypos;
  664.     extern CHAR  gin_c;
  665.  
  666.     /* Clear the received flag - this tells the PM thread we are ready for */
  667.     /* another value.                                                      */
  668.     DosSemClear(&gin_received_sem);
  669.     
  670.     /* Set the waiting flag and wait forever for it to be cleared */
  671.     DosSemSetWait(&gin_wait_sem,SEM_INDEFINITE_WAIT);
  672.     
  673.     /* Copy the values */
  674.     *xpos = (int) mouse_adj_xpos;
  675.     *ypos = (int) mouse_adj_ypos;
  676.     *ch   = gin_c;
  677.  
  678.     return;
  679.     }
  680.  
  681. /******************************************************************************
  682. Function:       AddToSwitch()
  683.  
  684. Description:    Adds the current process to the switch list with the supplied
  685.                 title.
  686.  
  687. Syntax:         AddToSwitch(hwndFrame, hwndIcon, title)
  688.                     HWND hwndFrame;  Windows frame handle
  689.                     HWND hwndIcon;   Windows icon handle
  690.                     char * title;    Title to go in switch list
  691.  
  692. Returns:        The switch handle or NULL if an error occurs
  693.  
  694. Mods:           19-Jan-90 C.P.Armstrong created
  695.  
  696. ******************************************************************************/
  697. HSWITCH AddToSwitch(hwndFrame, hwndIcon, title)
  698.     HWND hwndFrame;  /* Windows frame handle */
  699.     HWND hwndIcon;   /* Windows icon handle */
  700.     CHAR * title;    /* Title to go in switch list */
  701.     {
  702.     PID pid;
  703.     SWCNTRL swctl;
  704.     HSWITCH hswitch;
  705.  
  706.     if(!WinQueryWindowProcess(hwndFrame,&pid,NULL))
  707.         return(NULL);
  708.     else
  709.         {
  710.         swctl.hwnd=hwndFrame;
  711.         swctl.hwndIcon = hwndIcon;
  712.         swctl.hprog = NULL;
  713.         swctl.idProcess = (USHORT) pid;
  714.         swctl.idSession = (USHORT) 0;
  715.         swctl.uchVisibility = SWL_VISIBLE;
  716.         swctl.fbJump = SWL_JUMPABLE;
  717.         strcpy(swctl.szSwtitle,title);
  718.         swctl.fReserved = 0;             
  719.         }
  720.  
  721.     return(WinAddSwitchEntry(&swctl));
  722.     }
  723.  
  724.  
  725.  
  726.  
  727. /******************************************************************************
  728. Function:       do_aviotopm()
  729.  
  730. Description:    Posts an AVIO message to the PM queue thread for processing.
  731.                 It seems that AVIO functions can not be used by non message
  732.                 threads.
  733.  
  734. Syntax:         void do_aviotopm(struct avio_cellstr *ac)
  735.  
  736. Returns:        nothing
  737.  
  738. Mods:           00-Dec-89 C.P.Armstrong created
  739.  
  740. ******************************************************************************/
  741. void do_aviotopm(struct avio_cellstr *ac)
  742.     {
  743.     extern HWND hwndTFrame;
  744.     extern ULONG vio_sem;
  745.  
  746.     /* Kermit gets a single character and then sends it to the PM, not */
  747.     /* very efficient. It uses WRCCHSTAT, one char at a time. This     */
  748.     /* attempts to trap those single writes and store them until a line*/
  749.     /* is available.                                                   */
  750.     if(ac->fun == WRCCHSTATD)
  751.         WinPostMsg(hwndTFrame, WM_KERAVIO, MPFROMP(ac),0);
  752.     else if(DosSemRequest(&vio_sem,1000L)==0)
  753.         {
  754.         WinPostMsg(hwndTFrame, WM_KERAVIO, MPFROMP(ac),0);
  755.         /* Don't wait for the special WrtCharStrAtt */
  756.             DosSemWait(&vio_sem,5000L);
  757.         }
  758.     return;
  759.     }
  760.  
  761. /******************************************************************************
  762. Function:       process_avio()
  763.  
  764. Description:    Performs the VIO action requested by the non PM thread.
  765.  
  766. Syntax:         void process_avio(pac)
  767.                     struct avio_cellstr * pac;
  768.                     HVPS hvps;
  769.  
  770. Returns:        nothing
  771.  
  772. Mods:           31-Jan-90 C.P.Armstrong created
  773.  
  774. ******************************************************************************/
  775. void process_avio(pac,hvps)
  776.     struct avio_cellstr * pac;
  777.     HVPS hvps;
  778.     {
  779.     switch(pac->fun)
  780.         {
  781.         case RDCELLSTR:
  782.             VioReadCellStr(pac->string, pac->plen, pac->row, pac->col, hvps);
  783.             break;
  784.         case WRCELLSTR:
  785.             VioWrtCellStr(pac->string, pac->len, pac->row, pac->col, hvps);
  786.             break;
  787.         case WRNCELL:
  788.             VioWrtNCell(pac->pcell, pac->len, pac->row, pac->col, hvps);
  789.             break;
  790.         case SCROLLRT:
  791.             VioScrollRt(pac->row, pac->col, pac->hite, pac->wid, 
  792.                 pac->len, pac->pcell, hvps);
  793.             break;
  794.         case SCROLLLF:
  795.             VioScrollLf(pac->row, pac->col, pac->hite, pac->wid, 
  796.                 pac->len, pac->pcell, hvps);
  797.             break;       
  798.         case SCROLLUP:
  799.             VioScrollUp(pac->row, pac->col, pac->hite, pac->wid, 
  800.                 pac->len, pac->pcell, hvps);
  801.             break; 
  802.         case SCROLLDN:
  803.             VioScrollDn(pac->row, pac->col, pac->hite, pac->wid, 
  804.                 pac->len, pac->pcell, hvps);
  805.             break;     
  806.         case WRCCHSTATD:
  807.             if((pac!=NULL) && (pac->string!=NULL))
  808.                 {
  809.                 VioWrtCharStrAtt(pac->string,pac->len,pac->row,pac->col,
  810.                     pac->pcell,hvps);
  811.                 free(pac->string);
  812.                 free(pac);
  813.                 }
  814.             break;
  815.         case WRCCHSTAT:
  816.             VioWrtCharStrAtt(pac->string,pac->len,pac->row,pac->col,
  817.                 pac->pcell,hvps);
  818.             break;
  819.         case SETCURPOS:
  820.             VioSetCurPos(pac->row,pac->col,hvps);
  821.             break;
  822.         case GETCURPOS:
  823.             VioGetCurPos(&(pac->row), &(pac->col),hvps);
  824.             break;
  825.         case GETCURTYP:
  826.             VioGetCurType( (PVIOCURSORINFO) pac->string,hvps);
  827.             break;
  828.         case SETCURTYP:
  829.             VioSetCurType( (PVIOCURSORINFO) pac->string,hvps);
  830.             break;
  831.         case PRINTF:
  832.             vWrtchar(pac->string,pac->len,hvps);
  833.             break;
  834.         }
  835.     return;
  836.     }
  837.  
  838. void AVIOReadCellStr(PCH string,PUSHORT len, USHORT row, USHORT col)
  839.     {
  840.     struct avio_cellstr ac;
  841.     
  842.     ac.fun = RDCELLSTR;
  843.     ac.string = string;
  844.     ac.plen    = len;
  845.     ac.row    = row;
  846.     ac.col    = col;
  847.     do_aviotopm(&ac);
  848.     return;
  849.  
  850.     }
  851.     
  852. void AVIOWrtCellStr(PCH string, USHORT len, USHORT row, USHORT col)
  853.     {
  854.     struct avio_cellstr ac;
  855.     
  856.     ac.fun = WRCELLSTR;
  857.     ac.string = string;
  858.     ac.len    = len;
  859.     ac.row    = row;
  860.     ac.col    = col;
  861.  
  862.     do_aviotopm(&ac);
  863.     return;
  864.     }
  865.  
  866. void AVIOWrtNCell(PBYTE cell,  USHORT len, USHORT row, USHORT col)
  867.     {
  868.     struct avio_cellstr ac;
  869.     
  870.     ac.fun    = WRNCELL;
  871.     ac.pcell   = cell;
  872.     ac.len    = len;
  873.     ac.row    = row;
  874.     ac.col    = col;
  875.     do_aviotopm(&ac);
  876.     return;
  877.     }
  878.  
  879. void AVIOScrollRt(USHORT trow, USHORT lcol, USHORT brow, USHORT rcol, 
  880.                   USHORT len,  PBYTE cell)
  881.     {
  882.     struct avio_cellstr ac;
  883.     
  884.     ac.fun    = SCROLLRT;
  885.     ac.pcell   =  cell;
  886.     ac.len    = len;
  887.     ac.row    = trow;
  888.     ac.col    = lcol;
  889.     ac.hite   = brow;
  890.     ac.wid    = rcol;
  891.  
  892.     do_aviotopm(&ac);
  893.     return;
  894.     }
  895.  
  896. void AVIOScrollLf(USHORT trow, USHORT lcol, USHORT brow, USHORT rcol, 
  897.                  USHORT len,   PBYTE cell)
  898.     {
  899.     struct avio_cellstr ac;
  900.     
  901.     ac.fun = SCROLLLF;
  902.     ac.pcell   =  cell;
  903.     ac.len    = len;
  904.     ac.row    = trow;
  905.     ac.col    = lcol;
  906.     ac.hite   = brow;
  907.     ac.wid    = rcol;
  908.  
  909.     do_aviotopm(&ac);
  910.     return;
  911.     }
  912.  
  913.  
  914. void AVIOScrollUp(USHORT trow, USHORT lcol, USHORT brow, USHORT rcol, 
  915.                     USHORT len, PBYTE cell)
  916.     {
  917.     struct avio_cellstr ac;
  918.     
  919.     ac.fun = SCROLLUP;
  920.     ac.pcell   =  cell;
  921.     ac.len    = len;
  922.     ac.row    = trow;
  923.     ac.col    = lcol;
  924.     ac.hite   = brow;
  925.     ac.wid    = rcol;
  926.  
  927.     do_aviotopm(&ac);
  928.     return;
  929.     }
  930.  
  931. void AVIOScrollDn(USHORT trow, USHORT lcol, USHORT brow, USHORT rcol, 
  932.                     USHORT len, PBYTE cell)
  933.     {
  934.     struct avio_cellstr ac;
  935.     
  936.     ac.fun = SCROLLDN;
  937.     ac.pcell   =  cell;
  938.     ac.len    = len;
  939.     ac.row    = trow;
  940.     ac.col    = lcol;
  941.     ac.hite   = brow;
  942.     ac.wid    = rcol;
  943.  
  944.     do_aviotopm(&ac);
  945.     return;
  946.     }
  947.  
  948. void AVIOdWrtCharStrAtt(string, len, row, col, pbAttr)
  949.                        PCH string;      /* pointer to string to write */
  950.                        USHORT len;    /* length of string           */
  951.                        USHORT row;       /* starting position (row)    */
  952.                        USHORT col;    /* starting position (column) */
  953.                        PBYTE pbAttr;       /* pointer to attribute       */
  954.     {
  955.     struct avio_cellstr * pac;
  956.  
  957.     if( (pac = (struct avio_cellstr *)malloc(sizeof(struct avio_cellstr)))
  958.             ==NULL)
  959.         return;
  960.  
  961.     pac->fun = WRCCHSTATD;
  962.     pac->string = string;
  963.     pac->len    = len;
  964.     pac->row    = row;
  965.     pac->col    = col;
  966.     pac->pcell   = pbAttr;
  967.  
  968.     do_aviotopm(pac);
  969.     return;
  970.     }
  971.  
  972.  
  973.  
  974. void AVIOWrtCharStrAtt(string, len, row, col, pbAttr)
  975.                        PCH string;      /* pointer to string to write */
  976.                        USHORT len;    /* length of string           */
  977.                        USHORT row;       /* starting position (row)    */
  978.                        USHORT col;    /* starting position (column) */
  979.                        PBYTE pbAttr;       /* pointer to attribute       */
  980.     {
  981.     struct avio_cellstr ac;
  982.     
  983.     ac.fun = WRCCHSTAT;
  984.     ac.string = string;
  985.     ac.len    = len;
  986.     ac.row    = row;
  987.     ac.col    = col;
  988.     ac.pcell   = pbAttr;
  989.  
  990.     do_aviotopm(&ac);
  991.     return;
  992.     }
  993.  
  994.  
  995. void AVIOSetCurPos(usRow, usColumn)
  996.     USHORT usRow;       /* row position    */
  997.     USHORT usColumn;    /* column position */
  998.     {
  999.     struct avio_cellstr ac;
  1000.     
  1001.     ac.fun = SETCURPOS;
  1002.     ac.row    = usRow;
  1003.     ac.col    = usColumn;
  1004.     do_aviotopm(&ac);
  1005.     return;
  1006.     }
  1007.  
  1008. void AVIOGetCurPos(pusRow, pusColumn)
  1009.     PUSHORT pusRow;       /* row position    */
  1010.     PUSHORT pusColumn;    /* column position */
  1011.     {
  1012.     struct avio_cellstr ac;
  1013.     
  1014.     ac.fun = GETCURPOS;
  1015.     do_aviotopm(&ac);
  1016.     *pusRow = ac.row;
  1017.     *pusColumn = ac.col;
  1018.     return;
  1019.     }
  1020.  
  1021. void AVIOGetCurType(PVIOCURSORINFO string)
  1022.     {
  1023.     struct avio_cellstr ac;
  1024.     
  1025.     ac.fun = GETCURTYP;
  1026.     ac.string = (PCH) string;
  1027.     do_aviotopm(&ac); 
  1028.     return;
  1029.     }
  1030.  
  1031. void AVIOSetCurType(PVIOCURSORINFO string)
  1032.     {
  1033.     struct avio_cellstr ac;
  1034.     
  1035.     ac.fun = SETCURTYP;
  1036.     ac.string = (PCH) string;
  1037.     do_aviotopm(&ac); 
  1038.     return;
  1039.     }
  1040.  
  1041. void AVIOwrttyc(s,x)
  1042.     char* s;
  1043.     int  x;
  1044.     {
  1045.     struct avio_cellstr ac;
  1046.     
  1047.     ac.fun = PRINTF;
  1048.     ac.string = (PCH) s;
  1049.     ac.len    = x;
  1050.     do_aviotopm(&ac); 
  1051.     return;
  1052.     }
  1053.     
  1054.  
  1055. /******************************************************************************
  1056. Function:       PM_setViotitle()
  1057.  
  1058. Description:    Changes the title text used by the Vio screen.
  1059.                 Unfortunately this is not possible from a non PM message queue
  1060.                 containing thread.  Thus a message has to be posted to the 
  1061.                 message queue thread which is then processed by a separate
  1062.                 function.
  1063.  
  1064. Syntax:         void PM_setViotitle(title)
  1065.                     char * title; The string to use - it sould be constant
  1066.  
  1067. Returns:        nothing
  1068.  
  1069. Mods:           03-Feb-90 C.P.Armstrong created
  1070.                 25-Mar-90 C.P.Armstrong Need to use this from within the PM
  1071.                                         thread (when user changes emu mode 
  1072.                                         during a conect).  Waiting on a sem is
  1073.                                         no good because the PM thread is the
  1074.                                         one doing the waiting.In the absence of
  1075.                                         a better way the buffer must be a 
  1076.                                         constant, as must TitleText structure.
  1077.  
  1078. ******************************************************************************/
  1079. void PM_setViotitle(title)
  1080.     char * title; /* The string to use - it sould be constant */
  1081.     {
  1082.     extern HWND hwndTFrame;
  1083.     ULONG sm;
  1084.     static struct TitleText_command ttc;
  1085.                                 
  1086.     ttc.action = SET;
  1087.     ttc.hwnd   = hwndTFrame;
  1088.     ttc.buffer = title;
  1089.     ttc.sem    = &sm;
  1090. //    DosSemSet(&sm);
  1091.     WinPostMsg(hwndTFrame,WM_TITLETEXT, MPFROMP(&ttc),0);
  1092.     
  1093. //    DosSemWait(&sm,SEM_INDEFINITE_WAIT);
  1094.     
  1095.     return;
  1096.     }
  1097.     
  1098. /******************************************************************************
  1099. Function:       PM_getViotitle()
  1100.  
  1101. Description:    Returns the current Vio title text.  If the function is
  1102.                 called with a NULL buffer for the text then only the length
  1103.                 of the title text is returned. It is assumed by the routine that
  1104.                 the buffer is long enough to receive the full title text, 
  1105.                 including the NUL terminator.
  1106.                 The function is designed to be called once with a NUL buffer, 
  1107.                 reserve the memory, then call again with the full length buffer.
  1108.  
  1109. Syntax:         int PM_getViotitle(title)
  1110.                     char * title;  Buffer to receive the title
  1111.  
  1112. Returns:        The length of the title
  1113.  
  1114. Mods:           03-Feb-90 C.P.Armstrong created
  1115.  
  1116. ******************************************************************************/
  1117. int PM_getViotitle(title)
  1118.     char * title;  /* Buffer to receive the title */
  1119.     {
  1120.     extern HWND hwndTFrame;
  1121.     ULONG sm;
  1122.     struct TitleText_command ttc;
  1123.                                 
  1124.     ttc.action = LENGTH;
  1125.     ttc.hwnd   = hwndTFrame;
  1126.     ttc.buffer = NULL;
  1127.     ttc.len    = 0;
  1128.     ttc.sem    = &sm;
  1129.     DosSemSet(&sm);
  1130.     WinPostMsg(hwndTFrame,WM_TITLETEXT, MPFROMP(&ttc),0);
  1131.     DosSemWait(&sm,SEM_INDEFINITE_WAIT);
  1132.  
  1133.     if(title != NULL)
  1134.         {
  1135.         ttc.action = GET;
  1136.         ttc.hwnd   = hwndTFrame;
  1137.         ttc.buffer = title;
  1138.         ttc.sem    = &sm;
  1139.         DosSemSet(&sm);
  1140.         WinPostMsg(hwndTFrame,WM_TITLETEXT, MPFROMP(&ttc),0);
  1141.         DosSemWait(&sm,SEM_INDEFINITE_WAIT);
  1142.         }
  1143.  
  1144.     return(ttc.len);
  1145.     }
  1146.  
  1147. /******************************************************************************
  1148. Function:       TitleText()
  1149.  
  1150. Description:    Processes a title text command.  This function should only be
  1151.                 called from a thread containing a PM message queue.  Use
  1152.                 PM_getViotitle and PM_setViotitle to send commands to the
  1153.                 PM message queue.
  1154.  
  1155. Syntax:         void TitleText(mp1,mp2)
  1156.                     MPARAM mp1,mp2;  Parameters passed to the client window
  1157.                                      procudure.
  1158.  
  1159. Returns:        nothing
  1160.  
  1161. Mods:           03-Feb-90 C.P.Armstrong created
  1162.  
  1163. ******************************************************************************/
  1164. void TitleText(mp1,mp2)
  1165.     MPARAM mp1,mp2;
  1166.     {
  1167.     struct TitleText_command * pttc;
  1168.     
  1169.     pttc = (struct TitleText_command *) PVOIDFROMMP(mp1);
  1170.     
  1171.     switch(pttc->action)
  1172.         {
  1173.         case SET:
  1174.             WinSetWindowText(pttc->hwnd,pttc->buffer);
  1175.             break;
  1176.         case GET:
  1177.             pttc->len = WinQueryWindowText(pttc->hwnd,pttc->len,pttc->buffer);
  1178.             break;
  1179.         case LENGTH:
  1180.             pttc->len = WinQueryWindowTextLength(pttc->hwnd)+1;
  1181.             break;
  1182.         default:
  1183.             break;
  1184.         }
  1185.  
  1186.     /* clear the semaphore so the waiting thread knows we've finished */
  1187.     DosSemClear(pttc->sem);
  1188.     
  1189.     return;
  1190.     }
  1191.     
  1192.     
  1193.     
  1194. /******************************************************************************
  1195. Function:       DecodePMChar()
  1196.  
  1197. Description:    Decodes a PM WM_CHAR message into something more usable.  
  1198.                 Distinguishes between Num Keypad presses with NumLock on and
  1199.                 off and returns a pseudo scan code value defined in ckopm.h.
  1200.                 The decoded key press is inserted into the inter thread buffer
  1201.                 with buff_insert().
  1202.  
  1203. Syntax:         int DecodePMChar(mp1,mp2)
  1204.                     MPARAM mp1,mp2
  1205.  
  1206. Returns:        0
  1207.  
  1208. Mods:           29-Jan-90 C.P.Armstrong created
  1209.  
  1210. ******************************************************************************/
  1211. int DecodePMChar(mp1,mp2)
  1212. //    PUSHORT pmsg;
  1213.     MPARAM mp1,mp2;
  1214.     {
  1215.     extern char debugmsg;
  1216.     SHORT vkey,chr,fs,dum;
  1217.     unsigned char scancode; 
  1218.  
  1219.  
  1220.     fs  = SHORT1FROMMP(mp1);
  1221.     vkey=SHORT2FROMMP(mp2);
  1222.     chr =SHORT1FROMMP(mp2);
  1223.     scancode = CHAR4FROMMP(mp1);
  1224.  
  1225.     /* Weed out the keypad keys with NumLock off */
  1226.     if( (scancode >= KP7 && scancode<=KPDOT)
  1227.          || (scancode==KPSLASH || scancode==KPSTAR))
  1228.          {
  1229.          /* Most annoyingly the grey keypad keys are tagged as being CHAR keys*/
  1230.          /* regardless off whether the NumLock key is on or off.  Fing typical*/
  1231.  
  1232.          if((fs & KC_CHAR) && (numlock_status()&1)) /* Keypad keys are tagged */
  1233.                                                     /* as vkeys even */
  1234.             buff_insert(chr);           /* with the NumLock on.  So force them*/
  1235.          else                           /* to be numeric here. */
  1236.             buff_insert(scancode<<8);
  1237.          return(0);
  1238.          }
  1239.  
  1240.     if(fs&KC_VIRTUALKEY)
  1241.         {
  1242.         /* Seems to be no other way to do it!! */
  1243.         switch(vkey)
  1244.             {
  1245.             // THE shift keys are put in here
  1246.             case VK_SHIFT:
  1247.             case VK_CTRL:
  1248.             case VK_ALT:
  1249.             case VK_CAPSLOCK:
  1250.                 numlock_toggle();
  1251.             case VK_SCRLLOCK:
  1252.             case VK_ALTGRAF:
  1253.                 return(0);
  1254.             case VK_ESC:       buff_insert(27); return(0);
  1255.             case VK_SPACE:     buff_insert(32); return(0);
  1256.             case VK_TAB:       buff_insert(9);  return(0);
  1257.             case VK_NEWLINE:   buff_insert(13); return(0);
  1258.             case VK_PRINTSCRN:
  1259.                 /* Check if Shift-PrintScreen */
  1260.                 vkey = WinGetKeyState(HWND_DESKTOP,VK_SHIFT);
  1261.                 if(vkey & 0x8000)
  1262.                     vkey = (VK_PRINTSCRN | 0x20);
  1263.                 else
  1264.                     vkey = VK_PRINTSCRN;
  1265.  
  1266.                 buff_insert(vkey<<8);
  1267.                 break;
  1268.             case VK_NUMLOCK:
  1269.                 if(fs & KC_CTRL)
  1270.                     {
  1271.                     dbprintf("Got ctrl-NumLock");
  1272.                     return(0);
  1273.                     }
  1274.                 else                 /* This switches the NumLock state so it */
  1275.                     numlock_toggle();/* stays the same. Well it will when I   */
  1276.                 return(0);           /* find out how to get around the PM!    */
  1277.             default: 
  1278.                 buff_insert(vkey<<8);
  1279.             }
  1280.         }
  1281.     else if(fs & KC_CHAR)        /* Normal key */
  1282.         {
  1283.         buff_insert((unsigned int) chr);
  1284.         }
  1285.     else if((fs&KC_CTRL) && (chr>0))
  1286.         {
  1287.         buff_insert((unsigned int) (chr & 0x1F));
  1288.         }
  1289.     else if((fs&KC_ALT) && (chr>0))
  1290.         {
  1291.         dbprintf("We got an Alt key\nInserting %x",((scancode|0x80)<<8));
  1292.         buff_insert((unsigned int) ((scancode|0x80)<<8));
  1293.         }
  1294.     else
  1295.         {
  1296.         dbprintf("Unrecognized character");
  1297.         }
  1298.  
  1299.     return(0);
  1300.     }
  1301.     
  1302.  
  1303. /******************************************************************************
  1304. Function:       RgbToVioColor()
  1305.  
  1306. Description:    Converts a Presentation Manager colour code into a Vio
  1307.                 colour code.
  1308.  
  1309. Syntax:         BYTE RgbToVioColor(clrRgb)
  1310.                     COLOR clrRgb;       RGB colour code to be converted
  1311.  
  1312. Returns:        The Vio colour code in the low nibble.
  1313.  
  1314. Mods:           06-Oct-89 C.P.Armstrong Copied from p328 of Prog OS/2 P.M.
  1315.  
  1316. ******************************************************************************/
  1317. BYTE RgbToVioColor(COLOR clrRgb)
  1318.     {
  1319.     BYTE bIrgb;
  1320.     RGB  rgb;
  1321.     
  1322.     bIrgb = 0;
  1323. //    rgb = MAKETYPE(clrRgb,RGB);       /* This causes segment violations */
  1324. //    rgb = *((RGB*) &clrRgb)  ;        /* for some reason.               */
  1325.     rgb.bBlue  = (BYTE) (clrRgb & 0xFFl);
  1326.     rgb.bGreen = (BYTE) ((clrRgb & 0xFF00l) / 0x100);
  1327.     rgb.bRed   = (BYTE) ((clrRgb & 0xFF0000l) / 0x10000);
  1328.  
  1329.  
  1330.     if(rgb.bBlue  >= 0x80) bIrgb |= '\x01';
  1331.     if(rgb.bGreen >= 0x80) bIrgb |= '\x02';
  1332.     if(rgb.bRed   >= 0x80) bIrgb |= '\x04';
  1333.     
  1334.     if( rgb.bBlue  >= 0XC0 ||
  1335.         rgb.bGreen>= 0XC0 ||
  1336.         rgb.bRed  >= 0XC0)
  1337.         bIrgb |=8;
  1338.         
  1339.     if( bIrgb==0 && rgb.bBlue  >= 0X40 &&
  1340.         rgb.bGreen>= 0X40 &&
  1341.         rgb.bRed  >= 0X40)
  1342.         bIrgb = 8;
  1343.         
  1344.     return(bIrgb);
  1345.     }
  1346.  
  1347. /******************************************************************************
  1348. Function:       VioToRgbColor()
  1349.  
  1350. Description:    Converts a vio screen attribute to the PM rgb equivalent,
  1351.                 or thereabouts.  Note that only the lo nibble is used,
  1352.                 background colours must be moved into the lo nibble before
  1353.                 conversion.
  1354.  
  1355. Syntax:         LONG VioToRgbColor(attr)
  1356.                     BYTE attr;  The lo nible of a Vio attribute
  1357.  
  1358. Returns:        The colour index value as used by WinFillRect.  These might
  1359.                 not give the correct colours if the palette has been messed
  1360.                 around with in which case the Gpi nearest colour function
  1361.                 will probably need to be used.  The RGB value is not returned
  1362.                 since it is next to useless as far as I can make out.
  1363.  
  1364. Mods:           27-Nov-89 C.P.Armstrong created
  1365.  
  1366. ******************************************************************************/
  1367. LONG rgbs[16]=
  1368.     {
  1369.     CLR_BLACK             ,
  1370.     CLR_DARKBLUE          ,
  1371.     CLR_DARKGREEN         ,
  1372.     CLR_DARKCYAN          ,
  1373.     CLR_DARKRED           ,
  1374.     CLR_DARKPINK          ,
  1375.     CLR_BROWN             ,
  1376.     CLR_PALEGRAY          ,
  1377.     CLR_DARKGRAY          ,
  1378.     CLR_BLUE              ,
  1379.     CLR_GREEN             ,
  1380.     CLR_CYAN              ,
  1381.     CLR_RED               ,
  1382.     CLR_PINK              ,
  1383.     CLR_YELLOW            ,
  1384.     CLR_WHITE
  1385.     };
  1386.  
  1387. LONG VioToRgbColor(attr)
  1388.     BYTE attr;  /* The lo nible of a Vio attribute */
  1389.     {
  1390.     extern LONG rgbs[];
  1391.  
  1392.     return(rgbs[attr&0xF]);
  1393.     }
  1394.  
  1395. /******************************************************************************
  1396. Function:       buff_insert()
  1397.  
  1398. Description:    Inserts keystrokes from the keyboard into a
  1399.                 circular buffer.  When the buffer is filled input is
  1400.                 "wrapped" back to the begining.  
  1401.                 This function is meant to be used in conjunction with
  1402.                 buff_empty()..
  1403.                 The offset of the position in the buffer for the next
  1404.                 character is maintained by this function.
  1405.  
  1406. Syntax:         void buff_insert(c)
  1407.                     unsigned int c;
  1408.  
  1409. Returns:        nothing
  1410.  
  1411. Mods:           24-Nov-89 C.P.Armstrong created
  1412.  
  1413. ******************************************************************************/
  1414. void buff_insert(int c)
  1415.     {
  1416.     extern ULONG kbd_sem;
  1417.     extern int keybuffer[];     /* The buffer for the key presses */
  1418.     extern int keybuffer_size;  /* The buffer size */
  1419.     extern int next_put_pos;        /* Offset of next character */
  1420.     extern int next_get_pos;
  1421.     extern ULONG kbdovr_sem;
  1422.  
  1423.  
  1424.     if(WinMsgSemWait(&kbdovr_sem,SEM_IMMEDIATE_RETURN)!=0)
  1425.         {
  1426.         DosSemClear(&kbd_sem);  /* Make sure this is clear */
  1427.         if(WinMsgSemWait(&kbdovr_sem,10000L)!=0)
  1428.             {
  1429.             pm_err("Keyboard buffer not being emptied!");
  1430.             return;
  1431.             }
  1432.         }
  1433.  
  1434.  
  1435.     /* Stop other threads from taking things out of the buffer */
  1436.     DosEnterCritSec();
  1437.     keybuffer[next_put_pos] = c;
  1438.     next_put_pos++;
  1439.  
  1440.     /* See if we need to wrap */
  1441.     if(next_put_pos>=keybuffer_size)
  1442.         next_put_pos=0;     
  1443.         
  1444.     /* If in and out indices are now equal then we are about to overflow */
  1445.     if(next_put_pos==next_get_pos)   /* This has to be cleared by buff_empty */
  1446.         DosSemSet(&kbdovr_sem);      /* before anything can be inserted */
  1447.  
  1448.     DosExitCritSec();
  1449.  
  1450.     if(DosSemClear(&kbd_sem)!=0)
  1451.         pm_err("buff_insert - Failed to clear kbd_sem");
  1452.  
  1453.     return;
  1454.     }
  1455.  
  1456. /******************************************************************************
  1457. Function:       buff_empty()
  1458.  
  1459. Description:    Takes key presses from the buffer filled by buff_fill.
  1460.                 The ASCII code is returned.  If a special key is pressed the
  1461.                 lo byte of the return value is zero and the high byte is the
  1462.                 scan code.
  1463.  
  1464. Syntax:         int buff_empty()
  1465.  
  1466. Returns:        The character if one is present.
  1467.                 -1 if no character in buffer
  1468.  
  1469. Mods:           22-Nov-89 C.P.Armstrong
  1470.                 24-Apr-90 C.P.Armstrong Removes chars from paste buffer in
  1471.                                         preference to the keyboard buffer.
  1472.  
  1473. ******************************************************************************/
  1474. int buff_empty()
  1475.     {
  1476.     extern int keybuffer[];     /* The buffer for the key presses */
  1477.     extern int keybuffer_size;  /* The buffer size */
  1478.     extern int next_put_pos;    /* Offset of next character to be inserted  */
  1479.     extern int next_get_pos;    /* Offset of next character to be extracted */
  1480.     extern int buff_overflow;
  1481.     extern ULONG kbdovr_sem;
  1482.     extern int pasting;
  1483.     int c;
  1484.  
  1485.     if(pasting>0 && ((c=get_paste_char())>0))
  1486.         return(c);
  1487.  
  1488.     /* Freeze the other threads and check to see if the buffer is empty */
  1489.     DosEnterCritSec();
  1490.     if( (next_get_pos == next_put_pos) 
  1491.        && (DosSemWait(&kbdovr_sem,SEM_IMMEDIATE_RETURN)==0) )
  1492.         {
  1493.         DosSemClear(&kbdovr_sem);  /* We set it - so clear it! */
  1494.         DosExitCritSec();
  1495.         return(-1);
  1496.         }
  1497.  
  1498.  
  1499.  
  1500.     c = keybuffer[next_get_pos];
  1501.     DosExitCritSec();
  1502.     next_get_pos++;                       
  1503.  
  1504.     /* Wrap buffer pointer if necessary */
  1505.     if(next_get_pos>= keybuffer_size)
  1506.         next_get_pos=0;
  1507.  
  1508.     /* Clear the overflow flag */
  1509.     DosSemClear(&kbdovr_sem);
  1510.  
  1511.     if(c==0 && pasting>0)
  1512.         return(get_paste_char());
  1513.     else
  1514.         return(c);
  1515.     }
  1516.  
  1517.  
  1518. /******************************************************************************
  1519. Function:       buff_tgetch()
  1520.  
  1521. Description:    Returns a character from the PM keyboard buffer.  If no key
  1522.                 is present on entereing then the function waits for one for up
  1523.                 to the specified time.  Note that the character is returned in 
  1524.                 the lo byte and the scan code in the high byte of the word.
  1525.                 
  1526.                 The routine uses a semaphore to determine the wait time.  So
  1527.                 supplying a time of SEM_INDEFINITEWAIT or SEM_IMMEDIATE_RETURN
  1528.                 will have the same effect as when these values are used with
  1529.                 semaphores.  The values are defined in OS.H
  1530.  
  1531. Syntax:         int buff_tgetch(time)
  1532.                     LONG time;  Time to wait for a character in milliseconds
  1533.  
  1534. Returns:        The character
  1535.  
  1536. Mods:           04-Dec-89 C.P.Armstrong created
  1537.                 11-Mar-90 C.P.Armstrong Cursor visible check request added
  1538.                 24-Apr-90 C.P.Armstrong A -1 from buff_empty() only causes a 
  1539.                                         return if time is not 
  1540.                                         SEM_INDEFINITE_WAIT.
  1541. ******************************************************************************/
  1542. int buff_tgetch(time)
  1543.     LONG time;
  1544.     {
  1545.     extern ULONG kbd_sem;
  1546.     int c;
  1547.     
  1548.     do
  1549.         {
  1550.         if(buff_test() == 0)
  1551.             {
  1552.             /* Tell PM to reposition cursor */
  1553.             CurScrChk();
  1554.             /* Max 10s wait to set the semaphore */   
  1555.             DosSemRequest(&kbd_sem,100L); 
  1556.             /* Now wait for buff_insert() to clear it */
  1557.             DosSemWait(&kbd_sem,time);   
  1558.             }   /* buff_empty() returns -1 when paste buffer empties */
  1559.         }while( ((c=buff_empty())==-1) && (time==SEM_INDEFINITE_WAIT));
  1560.  
  1561.     return(c);
  1562.     }
  1563.     
  1564.  
  1565. int buff_getch()
  1566.     {
  1567.     return(buff_tgetch(SEM_INDEFINITE_WAIT));
  1568.     }
  1569.  
  1570.  
  1571.  
  1572. /******************************************************************************
  1573. Function:       buff_strins()
  1574.  
  1575. Description:    Inserts a string of characters into the keyboard buffer
  1576.  
  1577. Syntax:         void buff_strins(zstring)
  1578.                     char * zstring;  the Nul terminated string
  1579.  
  1580. Returns:        nothing
  1581.  
  1582. Mods:           28-Nov-89 C.P.Armstrong created
  1583.  
  1584. ******************************************************************************/
  1585. void buff_strins(zstring)
  1586.     char * zstring;  /* the Nul terminated string */
  1587.     {
  1588.     int i,l;
  1589.     l=strlen(zstring);
  1590.     
  1591.     for(i=0;i<l;i++)
  1592.         {
  1593.         buff_insert((int)zstring[i]);
  1594.         DosSleep(200L);
  1595.         }
  1596.     
  1597.     return;
  1598.     }
  1599.  
  1600.  
  1601. /******************************************************************************
  1602. Function:       buff_test()
  1603.  
  1604. Description:    Tests for the presence of a character without removing any
  1605.                 characters if present.
  1606.  
  1607. Syntax:         int buff_test()
  1608.  
  1609. Returns:        0 if no chars
  1610.                 >0 if chars present
  1611.  
  1612. Mods:           27-Nov-89 C.P.Armstrong created
  1613.  
  1614. ******************************************************************************/
  1615. int buff_test()
  1616.     {
  1617.     extern int pasting;
  1618.     extern int next_put_pos;    /* Offset of next character to be inserted  */
  1619.     extern int next_get_pos;    /* Offset of next character to be extracted */
  1620.     extern ULONG kbdovr_sem;
  1621.     int c;
  1622.     
  1623.     if(pasting>0)
  1624.         return(1);
  1625.  
  1626.  
  1627.     /* Freeze the other threads and check to see if the buffer is empty */
  1628.     DosEnterCritSec();
  1629.     if((next_get_pos == next_put_pos) && 
  1630.       (DosSemWait(&kbdovr_sem,SEM_IMMEDIATE_RETURN)==0))
  1631.         c=0;
  1632.     else
  1633.         c=1;
  1634.         
  1635.     DosExitCritSec();
  1636.     return(c);
  1637.     }
  1638.  
  1639.  
  1640. /******************************************************************************
  1641. Function:       vWrtchar()
  1642.  
  1643. Description:    Writes a single character out to a Vio screen and advances the
  1644.                 cursor to the next position.  The cursor is wrapped at the
  1645.                 end of the line.  If the end of the screen is reached then
  1646.                 the whole screen is scrolled by 1 line.  This replaces the
  1647.                 VioWrtTTY function and is compatible with multi-threaded
  1648.                 PM programs.  VioWrTTY fails in multi-threaded programs when
  1649.                 used outside the main window thread.  Note that the colour
  1650.                 is not written, only the character.
  1651.                 
  1652.                 The address of the video buffer must be declared externally.
  1653.                 Also the screen size must be declared externally.
  1654.                 
  1655.                 Note this behaviour of this function wrt LF may seem strange.
  1656.                 A CRLF sequence is produced when the function receives an LF.
  1657.                 This is in keeping with the behaviour of printf().  A CR
  1658.                 produces just a CR.  The ENTER key usually produces a CR so
  1659.                 any key interpretation function should convert this to LF.
  1660.                 
  1661.                 Function will move backwards one position on receipt of a
  1662.                 '\b'. To erase a character a "\b \b" sequence must be sent.
  1663.                 
  1664. Syntax:         void vWrtchar(c,l,h)
  1665.                     char * c;  Pointer to the string
  1666.                     int    l;  length of the string
  1667.                     HVPS   h;  handle to the presentation space (PS)
  1668.  
  1669. Returns:        nothing
  1670.  
  1671. Mods:           27-Nov-89 C.P.Armstrong created
  1672.  
  1673. ******************************************************************************/
  1674. void vWrtchar(c,l,h)
  1675.     char * c;  /* Pointer to the string */
  1676.     int    l;  /* length of the string */
  1677.     HVPS   h;  /* handle to the presentation space (PS) */
  1678.     {
  1679.     extern char far * ulVideoBuffer;
  1680.     extern char defaultattribute;
  1681.     extern ULONG vio_sem;
  1682.     extern HVPS hvps;
  1683.     extern int scrwidth;
  1684.     extern int scrheight;
  1685.     extern char defaultattribute;
  1686.  
  1687.     USHORT row,col;     /* Present cursor position */
  1688.     USHORT orow;
  1689.     int i;              /* Character to print */
  1690.     int off;
  1691.     BYTE cell[2];
  1692.  
  1693.     VioGetCurPos(&row,&col,hvps);
  1694.     orow=row;
  1695.  
  1696.     for(i=0;i<l;i++)
  1697.         {
  1698.         switch(c[i])
  1699.             {
  1700.             case '\a':
  1701.                 DosBeep(3000,100);
  1702.                 return;
  1703.             case '\t':
  1704.                 do
  1705.                     {
  1706.                     col++;
  1707.                     if(col>=scrwidth)  /* Row scrolling is dealt with below */
  1708.                         {
  1709.                         col=0;
  1710.                         row++;
  1711.                         }
  1712.                     }
  1713.                 while(col%5);
  1714.                 col--;  /* Reset to correct position below */
  1715.                 break;
  1716.             case '\b':
  1717.                 col-=2;
  1718.                 if(col<0)         /* Did we delete past bol */
  1719.                     {
  1720.                     row--;
  1721.                     col=scrwidth-2;
  1722.                     }
  1723.                 if(row<0)        /* Are we trying to delete past top of */
  1724.                     {            /* window?  If so stomp on it.         */    
  1725.                     row=0;
  1726.                     col=-1;
  1727.                     }
  1728.                 break;
  1729.             case '\n':
  1730.                 row++;
  1731.             case '\r':
  1732.                 col=-1; /* It'll get set to 0 at the end */
  1733.                 break;
  1734.             
  1735.             default:                
  1736.                 off = ((row*scrwidth)+col)*2;
  1737.                 ulVideoBuffer[ off ] = c[i];
  1738.                 ulVideoBuffer[off+1] = defaultattribute;
  1739.             }
  1740.         
  1741.         col++;
  1742.         if(col>=scrwidth)
  1743.             {
  1744.             col=0;
  1745.             row++;
  1746.             }
  1747.         
  1748.         if(row>=scrheight)
  1749.             {
  1750.             row=scrheight-1;
  1751.             cell[0]=' ';
  1752.             cell[1]=defaultattribute;
  1753.             VioScrollUp(0,0,scrheight,scrwidth,1,cell,hvps);
  1754.             }
  1755.             
  1756.         }        
  1757.  
  1758.         /* Move the cursor first - this stops the new chars flashing */
  1759.         VioSetCurPos(row,col,hvps);
  1760.         
  1761.         /* Unfortunately the PM freezes if deselection or resizing occurs */
  1762.         /* during output.  This does not seem to happen if now output is  */
  1763.         /* going on so I assume it must be something to do with this.     */
  1764.         /* I've had a lot of problems with the buffer showing.            */
  1765.         /* VioShowBuf ususally freezes completely. Maybe VioShowPS can't  */
  1766.         /* handle working in the background. Either that or there needs to*/
  1767.         /* be some way of figuring out when the move is completly done so */
  1768.         /* things can carry on.                                           */
  1769.  
  1770.         VioShowPS(row-orow+1,scrwidth,(orow*scrwidth),hvps);
  1771.  
  1772.         DosSemClear(&vio_sem);
  1773.         return;
  1774.         }
  1775.  
  1776. /******************************************************************************
  1777. Function:       flash_cursor()
  1778.  
  1779. Description:    Toggles the cursor on and off - if cursor display is enabled
  1780.                 by show_cursor().
  1781.  
  1782. Syntax:         void flash_cursor(hvps)
  1783.                     HVPS hvps;  Vio PS handle
  1784.  
  1785. Returns:        
  1786.  
  1787. Mods:           
  1788.  
  1789. ******************************************************************************/
  1790. void flash_cursor(hvps)
  1791.     HVPS hvps;  /* Vio PS handle */
  1792.     {
  1793.     extern char cursor_displayed;
  1794.     VIOCURSORINFO vc;
  1795.     
  1796.     if(cursor_displayed==1)
  1797.         {
  1798.         if(VioGetCurType(&vc,hvps)==0)
  1799.             {
  1800.             vc.attr = (vc.attr==0) ? -1 : 0;
  1801.             VioSetCurType(&vc,hvps);
  1802.             }
  1803.         }
  1804.     return;
  1805.     }
  1806.  
  1807.  
  1808.  
  1809.  
  1810. /******************************************************************************
  1811. Function:       show_cursor()
  1812.  
  1813. Description:    Shows or hides the Vio cursor
  1814.  
  1815. Syntax:         BOOL show_cursor(yn)
  1816.                     BOOL yn;    1 = Show the cursor, 0 = hide it
  1817.                     HVPS hvps;  Cursor belongs to this presentation space
  1818.  
  1819. Returns:        0 if cursor hidden
  1820.                 1 if cursor displayed
  1821.  
  1822. Mods:           06-Oct-89 C.P.Armstrong created
  1823.                 07-Dec-89 C.P.Armstrong Modified for use with software blink. 
  1824.                                         (Not implimented).
  1825.  
  1826. ******************************************************************************/
  1827. BOOL show_cursor(yn,hvps)
  1828.     BOOL yn;    /* Show the cursor? */
  1829.     HVPS hvps;  /* Cursor belongs to this presentation space */
  1830.  
  1831.     {
  1832.     extern char cursor_displayed;
  1833.     VIOCURSORINFO vc;
  1834.     BOOL oa;            // Old state
  1835.     static char state=1;
  1836.     
  1837.     if(VioGetCurType(&vc,hvps)==0)
  1838.         {
  1839.         oa = (vc.attr==0) ? 1 : 0; 
  1840.         vc.attr = yn ? 0 : -1;
  1841.  
  1842.         VioSetCurType(&vc,hvps);
  1843.         if(yn)
  1844.           cursor_displayed=1;
  1845.         else
  1846.             cursor_displayed=0;
  1847.         }
  1848.     else
  1849.         {    // In case of error assume the cursor isn't there
  1850.         oa=0;
  1851.         cursor_displayed=0;
  1852.         }
  1853.     
  1854.     return(oa);
  1855.     }
  1856.   
  1857. /******************************************************************************
  1858. Function:       Put_cursor_onscreen()
  1859.  
  1860. Description:    Adjusts the Vio origin so that the Vio cursor position lies
  1861.                 within the current window.
  1862.  
  1863. Syntax:         void Put_cursor_onscreen(hwndClient, hvps)
  1864.                     HWND hwndClient; Handle of the window (not the Frame window)
  1865.                     HVPS hvps      ; Handle to the associated vio pres. space.
  1866.  
  1867. Returns:        nothing
  1868.  
  1869. Mods:           11-Mar-90 C.P.Armstrong created
  1870.  
  1871. ******************************************************************************/
  1872. void Put_cursor_onscreen(HWND hwndClient, HVPS hvps)
  1873.     {
  1874.     SHORT crow,ccol;
  1875.     SHORT orow,ocol;
  1876.     RECTL clrctl;
  1877.     SIZEL sizl;
  1878.     SWP swp;
  1879.     HDC hdc;
  1880.     VIOMODEINFO vioinf;
  1881.     int repos=0;
  1882.  
  1883.     /* Get Vio cursor position */
  1884.     VioGetCurPos(&crow,&ccol,hvps);
  1885.     
  1886.     /* Get Vio window size and offset within the frame window */
  1887.     WinQueryWindowPos(hwndClient,&swp);
  1888.     
  1889.     /* Get the Vio screen size */
  1890.     if((repos =VioGetMode(&vioinf,hvps))!=0)
  1891.         {
  1892.         /* This does not work.  The return code is 494 which doesn't help    */
  1893.         /* much.  As usual things don't work like the manual says they       */
  1894.         /* should which squashes any hope of making this a general function. */
  1895.         /* I'll leave the code in on the off chance that MS pull their       */
  1896.         /* fingers out and one day make things work like they should.        */
  1897.         /* INVALID_HANDLE        436 */
  1898.         /* INVALID_LENGTH        438 */
  1899.         /* MODE                  355 */
  1900.         /* INVALID_PARMS         421 */
  1901.         vioinf.row=25;
  1902.         vioinf.col=80;
  1903.         }
  1904.  
  1905.     /* Get the size in pixels of a character */
  1906.     hdc = WinQueryWindowDC(hwndClient);
  1907.     DevQueryCaps(hdc, CAPS_CHAR_WIDTH, 2L, (PLONG) &sizl);
  1908.  
  1909.  
  1910.     /* Figure out window size in rows and cols */
  1911.     swp.cy = swp.cy/ (SHORT)sizl.cy;
  1912.     swp.cx = swp.cx/ (SHORT)sizl.cx;
  1913.     
  1914.     /* Get the current origin for the Vio screen (top left row/col) */
  1915.     VioGetOrg(&orow,&ocol,hvps);
  1916.  
  1917.     /* Is cursor visible then */
  1918.     /* Is cursor below bottom edge?  or are there too few lines displayed */
  1919.     if((crow>=(swp.cy+orow)) || ((crow-orow)<swp.cy) )   
  1920.         {
  1921.         orow = crow-swp.cy+1;
  1922.         if(orow<0)
  1923.             orow = 0;
  1924.         if(orow>vioinf.row-2)
  1925.             orow = vioinf.row-2;
  1926.         repos = 1;
  1927.         }
  1928.      else if(crow < orow)      /* Is cursor above top edge */
  1929.         {
  1930.         orow = crow;
  1931.         repos = 1;
  1932.         }
  1933.  
  1934.     /* Is cursor beyond right edge, or are too few cols displayed? */
  1935.     if((ccol>=(swp.cx+ocol)) || ((ccol-ocol)<swp.cx) )   
  1936.         {
  1937.         ocol = ccol-swp.cx+1;
  1938.         if(ocol<0)
  1939.             ocol = 0;
  1940.         if(ocol > vioinf.col-2)
  1941.             ocol = vioinf.col-2;
  1942.         repos = 1;
  1943.         }
  1944.      else if(ccol < ocol)      /* Is cursor beyond left edge */
  1945.         {
  1946.         ocol = ccol;
  1947.         repos = 1;
  1948.         }
  1949.  
  1950.     /* If so reposition the client window in the frame window */
  1951.     if(repos!=0)
  1952.         {
  1953.         VioSetOrg(orow,ocol,hvps);
  1954.         }
  1955.  
  1956.     return;
  1957.     }
  1958.     
  1959. /******************************************************************************
  1960. Function:       CurScrChk()
  1961.  
  1962. Description:    Tells the PM thread to put the cursor in the current Vio window.
  1963.  
  1964. Syntax:         void CurScrChk()
  1965.  
  1966. Returns:        nothing
  1967.  
  1968. Mods:           16-Mar-90 C.P.Armstrong
  1969.  
  1970. ******************************************************************************/
  1971. void CurScrChk()
  1972.     {
  1973.     extern HWND hwndTFrame;
  1974.  
  1975.     WinPostMsg(hwndTFrame,WM_CURCHECK,(MPARAM) NULL,(MPARAM) NULL);
  1976.     }
  1977.  
  1978.  
  1979. int numlock_status()
  1980.     {
  1981.     BYTE skt[256];
  1982.     
  1983.     WinSetKeyboardStateTable(HWND_DESKTOP,skt,FALSE);
  1984.  
  1985.     return(skt[VK_NUMLOCK]);
  1986.  
  1987.     }
  1988.