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

  1. /******************************************************************************
  2. File name:  ckopm4.c    Rev: 01  Date: 01-Apr-90 Programmer: C.P.Armstrong
  3.  
  4. File title: The Gpi window procedure and some associated functions.
  5.  
  6. Contents:   GpiWndProc()
  7.  
  8. Modification History:
  9.     01  01-Apr-90   C.P.Armstrong   created
  10.  
  11. ******************************************************************************/
  12. #include <stdio.h>
  13. #include <string.h>
  14. #include <malloc.h>
  15. #include <process.h>
  16. #define INCL_DOS
  17. #define INCL_WIN
  18. #define INCL_GPI    
  19. #define INCL_DOSERRORS      /* For the block marking */
  20. #define INCL_VIO            /* and copying routines  */
  21. #define INCL_AVIO
  22. #include <OS2.h>
  23. #include "ckcker.h"   /* For VT100 and TEKTRONIX */
  24. #include "ckopm.h"
  25. #include "ckorc.h"    /* Resource defines */
  26.  
  27. /* Whoever thought up the defaults for GpiLoadFonts should be shot.  The */
  28. /* function wont look in the current directory and if an extension is    */
  29. /* supplied it wont look in the "libpath".  If no path or extension is   */
  30. /* supplied it uses an extension of .DLL (all references in the refs.    */
  31. /* say to use .FON for font files).  So there is no choice but to call   */
  32. /* ckofon.dll since I have no idea where users will want to keep the     */
  33. /* font files - presumably in the libpath somewhere.                     */
  34.  
  35. #define REPAINTSTACKSIZE 8192
  36. #define FONFILE "ckofon"  
  37.  
  38.  
  39. /* Function definitions */
  40. MRESULT EXPENTRY GpiWndProc(HWND,USHORT,MPARAM,MPARAM);
  41. MRESULT EXPENTRY VioWndProc(HWND,USHORT,MPARAM,MPARAM);
  42. void dbprintf(const char *,...);
  43. int  DecodePMChar(MPARAM,MPARAM);
  44. void Put_cursor_onscreen(HWND,HVPS);
  45. void TitleText(MPARAM,MPARAM);
  46. int  DoPMTekGin(HWND,USHORT*);
  47. void avio_dispatch(struct avio_cellstr *, HVPS);
  48. int menu_routine(HAB,HWND,HWND,HVPS,USHORT,MPARAM,MPARAM);
  49. int init_menu(MPARAM,HWND,HWND,HAB);
  50.  
  51. /* Block marking and copying routiens */
  52. int mouse_to_curpos(int,int,int *,int *,HVPS,HWND);
  53. int do_mark(HWND,MPARAM,MPARAM,HVPS);
  54. int end_mark(HWND,MPARAM,MPARAM,HVPS);
  55. int start_mark(HWND,MPARAM,MPARAM,HVPS);
  56. int range_reverse(int,int,int,int,int,HVPS);
  57. int fill_clipboard(char far * ,int,HAB);
  58. char * copy_block(int,int,int,int,HVPS);
  59. int get_viops_size(int*,int*,HVPS);
  60. void buff_strins(char *);
  61. void far pc_paint_thread(struct pc_paint * pc_p);
  62.  
  63.  
  64.  
  65. void cdecl pm_err(char *);          /* declared in ckopm.h.  Redeclared here */
  66. void cdecl pm_msg(char*,char*);     /* to avoid having to include all the    */
  67.                                     /* OS2.H stuff required for ckopm.h in an*/
  68.                                     /* attempt to beat the MSC5.1 out of heap*/
  69.                                     /* messages which occur for tiny files.  */
  70. void buff_insert(int);
  71.  
  72.  
  73.  
  74.  
  75. /****** Initialised global variables */
  76. char far * copyb=NULL;              /* Paste buffer */
  77. int far pasting=0;
  78. char   immediate_update=1;          /* If 0 do not draw point now      */
  79. struct plot_command far pcroot=     /* First plot command structure of */
  80.     {                               /* linked list */
  81.     '\0',
  82.     0L,
  83.     0L,
  84.     NULL
  85.     };
  86. static struct plot_command * pcurrent= /* Pointer to current plot command */
  87.     &pcroot;                           /* static makes it local to this file */
  88.  
  89. /**** Uninitialised global variables ****/
  90. int pc_out;                     /* next value to be taken from the buffer    */
  91. int pc_in;                      /* next value to be inserted into the buffer */
  92.  
  93. /******************************************************************************
  94. Function:       GpiWndProc()
  95.  
  96. Description:    Main routine which handle the messages sent to the window used
  97.                 for Tek graphics
  98.  
  99. Syntax:         MRESULT EXPENTRY GpiWndProc(HWND hwnd,USHORT msg,MPARAM mp1,MPARAM mp2)
  100.  
  101. Returns:        Depends on the message
  102.  
  103. Mods:           01-Apr-90 C.P.Armstrong Well actually I created it ages ago.
  104.                                         Today is the day the "out of near heap"
  105.                                         error finally forced me to reduce the
  106.                                         no. of functions in ckopm1 to 3!!.
  107.  
  108. ******************************************************************************/
  109. MRESULT EXPENTRY GpiWndProc(HWND hwnd,USHORT msg,MPARAM mp1,MPARAM mp2)
  110.     {
  111.     extern HAB hab;
  112.     extern HWND hwndGFrame;
  113.     extern HWND hwndTFrame;
  114.     extern HVPS hvps;
  115.     extern ULONG wind_sem;
  116.     extern COLOR pmbgcol;
  117.     extern COLOR pmfgcol;
  118.     extern char  defaultattribute;
  119.     extern char immediate_update;
  120.     extern char Vio_visible;
  121.     extern struct plot_command pcroot;
  122.     extern struct plot_command * pcurrent;
  123.     extern char minied;              /* Indicates window is minimized */
  124.     extern ULONG paint_sem;          /* Set when repaint desired */
  125.     extern ULONG stop_painting_sem;  /* Set when about to clear */
  126.  
  127.     extern int Term_mode;
  128.  
  129.     static HPS gpi_hps;
  130.     static HPOINTER hptr;   /* The cross pointer handle */
  131.     static HWND hwndMenu;
  132.     static struct pc_paint paintdat;
  133.     static struct fontstuff fs;
  134.     static int* repaintstk;
  135.     static TID  repaintthrd;
  136.  
  137.     HDC gpi_hdc;
  138.     RECTL rcl;
  139.     SIZEL sizl;
  140.     SWP   swp;
  141.     POINTL ptl;             /* Stores the next draw command coords */
  142.     QMSG qmsg;
  143.     static char c;          /* contains the next draw command */
  144.     char far * psi;         /* pointer to a string for graphic input string */
  145.     long rgbcol;
  146.     struct plot_command * pcc;
  147.     
  148.     int i,start,x,y;
  149.  
  150.  
  151.     switch(msg)
  152.         {
  153.         case WM_CREATE:
  154.             gpi_hdc = WinOpenWindowDC(hwnd);
  155.             sizl.cx = sizl.cy = 0;
  156.             gpi_hps = GpiCreatePS(hab,gpi_hdc,&sizl, PU_PELS | GPIF_DEFAULT | 
  157.                                              GPIT_MICRO | GPIA_ASSOC);
  158.             
  159.             /* Load the menus */
  160.             hwndMenu = WinWindowFromID(
  161.                             WinQueryWindow(hwnd,QW_PARENT,FALSE),
  162.                             FID_MENU);
  163.             
  164.  
  165.             if(GpiLoadFonts(hab,FONFILE)!=GPI_OK)
  166.                 {
  167.                 pm_err("Failed to load TEKTRONIX fonts");
  168.                 paintdat.fnt = NULL;
  169.                 }
  170.             else 
  171.                 {
  172.                 fs.name = "Tektronix";
  173.                 fs.vect = 0;
  174.                 fs.h = 8;
  175.                 fs.w = 6;
  176.                 /* Let paint thread access the font info */
  177.                 paintdat.fnt = &fs;             
  178.                 /* Select the Tektronix font */
  179.                 SelectFont(gpi_hps,LCID_TEKFONT,fs.name,fs.vect,fs.h,fs.w);
  180.                 }
  181.  
  182.             /* Load the mouse cross pointer  */
  183.             hptr = WinLoadPointer(HWND_DESKTOP,(HMODULE)0,ID_CROSSPTR);
  184.  
  185.             /* Start the paint thread - the font info is set up above */
  186.             DosSemClear(&(paintdat.StopPaintSem));
  187.             paintdat.root = &pcroot;
  188.             paintdat.hwnd  = hwnd;
  189.             paintdat.fgcol = pmfgcol;
  190.             paintdat.bkcol = pmbgcol;
  191.             
  192.             /* allocate stack for repaint thread */
  193.             if((repaintstk = (int*) malloc(REPAINTSTACKSIZE))==NULL)
  194.                 {
  195.                 dbprintf("Can't allocate paint_thread stack space\n");
  196.                 DosExit(EXIT_PROCESS,1);
  197.                 }
  198.  
  199.             /* pc_paint_thread clears the EndPaintThread when its up and running */
  200.             if(DosSemSet(&(paintdat.EndPaintThread))!=0)
  201.                 {
  202.                 dbprintf("Can't set EndPaintThread\n");
  203.                 DosExit(EXIT_PROCESS,1);
  204.                 }
  205.  
  206.             _beginthread(pc_paint_thread,repaintstk,REPAINTSTACKSIZE,&paintdat);
  207.             DosSemWait(&(paintdat.EndPaintThread),SEM_INDEFINITE_WAIT);
  208.  
  209.             return(0);
  210.             
  211.         case WM_COMMAND:
  212.             menu_routine(hab,hwndMenu,hwnd,hvps,msg,mp1,mp2);
  213.             break;
  214.  
  215.         case WM_INITMENU:
  216.             init_menu(mp1,hwndMenu,hwnd,hab);
  217.             break;
  218.  
  219.         case WM_SIZE:
  220.  
  221.             /* Adjust VT100 screen to just fit new size if in VT100 mode */
  222.             if(Term_mode==VT100)
  223.                 {  
  224.                 /* Size the Vio screen */
  225.                 WinSetWindowPos(hwndTFrame,HWND_TOP,
  226.                     0,0,
  227.                     SHORT1FROMMP(mp2) , SHORT2FROMMP(mp2) ,
  228.                     SWP_SIZE|SWP_MOVE);
  229.                 }
  230.             else
  231.                 {
  232.                 WinQueryWindowPos(hwndTFrame,&swp);
  233.                 swp.cy = SHORT2FROMMP(mp2)-swp.cy;
  234.                 /* Set the position of the Vio window in the Gpi */
  235.                 WinSetWindowPos(hwndTFrame,HWND_TOP,
  236.                         (SHORT)swp.x,(SHORT)swp.cy,
  237.                         (SHORT)0, (SHORT)0,
  238.                         SWP_MOVE);
  239.                 }
  240.                 
  241.             /* Reposition the current graphics position */
  242.             if(SHORT1FROMMP(mp1)!=0 && SHORT2FROMMP(mp1)!=0)
  243.                 {
  244.                 GpiQueryCurrentPosition(gpi_hps, &ptl);
  245.                 ptl.x = ptl.x * (LONG)SHORT1FROMMP(mp2) / (LONG) SHORT1FROMMP(mp1);
  246.                 ptl.y = ptl.y * (LONG)SHORT2FROMMP(mp2) / (LONG) SHORT2FROMMP(mp1);
  247.                 GpiMove(gpi_hps, &ptl);
  248.                 }
  249.  
  250.             break;      /* Now do the default for this window */
  251.         case WM_PAINT:
  252.             /* Stop repaint thread from painting */
  253.             if(DosSemWait(&(paintdat.StartPaintSem),SEM_IMMEDIATE_RETURN)==0)
  254.                 {
  255.                 DosSemSet(&(paintdat.StopPaintSem));
  256.                 DosSemWait(&(paintdat.StopPaintSem),SEM_INDEFINITE_WAIT);
  257.                 }
  258.             WinBeginPaint(hwnd,gpi_hps,NULL);
  259.             if(WinQueryWindowULong(WinQueryWindow(hwnd,QW_PARENT,FALSE),
  260.                                     QWL_STYLE) & WS_MINIMIZED)
  261.                 {
  262.                 minied=1;
  263.                 WinSendMsg(hwndTFrame,WM_HIDE,(MPARAM)1L,(MPARAM)0L);
  264.                 }
  265.             else 
  266.                 {
  267.                 /* If we were minimized then show the text window */
  268.                 if(minied)
  269.                     {
  270.                     WinSendMsg(hwndTFrame,WM_HIDE,0,0);
  271.                     minied=0;
  272.                     }
  273.                 }
  274.  
  275.             WinQueryWindowRect(hwnd,&rcl);
  276.             pmbgcol = VioToRgbColor((BYTE)(defaultattribute>>4));
  277.             pmfgcol = VioToRgbColor(defaultattribute);
  278.  
  279.             /* Make sure the paint thread sees the current colours */
  280.             paintdat.fgcol = pmfgcol;
  281.             paintdat.bkcol = pmbgcol;
  282.  
  283.             /* Make sure this PS knows the current fg colour */
  284.             GpiSetColor(gpi_hps,pmfgcol);
  285.  
  286.             if(c!='v')
  287.                 {
  288.                 start = 0;
  289.                 pc_out=pc_in;
  290.                 WinFillRect(gpi_hps,&rcl,pmbgcol);
  291.                 WinQueryWindowPos(hwnd,&(paintdat.pc_swp));
  292.                 DosSemClear(&(paintdat.StartPaintSem));
  293.                 }
  294.                 
  295.             c=0;
  296.             WinEndPaint(gpi_hps);
  297.             return(0);
  298.             
  299.         case WM_USER:
  300.             /* Fill up the plot commands */
  301.             c = CHAR1FROMMP(mp2); 
  302.             if(c=='c')      /* Clear screen - we can deal with this here */
  303.                 {
  304.                 /* Tell the paint thread to stop */
  305.                 DosSemClear(&(paintdat.StopPaintSem));
  306.  
  307.                 /* Free the malloc'd plot command areas */
  308.                 pc_delete(&pcroot);
  309.                 pcurrent=&pcroot;
  310.  
  311.                 ptl.x=0;
  312.                 ptl.y=0;
  313.                 /* Home the cursor */
  314.                 GpiMove(gpi_hps,&ptl);
  315.                 
  316.                 /* c=0 causes a screen clear */
  317.                 c=0;
  318.                 }
  319.  
  320.             if(c==0 || c=='v')
  321.                 {
  322.                 WinQueryWindowRect(hwnd,&rcl);
  323.                 WinInvalidateRect(hwnd,&rcl,TRUE);
  324.                 }
  325.             else
  326.                 {
  327.                 /* Save the new plot command */
  328.                 pcurrent = pc_save(pcurrent,mp1,mp2);
  329.                 
  330.                 /* Most recent size is stored in the paintdat structure */
  331.                 pc_interp(*pcurrent,&(paintdat.pc_swp),0,gpi_hps);
  332.                 pc_in++;
  333.                 }
  334.             return(0L);
  335.  
  336.         case WM_GIN:              /* Get coordinate of a mouse press */
  337.             WinPostMsg(hwndTFrame, WM_HIDE,mp1,mp1);
  338.             SetPMGinMode(hwnd,mp1,hptr);   /* mp=1 set GIN mode, 0 clears it */
  339.  
  340.             return(0L);
  341.  
  342.         case WM_CHAR:
  343.             if(!(CHARMSG(&msg)->fs & KC_CHAR))
  344.                 {
  345.                 return(0);
  346.                 }
  347.         case WM_BUTTON3DOWN:
  348.         case WM_BUTTON2DOWN:
  349.         case WM_BUTTON1DOWN:
  350.             if(DoPMTekGin(hwnd,&msg))  /* If we are in Gin mode then send */
  351.                 return(0L);            /* the waiting routine some coords */
  352.                                        /* else do the WinDefProc thing    */
  353.             break;
  354.  
  355.         case WM_MOUSEMOVE:
  356.             if(TestPMGinMode())
  357.                 {
  358.                 WinSetPointer(HWND_DESKTOP, hptr);
  359.                 return((MRESULT)1);
  360.                 }
  361.             break;
  362.  
  363.         case WM_CLOSE:            /* User clicked on "Close.." so give prog  */
  364.             GpiDeleteSetId(gpi_hps,LCID_ALL); /* Delete all ids */
  365.             GpiUnloadFonts(hab,FONFILE);      /* unload the kermit fonts */
  366.             break;
  367.         case WM_DESTROY:
  368.             GpiDestroyPS(gpi_hps);
  369.             return(0);
  370.  
  371.         }
  372.     return(WinDefWindowProc(hwnd,msg,mp1,mp2));
  373.     }
  374.  
  375.  
  376. /* Vector font stuff */
  377.  
  378. /******************************************************************************
  379. Function:       SelectFont()
  380.  
  381. Description:    Creates and selects the font with the supplied name
  382.  
  383. Syntax:         LONG SelectFont (hps,lcid ,szFacename, vect,h,w)
  384.                     HPS hps
  385.                     LONG lcid
  386.                     CHAR *szFacename
  387.                     int vect; It's a vector font
  388.                     int h,w;  Height and width of non-vector font
  389. Returns:        
  390.  
  391. Mods:           19-Jan-90 C.P.Armstrong  Adapted from the PM Toolkit examples
  392.                 05-Apr-90 C.P.Armstrong  Selection of a vector font is optional
  393.  
  394. ******************************************************************************/
  395. LONG SelectFont (HPS hps, LONG lcid, CHAR *szFacename,
  396.     int vect,int h,int w)
  397.      {
  398.      FATTRS fat ;
  399.  
  400.      fat.usRecordLength  = sizeof fat ;
  401.      fat.fsSelection     = 0 ;
  402.      fat.lMatch          = 0 ;
  403.      fat.idRegistry      = 0 ;
  404.      fat.usCodePage      = GpiQueryCp (hps) ;
  405.  
  406.     if(vect==0)
  407.         {
  408.          fat.lMaxBaselineExt = h ;
  409.          fat.lAveCharWidth   = w ;
  410.          fat.fsType          = 0 ;
  411.          fat.fsFontUse       = 0 ;
  412.          }
  413.     else
  414.         {
  415.         fat.lMaxBaselineExt = 0 ;
  416.         fat.lAveCharWidth   = 0 ;
  417.         fat.fsType          = 0 ;
  418.         fat.fsFontUse       = FATTR_FONTUSE_OUTLINE |
  419.                               FATTR_FONTUSE_TRANSFORMABLE ;
  420.         }
  421.  
  422.  
  423.  
  424.      strcpy (fat.szFacename, szFacename) ;
  425.  
  426.      if(GpiCreateLogFont (hps, NULL, lcid, &fat)!=2)
  427.         {
  428.         pm_err("Font not selected");
  429.         return(GPI_ERROR);
  430.         }
  431.      return(GpiSetCharSet(hps, lcid));
  432.      }
  433.  
  434. /******************************************************************************
  435. Function:       SetCharBox()
  436.  
  437. Description:    Sets the character box size
  438.  
  439. Syntax:         void setcharbox(hps,width,height)
  440.                     HPS hps;     Presentation space
  441.                     int width;   Width in PELS
  442.                     int height;  Height in PELS
  443.  
  444. Returns:        nothing
  445.  
  446. Mods:           19-Jan-90 C.P.Armstrong created
  447.  
  448. ******************************************************************************/
  449.  
  450. void SetCharBox(hps,width,height)
  451.     HPS hps;
  452.     int width;   /* Width in PELS */
  453.     int height;  /* Height in PELS */
  454.     {                                 
  455.     SIZEF  sizfx ;
  456.                                                    
  457.     sizfx.cx = MAKEFIXED(width,0);
  458.     sizfx.cy = MAKEFIXED(height,0);
  459.     
  460.     GpiSetCharBox(hps,&sizfx);
  461.     
  462.     return;
  463.     }
  464.  
  465.  
  466. /******************************************************************************
  467. Function:       do_paste()
  468.  
  469. Description:    Performs the "paste" operation.  Transfers any text in the
  470.                 clipboard to the keyboard input buffer.
  471.                 
  472.                 Pauses after a CR to let kermit catch up!
  473.  
  474. Syntax:         int do_paste(HAB hab)
  475.  
  476. Returns:        0 if successful
  477.                 1 if not
  478.  
  479. Mods:           01-Apr-90 C.P.Armstrong created
  480.                 02-Apr-90 C.P.Armstrong Filters out the LFs which cause problems
  481.                         see *           with the asshole VMS editors.
  482.                 11-Apr-90 C.P.Armstrong Single LFs replace by CRs.  Paste text 
  483.                         see **          from the OS/2 1.2 system editor causes
  484.                                         errors similar to those caused by LFs.
  485.                                         Function moved to ckopm4 as the addition
  486.                                         of two lines causes MSC5.1 to barf on
  487.                                         this function - even if two massive ones
  488.                                         are removed from ckopm3!!!!!  Gimme
  489.                                         v6.00....... (for ever hopeful)
  490.                 20-Apr-90 C.P.Armstrong Removed the wait after CR. Waiting
  491.                                         didn't help as PM couldn't process in-
  492.                                         coming text thus holding up the other
  493.                                         threads.  The wait is now done in the
  494.                                         "conect" thread leaving PM free to
  495.                                         process incoming print messages.
  496.                                 *       Turns out LFs are supplied by the vt100
  497.                                         routines when a CR is received and LF
  498.                                         alone causes a backspace with VMS 
  499.                                         editors(!) resulting in long lines...
  500.                                  **     The OS/2 system editor does not insert
  501.                                         CRs or LFs in wrap mode resulting in
  502.                                         very long lines which cause the VMS
  503.                                         editors to choke.
  504. ******************************************************************************/
  505. do_paste(HAB hab)
  506.     {
  507.     extern char far * copyb;
  508.     extern int pasting;
  509.     int siz;
  510.     SEL sel;
  511.     char far * clipb;
  512.  
  513.     if(copyb!=NULL)             /* Copyb is allocated - pasting in progress */
  514.         return(-1);
  515.  
  516.     if(!WinOpenClipbrd(hab))     /* Open the clipboard */
  517.         {
  518.         pm_err("Failed to open clipboard");
  519.         return(1);
  520.         }
  521.  
  522.  
  523.     copyb=NULL;
  524.     if( (sel = (SEL) WinQueryClipbrdData(hab,CF_TEXT)) )
  525.         {
  526.         clipb = MAKEP( sel,0 );   /* Convert selector to pointer to text */
  527.         siz = strlen(clipb)+1;    /* Get length of text already there    */
  528.         if( (copyb=malloc(siz))!=NULL)
  529.             {
  530.             strcpy(copyb,clipb);  /* Copy clipboard text to buffer */          
  531.             }
  532.         }
  533.  
  534.         WinCloseClipbrd(hab);     /* Close the clipboard */
  535.  
  536.     /* If there was any text, and we copied it okay, copyb is not NULL */
  537.     if(copyb!=NULL)               /* For Kermit simply put it into the */
  538.         {                         /* keyboard buffer.                  */
  539.         pasting=1;                /* Tell buff_empty we are using paste buf */
  540.         buff_insert(0);           /* trigger buff_empty.                    */
  541.         }
  542.  
  543.     return(0);
  544.     }
  545.  
  546. /******************************************************************************
  547. Function:       get_paste_char()
  548.  
  549. Description:    Gets characters out of the paste buffer
  550.  
  551. Syntax:         int get_paste_char()
  552.  
  553. Returns:        The character or -1 if the buffer is empty
  554.  
  555. Mods:           24-Apr-90 C.P.Armstrong created
  556.  
  557. ******************************************************************************/
  558. int get_paste_char()
  559.     {
  560.     extern char far * copyb;
  561.     extern int pasting;
  562.     static int next=0;
  563.     char next_c;
  564.     
  565.     if(copyb==NULL)
  566.         return(-1);
  567.  
  568. //    if(next>0)              /* Convert lone LFs to CRs */
  569. //        {
  570. //        if((copyb[next]==10) && (copyb[next-1]!=13))
  571. //            copyb[next]=13;
  572. //        }
  573.  
  574.     if(copyb[next]==10)     /* Skip the LF in CRLFs */
  575.         next++;
  576.  
  577.     next_c=copyb[next];
  578.     
  579.     if(next_c==0)           /* If we've reached the end clean up */
  580.         {
  581.         next_c=-1;
  582.         next=0;
  583.         free(copyb);
  584.         pasting=0;
  585.         copyb=NULL;
  586.         }
  587.     else
  588.         next++;
  589.         
  590.     return(next_c);
  591.     }
  592.  
  593.  
  594.  
  595.  
  596. /* Requires INCL_DOSERRORS and INCL_VIO */
  597. int mark_start_row;     /* Start row of Vio marked block */
  598. int mark_start_col;     /* Start col of Vio marked block */
  599. int mark_end_row;     /* Start row of Vio marked block */
  600. int mark_end_col;     /* Start col of Vio marked block */
  601. int marking;            /* 0 if not marking,             */
  602.                         /* 1 if doing mark,              */
  603.                         /* 2 if block marked             */
  604. int direct;             /* direction of marking */
  605. int mcaptive;           /* 1 if mouse is captured */
  606.  
  607. int start_mark(HWND hwnd,MPARAM mp1,MPARAM mp2,HVPS hvps)
  608.     {
  609.     extern int mark_start_row;  /* Position of the start of the marked block */
  610.     extern int mark_start_col;  
  611.     extern int mark_end_row;
  612.     extern int mark_end_start;
  613.     extern int marking;
  614.     extern int direct;
  615.     extern int mcaptive;
  616.  
  617.     /* Unhighlight any current marked range */
  618.     direct=1;
  619.     if(marking==2)
  620.         range_reverse(mark_start_row,mark_start_col,mark_end_row,mark_end_col,
  621.             direct,hvps);
  622.  
  623.     mouse_to_curpos(SHORT1FROMMP(mp1),SHORT2FROMMP(mp1),
  624.         &mark_start_row,&mark_start_col,hvps,hwnd);
  625.     
  626.     mark_end_row = mark_start_row;
  627.     mark_end_col = mark_start_col;   
  628.  
  629.     direct=0;
  630.     marking = 1;
  631.     
  632.     /* Capture the mouse */
  633.     WinSetCapture(HWND_DESKTOP,hwnd);
  634.     mcaptive=1;
  635.     return(0);
  636.     }
  637.     
  638. int end_mark(HWND hwnd,MPARAM mp1,MPARAM mp2,HVPS hvps)
  639.     {
  640.     extern int mark_end_row;  /* Position of the end of the marked block */
  641.     extern int mark_end_col;  
  642.     extern int marking;
  643.     int temp;
  644.  
  645.     
  646.  
  647.     do_mark(hwnd,mp1,mp2,hvps);
  648.  
  649.     /* Free up the mouse */
  650.     WinSetCapture(HWND_DESKTOP, NULL) ;
  651.     mcaptive=0;
  652.  
  653.     if(mark_end_row==mark_start_row && mark_end_col==mark_start_col)
  654.         {
  655.         marking=0;
  656.         return(0);
  657.         }
  658.  
  659.  
  660.     /* Make sure point one is "higher" than point 2 */
  661.     if( ((mark_end_row==mark_start_row) && (mark_end_col<mark_start_col)) || 
  662.         (mark_end_row<mark_start_row) )
  663.         {
  664.         temp = mark_end_row;
  665.         mark_end_row = mark_start_row;
  666.         mark_start_row = temp;
  667.         
  668.         temp = mark_end_col;
  669.         mark_end_col = mark_start_col;
  670.         mark_start_col = temp;
  671.         }
  672.     marking = 2;                                      
  673.  
  674.     return(0);
  675.     }
  676.     
  677. int quit_mark(HWND hwnd,MPARAM mp1, MPARAM mp2,HVPS hvps, HAB hab)
  678.     {
  679.     extern int marking;
  680.     if(marking!=0)  
  681.         {
  682.         end_mark(hwnd,mp1,mp2,hvps);
  683.         do_copy(0,hvps,hab);
  684.         }
  685.     return(0);
  686.     }
  687.  
  688.  
  689. /******************************************************************************
  690. Function:       do_mark()
  691.  
  692. Description:    Marks an area of screen according to the mouse position.
  693.  
  694. Syntax:         int do_mark(HWND hwnd,MPARAM mp1,MPARAM mp2,HVPS hvps)
  695.  
  696. Returns:        0
  697.  
  698. Mods:           01-Apr-90 C.P.Armstrong created
  699.  
  700. ******************************************************************************/
  701. int do_mark(HWND hwnd,MPARAM mp1,MPARAM mp2,HVPS hvps)
  702.     {
  703.     extern int mark_start_row;  /* Position of the start of the marked block */
  704.     extern int mark_start_col;  
  705.     extern int mark_end_row;
  706.     extern int mark_end_col;
  707.     extern int marking;
  708.     extern int direct;
  709.  
  710.     int currow,curcol,temp;     /* Current cursor position */
  711.     int atsrow,atscol,atecol,aterow;
  712.     int newdirect;
  713.     int wasa,nowa;
  714.     int diroff; /* Another fudge factor.  Having marked forwards and are now
  715.                    marking back must not rehighlite current chart until we pass
  716.                    the orig place! */
  717.  
  718.  
  719.     if(marking!=1)              /* Not marking a block! */
  720.         return(0);
  721.  
  722.     mouse_to_curpos(SHORT1FROMMP(mp1),SHORT2FROMMP(mp1),
  723.         &currow,&curcol,hvps,hwnd);
  724.  
  725.     /* Has cursor moved a character position */
  726.     if( (currow==mark_end_row) && (curcol==mark_end_col) )
  727.         return(0);   
  728.  
  729.     if( ((currow==mark_end_row) && (curcol<=mark_end_col)) || 
  730.         (currow<mark_end_row) )
  731.         newdirect = -1;
  732.     else
  733.         newdirect = 1;
  734.  
  735.     /* are we above the start */
  736.     if( (currow==mark_start_row && curcol<mark_start_col) 
  737.         || currow<mark_start_row )
  738.         nowa=1;
  739.     else
  740.         nowa=0;
  741.         
  742.     /* Were we above the start */
  743.     if( (mark_end_col<mark_start_col && mark_end_row==mark_start_row)
  744.         || mark_end_row<mark_start_row)
  745.         wasa=1;
  746.     else
  747.         wasa=0;
  748.  
  749.     /* Avoid having the start char erased in a move from above to below start */
  750.     /* or a move from below to above */
  751.     /* this is a real kludge.  It double highlights the initial pos, leaving  */
  752.     /* it the same!                                                           */
  753.     if(wasa!=nowa && direct!=0)
  754.         {
  755.         range_reverse(mark_start_row,mark_start_col,mark_start_row,mark_start_col,
  756.             1,hvps);
  757.         }
  758.  
  759.  
  760.     if( (nowa && (!wasa)  && direct!=0) ||
  761.              ((!nowa) && wasa && direct!=0))
  762.         diroff=0;
  763.     else if(nowa && newdirect==1 && direct!=0) /* above, going forward */
  764.         diroff=-1;
  765.     else if((!nowa) && newdirect==-1 && direct!=0)/* below, going back */
  766.         diroff=1;
  767.     else if(direct!=0)
  768.         {
  769.         mark_end_col+=newdirect;
  770.         diroff=0;
  771.         }
  772.     else
  773.         {
  774.         diroff=0;
  775.         }
  776.  
  777.     direct=newdirect;
  778.  
  779.     /* Do mainmark! */
  780.     range_reverse(mark_end_row,mark_end_col,currow,curcol+diroff,direct,hvps);
  781.  
  782.  
  783.     /* Update the previous position */
  784.     mark_end_col = curcol;
  785.     mark_end_row = currow;
  786.  
  787.     /* If back at orig pos, make sure it gets highlit if cursor is moved */
  788.     /* Now needs to be specifically unhighlighted as well */
  789.     if( (mark_start_row==mark_end_row) && (mark_start_col==mark_end_col) )
  790.         {
  791.         range_reverse(mark_start_row,mark_start_col,mark_start_row,mark_start_col,
  792.             1,hvps);
  793.         direct=0;
  794.         }
  795.  
  796.     return(0);
  797.     }                                 
  798.  
  799.  
  800.  
  801. /*
  802. Mode = 0   - Erase marked block - do not copy it
  803. Mode = 1   - If block marked then clear clipboard, copy marked block to it
  804. Mode = 2   - If block marked then append marked block to any text present
  805. */
  806. do_copy(int mode, HVPS hvps, HAB hab)
  807.     {
  808.     extern int mark_start_row;  /* Position of the start of the marked block */
  809.     extern int mark_start_col;  
  810.     extern int mark_end_row;
  811.     extern int mark_end_col;
  812.     extern int marking;
  813.  
  814.     char far * block;
  815.  
  816.     
  817.  
  818.     if(mode>0)
  819.         {
  820.         if(marking!=2)
  821.             return(0);
  822.         /* Get the marked block */
  823.         if( (block = copy_block(mark_start_row,mark_start_col,
  824.                            mark_end_row,mark_end_col,hvps)) !=NULL)
  825.             {
  826.             fill_clipboard(block,mode,hab);
  827.             }
  828.         }
  829.  
  830.     /* Un mark the block */
  831.     range_reverse(mark_start_row,mark_start_col,mark_end_row,mark_end_col,
  832.         1,hvps);
  833.     marking=0;
  834.  
  835.     return(0);
  836.     }
  837.  
  838.  
  839. /******************************************************************************
  840. Function:       copy_block()
  841.  
  842. Description:    Copies the defined Vio block to the clipboard in text format 
  843.                 only.  If mode is 0 the previous contents are deleted.  If
  844.                 mode is 1 then the copied block is appended to the existing
  845.                 text in the clipboard.
  846.                 Note the the block coords must have the start character coords
  847.                 higher (nearer the top, above, to the left of etc.) the
  848.                 end character coords.
  849.  
  850.                 This routine uses a CRLF sequence delimit lines.  The PETZOLD
  851.                 clipboard example requires CRLF to produce correct newlines
  852.                 so I've chosen to use this as the "standard".... mainly because
  853.                 it's what I'm using to test the copy_block function!
  854.                 
  855.                 A pointer to the string block is now returned.  This is not
  856.                 sharable memory.  It should be "free()"d after use as it is
  857.                 allocated using malloc().
  858.  
  859. Syntax:         char * copy_block(strow,stcol,enrow,encol,hvps)
  860.                     int strow,stcol;   First character in block
  861.                     int enrow,encol;   Last character in block
  862.                     HVPS hvps;         AVIO handle to vio screen.
  863.  
  864. Returns:        NULL if an error occurs
  865.                 Pointer to the NUL terminated string block.
  866.  
  867. Mods:           31-Mar-90 C.P.Armstrong created
  868.                 01-Apr-90 C.P.Armstrong Returns pointer to string block.
  869.  
  870. ******************************************************************************/
  871. char * copy_block(strow,stcol,enrow,encol,hvps)
  872.     int strow,stcol;   /* First character in block */
  873.     int enrow,encol;   /* Last character in block */
  874.     HVPS hvps;         /* AVIO handle to vio screen. */
  875.     {
  876.     int sw,sh;          /* Vio screen dims */
  877.     
  878.     char far * cblk;    /* Area for the copied block */
  879.     USHORT off;         /* offset into buffer */
  880.     USHORT get;         /* no. chars to get/got */
  881.     USHORT siz;         /* Size of copied block */
  882.     
  883.     /* First get screen dims */
  884.     if(get_viops_size(&sw, &sh,hvps)!=0)
  885.         return(NULL);
  886.         
  887.     /* Calc size of block in chars with all lines except last terminated by */
  888.     /* a CR and the whole block NUL terminated.                             */
  889.     if(enrow==strow)
  890.         siz = encol-stcol+2;            /* No. chars plus NUL */
  891.     else
  892.         {
  893.         siz = ((enrow-strow-1)*(sw+2)); /* No. full lines and CRLFs */
  894.         siz += (sw-stcol+2);            /* No. chars on first line + CRLF */
  895.         siz += (encol)+2;               /* No. chars on last line plus NUL */
  896.         }
  897.  
  898.     /* Malloc the block - return NULL if we can't */
  899.     if( (cblk = (char far *) malloc(siz))==NULL)
  900.         return(NULL);
  901.  
  902.  
  903.     /* Read the block a line at a time into cblk, inserting CRs at the end of */
  904.     /* all but the last line.                                                 */
  905.     if(enrow==strow)    /* Less than one line is special case */
  906.         {
  907.         get = encol-stcol+1;
  908.         VioReadCharStr(cblk,&get,strow,stcol,hvps);
  909.         cblk[get]='\0';
  910.         }
  911.     else
  912.         {
  913.         /* First line */
  914.         get = sw-stcol;
  915.         VioReadCharStr(cblk,&get,strow,stcol,hvps);
  916.         off=0;
  917.         do
  918.             {
  919.             do                      /* Trim trailing blanks */
  920.                 {
  921.                 get--;
  922.                 }while((cblk[off+get]==' ') && (get>0));
  923.                                     /* off+get now points to last character */                
  924.  
  925.             cblk[off + (++get)]=13; /* Terminate previous string */
  926.             cblk[off + (++get)]=10;
  927.             off += (get+1);         /* Offset of next string in memory block*/
  928.             strow++;                /* Next row */
  929.             get = (strow==enrow)? encol+1 : sw;
  930.             VioReadCharStr(&cblk[off],&get,strow,0,hvps);
  931.             }while(strow<enrow);
  932.         cblk[off+get]='\0';         /* Nul terminate the string */
  933.         }
  934.  
  935.     return(cblk);    
  936.     }
  937.  
  938. /******************************************************************************
  939. Function:       fill_clipboard()
  940.  
  941. Description:    Transfers a block of marked text to the clipboard.
  942.                 In mode 1 the existing clipboard data is erased.
  943.                 In mode 2 the new text is added to at the end of any existing
  944.                 text in the clipboard.
  945.  
  946. Syntax:         int fill_clipboard(char far * block,int mode,HAB hab)
  947.  
  948. Returns:        0 for success
  949.                 1 if an error occurs
  950.  
  951. Mods:           01-Apr-90 C.P.Armstrong created
  952.  
  953. ******************************************************************************/
  954. int fill_clipboard(char far * block,int mode,HAB hab)
  955.     {
  956.     SEL sel;
  957.     char far * clipb;
  958.     char far * cblk;
  959.     int siz;
  960.  
  961.  
  962.     if(!WinOpenClipbrd(hab))     /* Open the clipboard */
  963.         {
  964.         pm_err("Failed to open clipboard");
  965.         return(1);
  966.         }
  967.  
  968.     siz=0;
  969.     clipb = NULL;
  970.     if(mode==2)                 /* Mode 2 = append */
  971.         {
  972.         if( (sel = (SEL) WinQueryClipbrdData(hab,CF_TEXT)) )
  973.             {
  974.             clipb = MAKEP( sel,0 );   /* Convert selector to pointer to text */
  975.             siz = strlen(clipb)+1;    /* Get length of text alredy there     */
  976.             }
  977.         }
  978.  
  979.     /* Add size of new text */
  980.     siz += strlen(block)+1;          /* Note, if appending the memory block  */
  981.                                      /* will be 1 too big - but who cares!   */
  982.  
  983.     /* Allocate the shared seg to give to clipboard */
  984.     if(DosAllocSeg(siz, &sel, SEG_GIVEABLE)!=0)
  985.         {
  986.         WinCloseClipbrd(hab);       /* Must close the clipboard */
  987.         return(1);
  988.         }
  989.         
  990.     /* Convert shared segment selector to pointer */
  991.     cblk = MAKEP(sel,0); 
  992.     cblk[0]=0;
  993.  
  994.     /* If clipb has been set we should copy its text first */
  995.     if(clipb != NULL)
  996.         strcpy(cblk,clipb);
  997.  
  998.     /* Now add in the new marked block */
  999.     strcat(cblk,block);
  1000.  
  1001.     /* Free the marked block */
  1002.     free(block);
  1003.  
  1004.     /* Empty the clipboard */ 
  1005.     if(!WinEmptyClipbrd(hab))
  1006.         pm_err("Failed to empty clipboard");          
  1007.  
  1008.     /* Now set it to the new stuff */
  1009.     if(!WinSetClipbrdData(hab, (ULONG) sel, CF_TEXT, CFI_SELECTOR))
  1010.         pm_err("Failed to place data in clipboard");
  1011.     
  1012.     if(!WinCloseClipbrd(hab)) /* Close clipboard */
  1013.         {
  1014.         pm_err(
  1015.         "You've got real problems now\nWe failed to close the clipboard");        
  1016.         return(1);
  1017.         }
  1018.     
  1019.     return(0);
  1020.     }
  1021.  
  1022.  
  1023. /******************************************************************************
  1024. Function:       mouse_to_curpos()
  1025.  
  1026. Description:    Converts a mouse position into a Vio row/col position.  The
  1027.                 mosue position is relative to the bottom lefthand corner,
  1028.                 the row/col position is relative to the top left corner of
  1029.                 the video buffer. i.e. an Vio origin shift is taken into 
  1030.                 account.
  1031.                 
  1032.                 If the position is outside the window the row/col is adjusted
  1033.                 to be inside the window.
  1034.                 
  1035.                 This function can be used with any window coord in pels.
  1036.  
  1037. Syntax:         int mouse_to_curpos(mousex,mousey,prow,pcol,hvps,hwnd)
  1038.                     int mousex,mousey;  Mouse window x and y pos
  1039.                     int * prow, * pcol; Returned vio cursor pos
  1040.                     HVPS hvps;          handle to the Vio pres space
  1041.                     HWND hwnd;          Handle to the window containing the PS
  1042.  
  1043. Returns:        0
  1044.  
  1045. Mods:           01-Apr-90 C.P.Armstrong created
  1046.  
  1047. ******************************************************************************/
  1048. int mouse_to_curpos(mousex,mousey,prow,pcol,hvps,hwnd)
  1049.     int mousex,mousey;      /* Mouse window x and y pos */
  1050.     int * prow, * pcol;     /* Returned vio cursor pos  */
  1051.     HVPS hvps;              /* handle to the Vio pres space */
  1052.     HWND hwnd;              /* Handle to the window containing the PS */
  1053.     {
  1054.     SIZEL sizl;
  1055.     SWP swp;
  1056.     HDC hdc;
  1057.  
  1058.  
  1059.     /* Get Vio window size and offset within the frame window */
  1060.     WinQueryWindowPos(hwnd,&swp);
  1061.  
  1062.     /* Get the size in pixels of a character */
  1063.     hdc = WinQueryWindowDC(hwnd);
  1064.     DevQueryCaps(hdc, CAPS_CHAR_WIDTH, 2L, (PLONG) &sizl);
  1065.  
  1066.     /* Check mouse is in the window */
  1067.     if(mousey<0)
  1068.         mousey=0;
  1069.     else if(mousey>swp.cy)
  1070.         mousey=swp.cy;
  1071.         
  1072.     if(mousex<0)
  1073.         mousex=0;
  1074.     else if(mousex>swp.cx)
  1075.         mousex=swp.cx;
  1076.  
  1077.     /* Convert mouse pos to top right origin */
  1078.     mousey = swp.cy - mousey;
  1079.  
  1080.  
  1081.     /* Calculate mouse pos in row/cols */
  1082.     mousex = mousex/ (int)sizl.cx;
  1083.     mousey = mousey/ (int)sizl.cy;
  1084.  
  1085.     /* Get the current origin for the Vio screen (top left row/col) */
  1086.     VioGetOrg((PSHORT)prow,(PSHORT)pcol,hvps);
  1087.     
  1088.     /* Add offset to mouse pos */
  1089.     *prow = *prow + mousey;
  1090.     *pcol = *pcol + mousex;
  1091.  
  1092.     return(0);
  1093.     }
  1094.     
  1095. int range_reverse(atsrow,atscol,aterow,atecol,direct,hvps)
  1096.     int atsrow,atscol;  /* Highest position to start from */
  1097.     int aterow,atecol;  /* Postion to go down to          */
  1098.     int direct;      /* Forward or reverse marking */
  1099.     HVPS hvps;          /* Handle of screen PS */
  1100.     {
  1101.     extern int scrwidth;  /* This is needed until we find a way of determining it */
  1102.     int  atsz;
  1103.     unsigned char attbuf[3];
  1104.  
  1105.     /* Make sure the last one gets highlit */
  1106.     atecol+=direct;
  1107.                   
  1108.     do
  1109.         {
  1110.         atsz=2;
  1111.         if(VioReadCellStr(attbuf,(PUSHORT)&atsz,atsrow,atscol,hvps)
  1112.           ==ERROR_VIO_COL)
  1113.             {
  1114.             atsrow+=direct;
  1115.             atscol=(direct==1) ? 0 : scrwidth-1;
  1116.             }
  1117.         else
  1118.             {
  1119.             attbuf[3] = (attbuf[1] << 4) + (attbuf[1] >> 4);
  1120.             attbuf[1] = attbuf[3];
  1121.             if(VioWrtCellStr(attbuf,2,atsrow,atscol,hvps)!=0)
  1122.                 return(0);
  1123.             atscol+=direct;
  1124.             }
  1125.         }while( (atscol!=atecol) || (atsrow!=aterow));
  1126.  
  1127.     return(0);
  1128.     }
  1129.  
  1130. /******************************************************************************
  1131. Function:       get_viops_size()
  1132.  
  1133. Description:    Determines the dimensions of a Vio screen.  VioGetMode is
  1134.                 supposed to do this but it doesn't work with an AdvancedVIO
  1135.                 presentatoin space handle.  This function uses the 
  1136.                 VioReadCharStr() error messages to determine the screen size.
  1137.  
  1138. Syntax:         int get_viops_size(width,height,hvps)
  1139.                     int* width;
  1140.                     int* height;
  1141.                     HVPS hvps;
  1142.  
  1143. Returns:        1 if an unexpected error occurs
  1144.                 0 if okay
  1145.  
  1146. Mods:           30-Mar-90 C.P.Armstrong created
  1147.  
  1148. ******************************************************************************/
  1149. int get_viops_size(int* width, int* height,HVPS hvps)
  1150.     {
  1151.     USHORT row,col,sz;
  1152.     USHORT err;
  1153.     char attr;
  1154.         
  1155.     row=1;
  1156.     col=1;
  1157.  
  1158.     /* Do the width first, step 2 at once for speed */
  1159.     do
  1160.         {
  1161.         sz=1;
  1162.         }while( (err=VioReadCharStr(&attr,&sz,row,col+=2,hvps))==0);
  1163.         
  1164.      if(err!=ERROR_VIO_COL)
  1165.         return(1);
  1166.      
  1167.      sz=1;
  1168.      col--;
  1169.      /* See if we've gone 1 too far */
  1170.      if(VioReadCharStr(&attr,&sz,row,col,hvps)!=0)
  1171.         col--;
  1172.      
  1173.     /* Now do the height */
  1174.     do
  1175.         {
  1176.         sz=1;
  1177.         }while( (err=VioReadCharStr(&attr,&sz,row+=2,col,hvps))==0);
  1178.         
  1179.      if(err!=ERROR_VIO_ROW)
  1180.         return(1);
  1181.      
  1182.      sz=1;
  1183.      row--;
  1184.      
  1185.      /* See if we've gone 1 too far */
  1186.      if(VioReadCharStr(&attr,&sz,row,col,hvps)!=0)
  1187.         row--;
  1188.  
  1189.     *width=  ++col;     /* We want no. of characters, not max positions */
  1190.     *height= ++row;
  1191.     return(0);
  1192.     }
  1193.  
  1194. /******************************************************************************
  1195. Function:       pc_paint_thread()
  1196.  
  1197. Description:    The thread which does the painting for the Gpi window
  1198.                 Special situations of which this function must be told;
  1199.                     1 About to clear the plot list.
  1200.                     2 Want to do a repaint so stop any repaint in progress
  1201.                     3 Program ending.
  1202.  
  1203. Syntax:         void far pc_paint_thread()
  1204.  
  1205. Returns:        nothing
  1206.  
  1207. Mods:           13-Feb-90 C.P.Armstrong created
  1208.  
  1209. ******************************************************************************/
  1210. void far pc_paint_thread(struct pc_paint * pc_p)
  1211.     {
  1212. //    extern ULONG paint_sem;          /* Set when repaint desired */
  1213. //    extern ULONG stop_painting_sem;  /* Set when about to clear */
  1214. //    extern SWP pc_swp;
  1215. //    extern struct plot_command pcroot;
  1216. //    extern char minied;
  1217. //    extern HPS gpi_hps;
  1218.     extern COLOR pmfgcol;
  1219.     extern HWND hwndGraph;
  1220.  
  1221.     HPS hps;
  1222.     HAB painthab;
  1223.     int count;
  1224.  
  1225.     struct plot_command * pcc;
  1226.  
  1227.     painthab=WinInitialize(0);
  1228.  
  1229.     DosSemSet(&(pc_p->StartPaintSem)); /* Make sure semaphore is set before */
  1230.                                        /* entering the loop */
  1231.     /* Clear the EndPaintThread sem so caller knows we are running */
  1232.     DosSemClear(&(pc_p->EndPaintThread));
  1233.     while(TRUE)
  1234.         {
  1235.         /* Wait for it to repaint request */
  1236.         DosSemWait(&(pc_p->StartPaintSem),SEM_INDEFINITE_WAIT);
  1237.         hps = WinGetPS(pc_p->hwnd);
  1238.  
  1239.         /* Set parameters for this incarnations of the PS */
  1240.         GpiSetColor(hps,pc_p->fgcol);
  1241.  
  1242.         if(pc_p->fnt != NULL)
  1243.             {
  1244.             SelectFont(hps, LCID_TEKFONT, 
  1245.               pc_p->fnt->name,pc_p->fnt->vect,pc_p->fnt->h,pc_p->fnt->w);
  1246.  
  1247.             /* Size the font */
  1248.             SetCharBox(hps, 
  1249.               MAXCHARWIDTH* pc_p->pc_swp.cx/MAXXRES, 
  1250.               MAXCHARHEIGHT* pc_p->pc_swp.cy/MAXYRES);
  1251.             }
  1252.  
  1253.         pcc=(pc_p->root);                           /* Do the painting */
  1254.         count=0;
  1255.         do
  1256.             {
  1257.             pc_interp(*pcc,&(pc_p->pc_swp),0,hps);
  1258.             pcc = pcc->next;
  1259.             }
  1260.         while((pcc != NULL)
  1261.          && (DosSemWait(&(pc_p->StopPaintSem),SEM_IMMEDIATE_RETURN)==0));
  1262.  
  1263.  
  1264.         WinReleasePS(hps);
  1265.         DosSemSet(&(pc_p->StartPaintSem));               /* Reset it */
  1266.  
  1267.         /* Set the StopPaint to ack that we've stopped */
  1268.         if(DosSemClear(&(pc_p->StopPaintSem))!=0)
  1269.             dbprintf("pc_paint_thread - Error clearing StopPaintSem\n");
  1270.  
  1271.         dbprintf("Repainting finished\n");
  1272.         }
  1273.  
  1274.     dbprintf("pc_paint_thread finishing\n");
  1275.     WinTerminate(painthab);
  1276.     DosEnterCritSec();
  1277.     DosSemClear(&(pc_p->EndPaintThread));
  1278.     DosExit(EXIT_THREAD,0);        /* This will also do a DosExitCritSec */
  1279.     }
  1280.