home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / s12628.zip / PMACCESS.C < prev    next >
C/C++ Source or Header  |  1990-07-01  |  26KB  |  772 lines

  1. /* pmaccess.c RHS
  2.  *
  3.  * application that uses PMSERVER for accessing PM services
  4.  *
  5.  *
  6.  */
  7.  
  8. #define    INCL_SUB
  9. #define    INCL_DOSERRORS
  10. #define    INCL_DOS
  11. #include<os2.h>
  12. #include<mt\stdio.h>
  13. #include<mt\string.h>
  14. #include<mt\stdlib.h>
  15. #include<mt\process.h>
  16. #include<mt\dos.h>
  17. #include"mou.h"
  18. #include"kbd.h"
  19. #include"pmserver.h"
  20. #include"moudefs.h"
  21. #include"kbddefs.h"
  22. #include"msgq.h"
  23. #include"button.h"
  24. #include"errexit.h"
  25. #include"msgs.h"
  26.  
  27. #define     MAINMSGQUEUE    "\\QUEUES\\PMLITE.QUE"
  28.  
  29. #define     VIOHDL                  0
  30. #define     KEYTHREADSTACK          500         // keyboard stack
  31. #define     REQUESTTHREADSTACK      500         // request stack
  32. #define     MOUTHREADSTACK          800         // mouse stack
  33.  
  34. #define     BORDERCOL               79
  35. #define     BORDERROW               17
  36. #define     BORDERROW2              21
  37. #define     STARTROW                0
  38. #define     ENDROW                  20
  39.  
  40. #define     BUTTON_ON               0x70
  41. #define     BUTTON_OFF              0x0f
  42. #define     NORMAL                  BUTTON_OFF
  43. #define     HIGHLIGHT               BUTTON_ON
  44.  
  45. #define     beep()                  DosBeep(440,200)
  46. #define     Lastchar(str)           (str[strlen(str)-1])
  47.  
  48. #define     MAXREQUESTCOUNT         10
  49. #define     REQUESTTHREADSLEEPTIME  3000L
  50.  
  51.     /********************* Buttons ****************************/
  52.  
  53. #define     BUTTONLIST              13
  54. BUTTON buttonlist[BUTTONLIST] =
  55.     {
  56. /* text  title  row,col,row,col,attr,     type  left val, right val,
  57.         accelerator    */
  58. {"                         ","Application Name",
  59.               18,16,  0, 0, BUTTON_OFF, INPUT,  MSG_APPNAME,
  60.             MSG_APPNAME,
  61.         ALT_1,  0},
  62. {"                 ",       "Topic Name",
  63.               18,43,  0, 0, BUTTON_OFF, INPUT,  MSG_TOPICNAME,
  64.             MSG_TOPICNAME,
  65.         ALT_2,  0},
  66. {"               ",         "Item Name",
  67.               18,62,  0, 0, BUTTON_OFF, INPUT,  MSG_ITEMNAME,
  68.             MSG_ITEMNAME,
  69.         ALT_3,  0},
  70. {"Copy","",   22, 0, 0, 0,  BUTTON_OFF, BPRESS, MSG_COPY,   MSG_COPY,
  71.         ALT_O,  0},
  72. {"Cut","",    22, 7, 0, 0,  BUTTON_OFF, BPRESS, MSG_CUT,    MSG_CUT,
  73.         ALT_U,  0},
  74. {"Paste","",  22,13, 0, 0,  BUTTON_OFF, BPRESS, MSG_PASTE, MSG_PASTE,
  75.         ALT_P,  0},
  76. {"Initiate","",22,23,0, 0,  BUTTON_OFF, BPRESS, MSG_INIT,   MSG_INIT,
  77.         ALT_I,  0},
  78. {"Request","",22,34, 0, 0,  BUTTON_OFF, BPRESS, MSG_REQUEST,
  79.             MSG_REQUEST,
  80.         ALT_R,  0},
  81. {"Advise","", 22,44, 0, 0,  BUTTON_OFF, BPRESS, MSG_ADVISE,
  82.             MSG_ADVISE,
  83.         ALT_A},
  84. {"Terminate","",22,53,0,0,  BUTTON_OFF, BPRESS, MSG_TERM,   MSG_TERM,
  85.         ALT_T,  0},
  86. {"Clear","",  22,67, 0, 0,  BUTTON_OFF, BPRESS, MSG_CLR,    MSG_CLR,
  87.         ALT_C,  0},
  88. {"Esc","",    22,75, 0, 0,  BUTTON_OFF, BPRESS, MSG_ESCAPE,
  89.             MSG_ESCAPE,
  90.         ESC,    0},
  91. {NULL,   0,     0, 0, 0,  0,          0,      0,          0,
  92.                 0,      0}
  93.     };
  94.  
  95.     /**********************************************************/
  96.  
  97. typedef struct _screen_label
  98.     {
  99.     PCHAR   text;
  100.     SHORT   row;
  101.     SHORT   column;
  102.     } SCREEN_LABEL;
  103.  
  104. #define SCREEN_LABELS 4
  105. SCREEN_LABEL screen_labels[SCREEN_LABELS] =
  106.     {
  107.     {"Clipboard Functions",     BORDERROW2,     1},
  108.     {"DDE Functions",           BORDERROW2,     35},
  109.     {"Gen'l",                   BORDERROW2,     72},
  110.     {"DDE Parameters:",         BORDERROW+2,      0}
  111.     };    
  112.  
  113. PCHAR mainmsgqueue = MAINMSGQUEUE;
  114. BYTE MouThreadStack[MOUTHREADSTACK];
  115. BYTE KbdThreadStack[KEYTHREADSTACK];
  116. BYTE RequestThreadStack[REQUESTTHREADSTACK];
  117.  
  118. long MouSem = 0L, KbdSem = 0L;
  119.  
  120. unsigned    BlankCell = 0x0f20;
  121. USHORT  dirrow = BORDERROW;
  122.  
  123. USHORT  DDEstartrow,DDEstartcol,DDEendrow,DDEendcol;
  124. USHORT  rowBlockBeg,colBlockBeg,startBlock,ScreenRows,ScreenCols,
  125.         blocksize;
  126. USHORT  startrow,startcol,endrow,endcol;
  127. BYTE    highlight_att = HIGHLIGHT,normal_att = NORMAL;
  128. PBYTE   blockptr, bufptr;
  129. HQUEUE  pmshdl;
  130.  
  131. BYTE    tempbuffer[8192];
  132. USHORT  clipboard_data = TRUE, dde_init = FALSE, Server = FALSE;
  133. PIDINFO pidinfo;
  134. char appname[MAXAPPNAME], topicname[MAXTOPICNAME],
  135.         itemname[MAXITEMLEN];
  136. BUTTON  *app, *topic, *item;
  137.  
  138.     /********************* Function Prototypes ********************/
  139.  
  140. void    main(void);
  141. void    RequestThread(void);
  142. void    InitScreen(void);
  143. void    SetBlock(USHORT row, USHORT col);
  144. void    ResetScreen(void);
  145. void    BlankBlock(void);
  146. void    ResetBlock(void);
  147.  
  148. void    ButtonPress(USHORT *eventcode);
  149. USHORT  prepare_CLPBRDblock(void);
  150. void    PMS_Init(HQUEUE serverhandle,char *qname);
  151. void    PMS_Terminate(HQUEUE serverhandle);
  152. USHORT  readtextblock(PCHAR buffer,
  153.         USHORT srow, USHORT scol, USHORT erow, USHORT ecol);
  154.  
  155. void    activate_entrybutton(BUTTON *b, char *buttonfield);
  156.  
  157. void main(void)
  158.     {
  159.     USHORT pause = 0, msg, capture, valid_block, msgsize, retval, i;
  160.     USHORT post_on = FALSE,row,col;
  161.     HQUEUE qhandle;
  162.     PVOID  *msgdata;
  163.     BUTTON *b;
  164.     PBYTE   p;
  165.  
  166.     app = &buttonlist[0];
  167.     topic = &buttonlist[1];
  168.     item = &buttonlist[2];
  169.  
  170.     *appname = *topicname = *itemname = '\0';
  171.  
  172.     DosGetPID(&pidinfo);                        // get process id
  173.     MsgQCreate(&qhandle,MAINMSGQUEUE);
  174.     if(retval = MsgQOpen(&pmshdl,PMSERVERQUE))
  175.         error_exit(retval,
  176.         "MsgQOpen - PM Server probably hasn\'t started...");
  177.  
  178.     DosSemSet(&MouSem);
  179.     DosSemSet(&KbdSem);
  180.     
  181.                                                 //start other threads
  182.     if(_beginthread(MouThread,MouThreadStack,
  183.             sizeof(MouThreadStack),NULL) == -1)
  184.         error_exit(0,"_beginthread(Mouse)");
  185.     if(_beginthread(KbdThread,KbdThreadStack,
  186.             sizeof(KbdThreadStack),NULL) == -1)
  187.         error_exit(0,"_beginthread(Keyboard)");
  188.     if(_beginthread(RequestThread,RequestThreadStack,
  189.             sizeof(RequestThreadStack),NULL) == -1)
  190.         error_exit(0,"_beginthread(Request)");
  191.     
  192.     DosSemWait(&MouSem,SEM_INDEFINITE_WAIT);    // get threads going
  193.     DosSemWait(&KbdSem,SEM_INDEFINITE_WAIT);
  194.  
  195.     InitButtons();
  196.     InitScreen();
  197.     DisplayButtons();
  198.     VioGetBuf((PULONG)&bufptr, &msg, VIOHDL);
  199.     PMS_Init(pmshdl,MAINMSGQUEUE);
  200.  
  201.     while(TRUE)
  202.         {
  203.         MsgQGet(qhandle, &msgdata, &msgsize, &msg);
  204.  
  205.         if(ButtonEvent(msg))
  206.             ButtonPress(&msg);
  207.  
  208.         switch(msg)
  209.             {
  210.             case MSG_ESCAPE:
  211.             case ESC:
  212.                 MsgQClose(qhandle);             // close queue
  213.                                                 // clear the screen
  214.                 VioScrollUp(0,0,-1,-1,-1,(char *)&BlankCell,VIOHDL);
  215.                 PMS_Terminate(pmshdl);
  216.                 DosExit(EXIT_PROCESS,0);        // get out of Dodge
  217.                 break;
  218.  
  219.             case MSG_CLR:                       // clear screen
  220.                 VioScrollUp(0,0,BORDERROW-1,ScreenCols,0xffff,
  221.                     (char *)&BlankCell,VIOHDL);
  222.                 InitScreen();
  223.                 DisplayButtons();
  224.                 VioWrtCharStr(appname,strlen(appname),
  225.                     app->startrow+1,app->startcol+1,VIOHDL);
  226.                 VioWrtCharStr(topicname,strlen(topicname),
  227.                     topic->startrow+1,topic->startcol+1,VIOHDL);
  228.                 VioWrtCharStr(itemname,strlen(itemname),
  229.                     item->startrow+1,item->startcol+1,VIOHDL);
  230.                 MsgQSend(pmshdl,&pidinfo.pid,sizeof(PID),
  231.                     PMS_CLPBRD_QUERY);
  232.                 VioSetCurPos(0,0,VIOHDL);
  233.                 MsgQSend(qhandle,0,0,MSG_RESETINITBUTTON);
  234.                 break;
  235.  
  236.             // ************* Mouse Message handling
  237.             case MSG_B1DOWN:
  238.                 // clear any existing block and set up a new one
  239.                 valid_block = FALSE;
  240.                 ResetScreen();
  241.                 capture = TRUE;
  242.                 rowBlockBeg = MOUMSG(msgdata)->row;
  243.                 colBlockBeg = MOUMSG(msgdata)->col;
  244.                 startBlock = (rowBlockBeg * ScreenCols)+colBlockBeg;
  245.                 SetBlock(rowBlockBeg,colBlockBeg);
  246.                 VioSetCurPos(rowBlockBeg,colBlockBeg,VIOHDL);
  247.                 break;
  248.  
  249.             case MSG_MOUSEMOVED:
  250.                 if(capture)
  251.                     SetBlock(MOUMSG(msgdata)->row,
  252.                         MOUMSG(msgdata)->col);
  253.                 break;
  254.  
  255.             case MSG_B1UP:
  256.                 if(capture)
  257.                     {
  258.                     capture = FALSE;
  259.                     valid_block = TRUE;
  260.                     SetBlock(MOUMSG(msgdata)->row,
  261.                         MOUMSG(msgdata)->col);
  262.                     }
  263.                 break;
  264.  
  265.             case MSG_APPNAME:
  266.                 activate_entrybutton(app,appname);
  267.                 break;
  268.  
  269.             case MSG_ITEMNAME:
  270.                 activate_entrybutton(item,itemname);
  271.                 break;
  272.  
  273.             case MSG_TOPICNAME:
  274.                 activate_entrybutton(topic,topicname);
  275.                 break;
  276.  
  277.             case MSG_RESETINITBUTTON:
  278.                 findbutton("Initiate",&b);
  279.                 ButtonPaint(b,(BYTE)(dde_init ?
  280.                     BUTTON_ON : BUTTON_OFF));
  281.                 break;
  282.  
  283.             case MSG_RESETPASTEBUTTON:
  284.                 findbutton("Paste", &b);
  285.                 ButtonPaint(b,(BYTE)(clipboard_data ?
  286.                     BUTTON_ON : BUTTON_OFF));
  287.                 break;
  288.  
  289.             // ************* Keyboard message handling
  290.             case MSG_CHAR:
  291.                 {
  292.                 int c = KBDMSG(msgdata)->chChar;
  293.  
  294.                 VioGetCurPos(&row,&col,VIOHDL); // get cursor pos.
  295.                 b = IsButton(row,col);
  296.                 if(b)
  297.                     if(c == '\r')
  298.                         break;
  299.                     else if((c == '\b') && (col == b->startcol+1))
  300.                         break;
  301.                 if(!b || ((col > b->startcol) && (col < b->endcol)))
  302.                     VioWrtTTY((PCH)&c,1,VIOHDL);
  303.  
  304.                 switch(c)
  305.                     {
  306.                     case '\b':
  307.                         if(b && (row == b->startcol+1))
  308.                             break;
  309.                         VioWrtTTY(" \b",2,VIOHDL);
  310.                         break;
  311.  
  312.                     case '\r':
  313.                         if(row == ScreenRows)
  314.                             VioScrollUp(0,0,BORDERROW-1,ScreenCols,1,
  315.                                     (char *)&BlankCell,VIOHDL);
  316.                         else
  317.                             VioWrtTTY("\n",1,VIOHDL);
  318.                         break;
  319.                     }
  320.                 }
  321.                 break;
  322.  
  323.             case MSG_UPARROW:
  324.             case MSG_DOWNARROW:
  325.             case MSG_LEFTARROW:
  326.             case MSG_RIGHTARROW:
  327.             case MSG_HOME:
  328.             case MSG_END:
  329.                 {
  330.                 BUTTON *b;
  331.                 USHORT start = 0,end = ScreenCols-1;
  332.  
  333.                 VioGetCurPos(&row,&col,VIOHDL); // get cursor pos.
  334.                 if(b = IsButton(row,col))
  335.                     {
  336.                     start = b->startcol+1;
  337.                     end = b->endcol-1;
  338.                     }
  339.  
  340.                 switch(msg)
  341.                     {
  342.                     case MSG_UPARROW:
  343.                         if(!b && (row > 0))
  344.                             row--;
  345.                         break;
  346.  
  347.                     case MSG_DOWNARROW:
  348.                         if(!b && (row < BORDERROW))
  349.                             row++;
  350.                         break;
  351.  
  352.                     case MSG_LEFTARROW:
  353.                         if(col > start)
  354.                             col--;
  355.                         break;
  356.  
  357.                     case MSG_RIGHTARROW:
  358.                         if(col < end)
  359.                             col++;
  360.                         break;
  361.  
  362.                     case MSG_HOME:
  363.                         col = start;
  364.                         break;
  365.  
  366.                     case MSG_END:
  367.                         col = end;
  368.                         break;
  369.                     }
  370.                 VioSetCurPos(row,col,VIOHDL);
  371.                 }
  372.                 break;
  373.  
  374.             // *******************Clipboard handling****************
  375.  
  376.             case MSG_COPY:              // user copy to clipboard
  377.             case MSG_CUT:               // user cut to clipboard
  378.                 if(!valid_block)        // if no block selected
  379.                     {
  380.                     beep();             // warn user
  381.                     break;              // forget it
  382.                     }
  383.                 i = prepare_CLPBRDblock();
  384.                                         // pass data to server
  385.                 MsgQSend(pmshdl,tempbuffer,i,PMS_CLPBRD_COPY);
  386.  
  387.                 if(msg == MSG_CUT)      // reset screen
  388.                     BlankBlock();
  389.                 else
  390.                     ResetBlock();
  391.                 valid_block = FALSE;
  392.                 break;
  393.  
  394.             case MSG_PASTE:                     // user paste
  395.                 MsgQSend(pmshdl,&pidinfo.pid,sizeof(PID),
  396.                     PMS_CLPBRD_PASTE);
  397.                 break;
  398.  
  399.             // ********************DDE handling*********************
  400.  
  401.             case MSG_INIT:                      // user wants dde
  402.                 if(dde_init)                    // if dde active
  403.                     {
  404.                     beep();
  405.                     break;
  406.                     }
  407.                 {
  408.                 CLIENTDATA *pclientdata = (CLIENTDATA *)tempbuffer;
  409.                 PBYTE p;
  410.  
  411.                 ButtonRead(app,appname);        // get app name
  412.                 ButtonRead(topic,topicname);    // get topic name
  413.  
  414.                 pclientdata->pid = pidinfo.pid; // set up PID
  415.                 strcpy(pclientdata->qname,appname);// add app name
  416.                 p = pclientdata->qname;                     
  417.                 p += strlen(p)+1;
  418.                 strcpy(p,topicname);            // add topic name
  419.                 p += strlen(p)+1;
  420.                 if(i = (p-(PBYTE)pclientdata))  // size
  421.                     {
  422.                         // request initiation of DDE conversation
  423.                     dde_init = TRUE;
  424.                     MsgQSend(pmshdl,tempbuffer,i,PMS_DDE_INIT);
  425.                     }
  426.                 }
  427.                 break;
  428.  
  429.             case MSG_REQUEST:
  430.             case MSG_ADVISE:
  431.             case MSG_TERM:
  432.                 {
  433.                 int i;
  434.  
  435.                 if(!dde_init)
  436.                     beep();
  437.                 else
  438.                     {
  439.                     CLIENTDATA *pclientdata =
  440.                         (CLIENTDATA *)tempbuffer;
  441.                     pclientdata->pid = pidinfo.pid; // set up PID
  442.                     ButtonRead(item,itemname);
  443.                     strcpy(pclientdata->qname,itemname);
  444.                     i = sizeof(PID)+strlen(pclientdata->qname)+1;
  445.  
  446.                     switch(msg)
  447.                         {
  448.                         case MSG_REQUEST:
  449.                             MsgQSend(pmshdl,tempbuffer,i,
  450.                                 PMS_DDE_REQUEST);
  451.                             break;
  452.                         case MSG_ADVISE:
  453.                             MsgQSend(pmshdl,tempbuffer,i,
  454.                                 PMS_DDE_ADVISE);
  455.                             break;
  456.                         case MSG_TERM:
  457.                             MsgQSend(pmshdl,tempbuffer,sizeof(PID),
  458.                                 PMS_DDE_TERMINATE);
  459.                             dde_init = FALSE;
  460.                             ButtonDisplay(app);
  461.                             ButtonDisplay(topic);
  462.                             ButtonDisplay(item);
  463.                             MsgQSend(qhandle,0,0,
  464.                                 MSG_RESETINITBUTTON);
  465.                             break;
  466.                         }
  467.                     }
  468.                 }
  469.                 break;
  470.  
  471.             // **************** PMServer message handling ***********
  472.             case PMS_CLPBRD:                    // data available
  473.             case PMS_CLPBRD_EMPTY:              // clpbrd is empty
  474.                 clipboard_data = ((msg == PMS_CLPBRD) ? TRUE :
  475.                     FALSE);
  476.                 MsgQSend(qhandle,0,0,MSG_RESETPASTEBUTTON);
  477.                 break;
  478.  
  479.             case PMS_DDE_INITACK:               // DDE available
  480.                 MsgQSend(qhandle,0,0,MSG_RESETINITBUTTON);
  481.                 beep();
  482.                 break;
  483.  
  484.             case PMS_DDE_INITNAK:               // DDE not available
  485.                 dde_init = FALSE;
  486.                 beep();
  487.                 break;
  488.  
  489.             case PMS_DDE_TERMINATE:  // DDE conversation terminated
  490.                 if(dde_init)
  491.                     {
  492.                     dde_init = FALSE;
  493.                     beep();
  494.                     MsgQSend(qhandle,0,0,MSG_RESETINITBUTTON);
  495.                     }
  496.                 break;
  497.  
  498.             case PMS_CLPBRD_DATA:    // clipboard data rec'd
  499.             case PMS_DDE_DATA:       // dde data rec'd
  500.                 {
  501.                 PITEMREQ pitemreq = (PITEMREQ)msgdata;
  502.                 PBYTE mptr;
  503.  
  504.                 if(msg == PMS_DDE_DATA)
  505.                     {
  506.                     if(stricmp(pitemreq->item,itemname))
  507.                         break;
  508.                     mptr = pitemreq->value;
  509.                     msgsize = strlen(mptr)+1;
  510.                     }
  511.                 else
  512.                     mptr = (PBYTE)msgdata;
  513.  
  514.                 VioGetCurPos(&row,&col,VIOHDL); // get cursor pos.
  515.                 for(i = 0, p = (PBYTE)mptr; *p; p++)
  516.                     if(*p == 13)                // if a linefeed
  517.                         i++;                    // # of lines in text
  518.                 if(row+i > ScreenRows)
  519.                     {
  520.                     int j = (row+i)-ScreenRows;
  521.  
  522.                     VioScrollUp(0,0,BORDERROW-1,ScreenCols,j,
  523.                             (char *)&BlankCell,VIOHDL);
  524.                     row -= j;
  525.                     VioSetCurPos(row,col,VIOHDL);
  526.                     }
  527.                 VioWrtTTY((PCH)mptr,msgsize-1,VIOHDL);
  528.                 if(msg == PMS_CLPBRD_DATA)
  529.                     MsgQSend(pmshdl,&pidinfo.pid,sizeof(PID),
  530.                         PMS_CLPBRD_QUERY);
  531.                 }
  532.                 break;
  533.  
  534.             case PMS_NO_INIT:                   // server can't init
  535.                 error_exit(msg,
  536.                     "PMS_Init - unable to access PM Server");
  537.                 break;
  538.  
  539.             case PMS_SERVER_TERM:          // server has terminated
  540.                 error_exit(msg,
  541.                     "PMAccess: Server had terminated, exiting");
  542.                 Server = FALSE;
  543.                 break;
  544.  
  545.  
  546.             case PMS_INIT_ACK:             // server initialized
  547.                 Server = TRUE;
  548.                 clipboard_data = FALSE;    // then fall thru
  549.  
  550.             default:
  551.                 break;
  552.             }
  553.         if(msgdata != NULL)
  554.             DosFreeSeg(SELECTOROF(msgdata));
  555.         }
  556.     }
  557.  
  558. // terminates PMServer connection
  559. void PMS_Terminate(HQUEUE serverhandle)
  560.     {
  561.                                             // terminate connection
  562.     MsgQSend(serverhandle,&pidinfo.pid,sizeof(PID),PMS_TERMINATE);
  563.     MsgQClose(serverhandle);                // close queue
  564.     }
  565.  
  566. // initializes PMServer connection
  567. void PMS_Init(HQUEUE serverhandle,char *qname)
  568.     {
  569.     CLIENTDATA clientdata;
  570.  
  571.     strcpy(clientdata.qname,qname);         // set up qname
  572.     clientdata.pid = pidinfo.pid;           // set up PID
  573.                                             // initialize connection
  574.     MsgQSend(serverhandle,&clientdata,sizeof(clientdata),PMS_INIT);
  575.     }
  576.  
  577. // prepare data for clipboard
  578. USHORT prepare_CLPBRDblock(void)
  579.     {
  580.     return readtextblock(tempbuffer,startrow,startcol,endrow,endcol);
  581.     }
  582.  
  583. // read text from screen
  584. USHORT readtextblock(PCHAR buffer,USHORT srow, USHORT scol,
  585.         USHORT erow, USHORT ecol)
  586.     {    
  587.     USHORT    i,row,len,col;
  588.  
  589.     for( row = srow, col = scol, i = 0; row <= erow; row++)
  590.         {
  591.         len = ScreenCols;
  592.         if(row != srow)
  593.             col = 0;
  594.         if(row == erow)
  595.             len = ecol+1;
  596.         VioReadCharStr(&buffer[i],&len,row,col,VIOHDL);
  597.         i += len-1;
  598.         while(buffer[i] == ' ')
  599.             i--;
  600.         buffer[++i] = '\r';
  601.         buffer[++i] = '\n';
  602.         i++;
  603.         }
  604.     buffer[i] = '\0';
  605.     return i+1;                            // return length of block
  606.     }
  607.  
  608. // set screen text block
  609. void SetBlock(USHORT row, USHORT col)
  610.     {
  611.     USHORT endBlock = (row * ScreenCols) + col;
  612.     USHORT presize,postsize,start;
  613.  
  614.     if(startBlock <= endBlock)          // block end at/after start
  615.         {
  616.         // normal from top to startBlock-1, 
  617.         // highlight from startBlock to endBlock
  618.         // normal from endBlock+1 to bottom
  619.         presize = startBlock;
  620.         startrow = rowBlockBeg;
  621.         startcol = colBlockBeg;
  622.         blocksize = endBlock-startBlock+1;
  623.         endBlock++;
  624.         endrow = (endBlock/ScreenCols);
  625.         endcol = (endBlock%ScreenCols);
  626.         postsize = (ScreenRows*ScreenCols)-endBlock+1;
  627.         }
  628.     else                                // block end before start
  629.         {
  630.         // normal from top to endBlock-1
  631.         // highlight from endBlock to startBlock
  632.         // normal from startBlock+1 to bottom
  633.         presize = endBlock;
  634.         startrow = row;
  635.         startcol = col;
  636.         blocksize = startBlock-endBlock+1;
  637.         start = startBlock+1;
  638.         endrow = (start/ScreenCols);
  639.         endcol = (start%ScreenCols);
  640.         postsize = (ScreenRows*ScreenCols)-start+1;
  641.         }
  642.  
  643.     blockptr = bufptr+presize;          // set to beginning of block
  644.     // now write pre-block and post-block normal, highlight block
  645.     VioWrtNAttr(&normal_att,presize,0,0,VIOHDL);
  646.     VioWrtNAttr(&highlight_att,blocksize,startrow,startcol,VIOHDL);
  647.     VioWrtNAttr(&normal_att,postsize,endrow,endcol,VIOHDL);
  648.     }
  649.  
  650. // reset screen work area
  651. void ResetScreen(void)
  652.     {
  653.     USHORT i;
  654.  
  655.     for( i = STARTROW; i <= ENDROW; i++)
  656.         VioWrtNAttr(&normal_att,BORDERCOL,STARTROW,0,VIOHDL);
  657.     }
  658.  
  659. // blank screen text block
  660. void BlankBlock(void)
  661.     {
  662.     VioWrtNCell((PBYTE)&BlankCell,blocksize,startrow,startcol,
  663.         VIOHDL);
  664.     }
  665.  
  666. // reset screen to normal
  667. void ResetBlock(void)
  668.     {
  669.     VioWrtNAttr(&normal_att,(ScreenCols*ScreenRows),0,0,
  670.         VIOHDL);
  671.     }
  672.  
  673. // initialize screen
  674. void InitScreen(void)
  675.     {
  676.     SHORT i;
  677.     char c = 196;
  678.  
  679.     VIOMODEINFO modeinfo;
  680.  
  681.     VioGetMode(&modeinfo,VIOHDL);   // get screen mode, rows, cols
  682.     ScreenCols = modeinfo.col;
  683.     ScreenRows = modeinfo.row;
  684.     if(ScreenRows > BORDERROW-1)
  685.         ScreenRows = BORDERROW-1;
  686.  
  687.     VioScrollUp(0,0,-1,-1,-1,(char *)&BlankCell,VIOHDL); // clear scr
  688.     VioSetCurPos(0,0,VIOHDL);                   // set cursor
  689.     VioWrtNChar(&c,ScreenCols,BORDERROW,0,VIOHDL); // draw border 
  690.     VioWrtNChar(&c,ScreenCols,BORDERROW2,0,VIOHDL); // draw border
  691.     for( i = 0; i < SCREEN_LABELS; i++)         // write labels
  692.         VioWrtCharStr(screen_labels[i].text,
  693.             strlen(screen_labels[i].text),
  694.             screen_labels[i].row,screen_labels[i].column,VIOHDL);
  695.     }
  696.  
  697. // manipulate buttons for specific event code and button type
  698. void ButtonPress(USHORT *eventcode)
  699.     {
  700.     BUTTON *b = &buttonlist[0];
  701.  
  702.     MOUSECODEOFF(*eventcode);                   // turn off mouse bit
  703.  
  704.     for( ; b->text; b++)                        // find the button            
  705.         if((b->left_button_val == *eventcode) ||
  706.                 (b->right_button_val == *eventcode) ||
  707.                 (b->accelerator == *eventcode))
  708.             {
  709.             switch(b->type)
  710.                 {
  711.                 case BPRESS:                    // if a press button            
  712.                     ButtonPaint(b,BUTTON_ON);   // turn it on                   
  713.                     DosSleep(100L);             // wait                            
  714.                     ButtonPaint(b,BUTTON_OFF);  // turn it off                    
  715.                     break;
  716.  
  717.                 case BTOGGLE:                   // if a toggle button        
  718.                     b->state = !b->state;       // toggle it                    
  719.                                                 // and toggle color        
  720.                     ButtonPaint(b,(b->state ? (BYTE)BUTTON_ON :
  721.                         b->attribute));
  722.                     break;
  723.  
  724.                 default:
  725.                     break;
  726.                 }
  727.             return;
  728.             }
  729.     }
  730.  
  731.  
  732. void activate_entrybutton(BUTTON *b, char *buttonfield)
  733.     {
  734.     int i;
  735.  
  736.     ButtonRead(b,buttonfield);                  // read button
  737.     for(i = 0; buttonfield[i]; i++);            // get # of chars
  738.                                                 // cursor to end
  739.     VioSetCurPos(b->startrow+1,b->startcol+1+i,VIOHDL);
  740.     }
  741.  
  742.     /******* end of main thread code **************************/
  743.  
  744.     /******* start of request thread code *********************/
  745.  
  746. // periodically wakes up and queries PMServer about Clipboard
  747. void RequestThread(void)
  748.     {
  749.     USHORT count = 0;
  750.  
  751.     while(TRUE)
  752.         {
  753.         if(!clipboard_data && Server)           // if invalidated
  754.                                                 // ask if paste
  755.             MsgQSend(pmshdl,&pidinfo.pid,sizeof(PID),
  756.                 PMS_CLPBRD_QUERY);
  757.         DosSleep(REQUESTTHREADSLEEPTIME);       // sleep a while
  758.         count++;
  759.         if(count >= MAXREQUESTCOUNT)            // count over limit?
  760.             {
  761.             clipboard_data = FALSE;             // invalidate flag
  762.             count = 0;                          // reset count
  763.             }
  764.         }
  765.     }
  766.  
  767.     /******* end of request thread code ***********************/
  768.  
  769.  
  770.     /********************** end of pmlite.c ********************/
  771.  
  772.