home *** CD-ROM | disk | FTP | other *** search
/ The Pier Shareware 6 / The_Pier_Shareware_Number_6_(The_Pier_Exchange)_(1995).iso / 035 / cenvi29.zip / TEXTBOSS.LIB < prev    next >
Text File  |  1994-11-16  |  16KB  |  409 lines

  1. // TextBoss.lib - Functions for controlling a windowed DOS or windowed OS/2
  2. // ver.4          session. Read the screen and send keystrokes.  These
  3. //                routines work with both OS/2 and DOS windows alike, except
  4. //                SendDosKey() and SendOS2Key(), and specific routines
  5. //                for full-screen OS/2 sessions.
  6. //
  7. //**** KeyStroke(): Press and release a key or combination of keys
  8. // See KeyStroke in KEYPUSH.LIB.  KeyStroke() can be used in most
  9. // situations to send keystrokes to windowed DOS sessions.
  10. //
  11. //***** ReadTextWindow(): Return contents of Text window in buffer
  12. // SYNTAX: string ReadTextWindow(int TextWindowHandle[,int DataLen])
  13. //         string ReadTextWindow(string WindowTitle[,int DataLen])
  14. // WHERE: TextWindowHandle: Integer identifier for this window
  15. //        TextWindowTitle: Partial text title of the window (case-insensitive)
  16. //        DataLen: Length of string returned if not NULL
  17. // RETURN: Returns NULL if failed to read, else returns string containing the
  18. //         contents of the Text window.
  19. //
  20. //
  21. //***** CopyTextBufferToLines(): Convert Text window string to lines
  22. // SYNTAX: string[] CopyTextBufferToLines(string Buffer,int LineCount)
  23. // WHERE: Buffer: Text buffer as returned by ReadTextWindow()
  24. //        LineCount: Return number of lines in the returned array
  25. // MODIFY: Linecount is set to number of returned lines
  26. // RETURN: Returns an array of strings where each element represents
  27. //         the next row of the Text screen.
  28. //
  29. //
  30. //***** PasteToTextWindow(): Send characters to a Text window's keyboard
  31. // SYNTAX: void PasteToTextWindow(int TextWindowHandle,string String)
  32. //         void PasteToTextWindow(string WindowTitle,string String)
  33. // WHERE: TextWindowHandle: Integer identifier for this window
  34. //        TextWindowTitle: Partial text title of the window (case-insensitive)
  35. //        String: String of characters to paste into the Text window
  36. // NOTE: If this function fails after about 15 calls, and won't work again,
  37. //       then call IBM at 1-800-992-4777 and ask for fix for APAR PJ11939.
  38. // new report # 3X128,PSZ
  39. //
  40. //
  41. //**** SendDosKey(): Send keystrokes (key and scancode) to DOS window running ServeOS2
  42. // SYNTAX: bool SendDosKey(string ServerSpec,string AsciiBuffer)
  43. //         bool SendDosKey(string ServerSpec,int KeyCode)
  44. //         bool SendDosKey(string ServerSpec,int[] KeyCodes,KeyCount)
  45. //         bool SendDosKey(string ServerSpec,int KeyCode,K_CTRL or K_ALT or K_SHIFT)
  46. // WHERE: ServerSpec: Unique 8.3 name that ServeOS2 was started with
  47. //        AsciiBuffer: Character string to send, will translate to KeyCode
  48. //        KeyCode: ScanCode is high byte, and CharCode is low byte; if not ScanCode
  49. //                 then this function will determine one
  50. //        KeyCodes: An array of ScanCode/CharCode key codes
  51. //        KeyCount: How many keys in the KeyCodes array
  52. //        K_CTRL or K_ALT or K_SHIFT: Use one of these pre-defined values to send code that
  53. //                 this key was held while Key is pressed 
  54. // RETURN: Return True if communication with DOS works, else False
  55. // NOTE: You cannot send more than 255 keys in one call
  56. //
  57. //
  58. //**** SendOS2Key(): Send keystrokes (key and scancode) to OS/2 window
  59. // SYNTAX: bool SendOS2Key(WindowSpec,string AsciiBuffer)
  60. //         bool SendOS2Key(WindowSpec,int KeyCode)
  61. //         bool SendOS2Key(WindowSpec,int[] KeyCodes,KeyCount)
  62. //         bool SendOS2Key(WindowSpec,int KeyCode,K_CTRL or K_ALT or K_SHIFT)
  63. // WHERE: WindowSpec: integer window handle, or partial title string
  64. //        AsciiBuffer: Character string to send, will translate to KeyCode
  65. //        KeyCode: ScanCode is high byte, and CharCode is low byte; if not ScanCode
  66. //                 then this function will determine one
  67. //        KeyCodes: An array of ScanCode/CharCode key codes
  68. //        KeyCount: How many keys in the KeyCodes array
  69. //        K_CTRL | K_ALT | K_SHIFT: Use one of these pre-defined values to send code that
  70. //                 this key was held while Key is pressed
  71. // RETURN: Return True if communication with window works, else False
  72. //
  73. //
  74. //**** SendFullOS2Key(): Send keystrokes (key and scancode) to full-screen OS/2
  75. //****                   session running FSSlave.cmm
  76. // SYNTAX: bool SendFullOS2Key(string FSSlaveSpec,string AsciiBuffer)
  77. //         bool SendFullOS2Key(string FSSlaveSpec,int KeyCode)
  78. //         bool SendFullOS2Key(string FSSlaveSpec,int[] KeyCodes,KeyCount)
  79. //         bool SendFullOS2Key(string FSSlaveSpec,int KeyCode,K_CTRL or K_ALT or K_SHIFT)
  80. // WHERE: FSSlaveSpec: Unique 8.3 name that FSSlave.cmm was started with
  81. //        AsciiBuffer: Character string to send, will translate to KeyCode
  82. //        KeyCode: ScanCode is high byte, and CharCode is low byte; if not ScanCode
  83. //                 then this function will determine one
  84. //        KeyCodes: An array of ScanCode/CharCode key codes
  85. //        KeyCount: How many keys in the KeyCodes array
  86. //        K_CTRL or K_ALT or K_SHIFT: Use one of these pre-defined values to send code that
  87. //                 this key was held while Key is pressed
  88. // RETURN: Return True if communication with FSSlave.cmm works, else False
  89. // NOTE: This function returns before all keystrokes have been removed by
  90. //       FSServer.cmm
  91. //
  92. //
  93. //**** ReadFullOS2Text(): Read contents of OS/2 full-screen text window
  94. // SYNTAX: string ReadFullOS2Text(string FSSlaveSpec[,int Col,int Row[,int Timeout]])
  95. // WHERE: FSSlaveSpec: Unique 8.3 name that FSSlave.cmm was started with
  96. //        Col,Row: If specified, set how many columns and rows of data
  97. //        Timeout: Time to wait, in milliseconds, for data to be filled, if
  98. //                 not supplied then use a long default
  99. // RETURN: Returns NULL if failed to read, else returns string containing the
  100. //         contents of the full-screen OS/2 text window.
  101. //
  102. //
  103.  
  104. #define K_CTRL    1
  105. #define K_ALT     2
  106. #define K_SHIFT   3
  107.  
  108. #define K_F1   0x3B00
  109. #define K_F2   0x3C00
  110. #define K_F3   0x3D00
  111. #define K_F4   0x3E00
  112. #define K_F5   0x3F00
  113. #define K_F6   0x4000
  114. #define K_F7   0x4100
  115. #define K_F8   0x4200
  116. #define K_F9   0x4300
  117. #define K_F10  0x4400
  118. #define K_INS  0x5200
  119. #define K_DEL  0x4300
  120. #define K_UP   0x4800
  121. #define K_DOWN 0x5000
  122. #define K_LEFT 0x4B00
  123. #define K_RIGHT 0x4D00
  124. #define K_PGUP 0x4900
  125. #define K_PGDN 0x5100
  126. #define K_END  0x4F00
  127. #define K_HOME 0x4700
  128.  
  129. #define K_ESC  0x011B
  130. #define K_SHIFT_TAB 0x0F00
  131.  
  132.  
  133. #include <WinTools.lib>
  134. #include <ClipBrd.lib>
  135. #include <WinMsg.lib>
  136. #include <FileIO.lib>
  137. #include <NamePipe.lib>
  138. #include <ScanCode.lib>
  139. #include <GiveMem.lib>
  140.  
  141. ReadTextWindow(pWindowSpec,pDataLen)
  142. {
  143.    lTextWindowData = NULL;  // assume failure
  144.    lDataLen = 0;
  145.    if ( (lReadHandle = GetWindowHandle(pWindowSpec)) ) {
  146.  
  147.       // Clear the clipboard, so we'll know when new data is here
  148.       PutClipboardData(NULL);
  149.  
  150.       // Send MENU message to the Window to paste all data into the clipboard
  151.       #define WM_SYSCOMMAND      0x0021
  152.       #define CMDSRC_MENU        2
  153.       #define COPY_ALL_COMMAND   0x9E
  154.       WinSendMsg(lReadHandle,WM_SYSCOMMAND,COPY_ALL_COMMAND,CMDSRC_MENU);
  155.  
  156.       if ( NULL != (lTextWindowData = GetClipboardData(CF_TEXT,lDataLen)) )
  157.          lDataLen = strlen(lTextWindowData);
  158.  
  159.    }
  160.    if ( 1 < va_arg() )
  161.       pDataLen = lDataLen;
  162.    return lTextWindowData;
  163. }
  164.  
  165.  
  166. CopyTextBufferToLines(pBuffer,pLineCount)
  167. {
  168.    for ( lBuf = pBuffer, pLineCount = 0; lBuf[0];
  169.          pLineCount++, lBuf += lStringLen + 1 ) {
  170.       lStringLen = strcspn(lBuf,"\n");
  171.       strncpy(lLines[pLineCount],lBuf,lStringLen);
  172.    }
  173.    return lLines;
  174. }
  175.  
  176.  
  177. PasteToTextWindow(pWindowSpec,pString)
  178. {
  179.    if ( (lTypeHandle = GetWindowHandle(pWindowSpec)) ) {
  180.  
  181.       // Put the pString data into the clipboard
  182.       PutClipboardData(pString,1+strlen(pString),CF_TEXT);
  183.  
  184.       // Send menu message to paste from the clipboard
  185.       #define PASTE_COMMAND   0x9F
  186.       WinPostMsg(lTypeHandle,WM_SYSCOMMAND,PASTE_COMMAND,CMDSRC_MENU,False);
  187.    }
  188. }
  189.  
  190. BuildScanCharBuffer(pArgCount,pKeyCode,pHoldKey,pKeyCount)
  191.    // return buffer containing scan-code/keycode, or NULL if error.
  192.    // pArgCount shows how many; set pKeyCount to keys in buffer
  193. {
  194.    // Build lBuffer based on type of input
  195.    lHoldAKeyDown = ( 2 < pArgCount );
  196.    lBuffer[0] = '\0';   // initialize lBuffer as a byte buffer
  197.    if ( 1 == DataDimension(pKeyCode) ) {
  198.       if ( CMM_BYTE == DataType(pKeyCode) ) {
  199.          // pKeyCode is an ascii string, for all of string add this key code
  200.          // and look up its scan code too
  201.          for ( pKeyCount = 0; pKeyCode[pKeyCount]; pKeyCount++ ) {
  202.             // char code is written first, then scan code
  203.             lBuffer[pKeyCount*2] = pKeyCode[pKeyCount];
  204.             lBuffer[1+(pKeyCount*2)] = GetScanCode(pKeyCode[pKeyCount]);
  205.          }
  206.       } else {
  207.          // this is an array of pkeycode, scancode and charcode
  208.          for ( pKeyCount = 0; pKeyCount < pHoldKey; pKeyCount++ ) {
  209.             // char code is written first, then scan code
  210.             lBuffer[pKeyCount*2] = pKeyCode[pKeyCount] & 0xFF;
  211.             lBuffer[1+(pKeyCount*2)] = (pKeyCode[pKeyCount] >> 8) & 0xFF;
  212.          }
  213.       }
  214.    } else {
  215.       // pKeyCode is a single key if no scan code then must get it
  216.       pKeyCount = 1;
  217.       lCharCode = pKeyCode & 0xFF;
  218.       lScanCode = (pKeyCode & 0xFF00) >> 8;
  219.       if ( 0 == lScanCode )
  220.          lScanCode = GetScanCode(lCharCode);
  221.       if ( lHoldAKeyDown ) {
  222.          // adjust keys for pHoldKey
  223.          switch( pHoldKey ) {
  224.             case K_CTRL:
  225.                if ( 'A' <= toupper(lCharCode) && toupper(lCharCode) <= 'Z' )
  226.                   lCharCode -= 'A' - 1;
  227.                else if ( K_F1 <= pKeyCode  &&  pKeyCode <= K_F10 )
  228.                   lScanCode += 0x23;
  229.                else {
  230.                   switch ( lScanCode ) {
  231.                      case K_LEFT:  lScanCode = 0x73; break;
  232.                      case K_RIGHT: lScanCode = 0x74; break;
  233.                      case K_PGUP:  lScanCode = 0x84; break;
  234.                      case K_PGDN:  lScanCode = 0x76; break;
  235.                      case K_END:   lScanCode = 0x77; break;
  236.                      case K_HOME:  lScanCode = 0x75; break;
  237.                   }
  238.                }
  239.                break;
  240.             case K_ALT:
  241.                if ( 'A' <= toupper(lCharCode) && toupper(lCharCode) <= 'Z' )
  242.                   lCharCode = 0;
  243.                else if ( K_F1 <= pKeyCode  &&  pKeyCode <= K_F10 )
  244.                   lScanCode += 0x2D;
  245.                else if ( 0x02 <= ScanCode  &&  ScanCode <= 0x0D )
  246.                   lScanCode += 0x76, lCharCode = 0;
  247.                break;
  248.             case K_SHIFT:
  249.                if ( islower(lCharCode) )
  250.                   lCharCode = toupper(lCharCode);
  251.                else if ( K_F1 <= pKeyCode  &&  pKeyCode <= K_F10 )
  252.                   lScanCode += 0x19;
  253.                break;
  254.             default:
  255.                printf("\aHoldKey = %d unknown!\a\n",pHoldKey); abort();
  256.          }
  257.       }
  258.       lBuffer[0] = lCharCode;
  259.       lBuffer[1] = lScanCode;
  260.    }
  261.    return ( 0 == pKeyCount ) ? NULL : lBuffer ;
  262. }
  263.  
  264. SendDosKey(pServerSpec,pKeyCode,pHoldKey)
  265. {
  266.    lArgCount = va_arg();
  267.    lBuffer = BuildScanCharBuffer(lArgCount,pKeyCode,2<lArgCount?pHoldKey:NULL,lKeyCount);
  268.    if ( !lBuffer || 255 < lKeyCount ) return False;
  269.    return SendKeyBufferToDOSServer(pServerSpec,lBuffer,lKeyCount);
  270. }
  271.  
  272. SendKeyBufferToDOSServer(pPipeName,pBuffer,pBufferLen/*max 255*/)
  273. {
  274.    bool lSuccess = False;   // assume failure
  275.    sprintf(lFullName,"\\PIPE\\%s",pPipeName);
  276.  
  277.    if ( !DosCreateNPipe(lFullName,lPipeHandle,
  278.                         NP_ACCESS_DUPLEX | NP_NOINHERIT,
  279.                         NP_NOWAIT | NP_TYPE_BYTE | NP_UNLIMITED_INSTANCES | NP_READMODE_BYTE,
  280.                         4096, 0, 0) ) {
  281.       // Give the DOS program up to 10 seconds to open the file
  282.       for ( lrepeat =  10 * 10; lRepeat--; ) {
  283.          suspend(100);
  284.          if ( !DosConnectNPipe(lPipeHandle) ) {
  285.             lSuccess = True;
  286.             break;
  287.          }
  288.       }
  289.       if ( lSuccess ) {
  290.  
  291.          // change pipe to blocking state to make sure reads and writes are
  292.          // finished
  293.          DosSetNPHState(lPipeHandle,NP_WAIT | NP_READMODE_BYTE);
  294.  
  295.          _SendBuf[0] = byte(pBufferLen);
  296.          memcpy(_SendBuf+1,pBuffer,2*pBufferLen);
  297.          if ( DosWrite(lPipeHandle,_SendBuf,2*pBufferLen+1,lBytesSent)
  298.            || lBytesSent != 2*pBufferLen+1 ) {
  299.             lSuccess = False;
  300.          } else {
  301.             // Will be finished when DOS closes the file, which will
  302.             // break the pipe.  A READ will hang until pipe is broken.
  303.             lDummyBuf[0] = '\0';
  304.             DosRead(lPipeHandle,lDummyBuf,1,lByteRead);
  305.          }
  306.          DosDisconnectNPipe(lPipeHandle);
  307.       }
  308.       DosClose(lPipeHandle);
  309.    }
  310.    return(lSuccess);
  311. }
  312.  
  313. SendOS2Key(pWindowSpec,pKeyCode,pHoldKey)
  314. {
  315.    lArgCount = va_arg();
  316.    lBuffer = BuildScanCharBuffer(lArgCount,pKeyCode,2<lArgCount?pHoldKey:NULL,lKeyCount);
  317.    if ( !lBuffer ) return False;
  318.  
  319.    lWindowHandle = GetWindowHandle(pWindowSpec);
  320.    if ( !lWindowHandle ) return False;
  321.  
  322.    // the window to send keystrokes to is the FID_CLIENT window
  323.    #define FID_CLIENT      0x8008
  324.    #define ORD_WIN32WINDOWFROMID 899
  325.    lWindowHandle = DynamicLink("PMWIN",ORD_WIN32WINDOWFROMID,BIT32,CDECL,
  326.                                lWindowHandle,FID_CLIENT);
  327.    if ( !lWindowHandle ) return False;
  328.  
  329.    lParam1 = 1 << 16;
  330.    for ( lKey = 0; lKey < lKeyCount; lKey++, lBuffer += 2 ) {
  331.       #define WM_CHAR   0x007a
  332.       WinPostMsg(lWindowHandle,WM_CHAR,lParam1,BLObGet(lBuffer,0,UWORD16));
  333.    }
  334.    return True;
  335. }
  336.  
  337. SendFullOS2Key(pFSSlaveSpec,pKeyCode,pHoldKey)
  338. {
  339.    lArgCount = va_arg();
  340.    lBuffer = BuildScanCharBuffer(lArgCount,pKeyCode,2<lArgCount?pHoldKey:NULL,lKeyCount);
  341.    return SendKeyBufferToFullOS2Server(pFSSlaveSpec,lBuffer,lKeyCount);
  342. }
  343.  
  344. SendKeyBufferToFullOS2Server(pQueueName,pBuffer,pBufferLen,pReadTimeout)
  345. { // if ReadTimeout then waiting for text to be passed back
  346.    sprintf(lQueueName,"\\QUEUES\\%s",pQueueName);
  347.  
  348.    // open queue to send messages
  349.    #define ORD_DOS32OPENQUEUE    15
  350.    if ( DynamicLink("QUECALLS",ORD_DOS32OPENQUEUE,BIT32,CDECL,
  351.                     lQueueProcess,lQueueHandle,lQueueName) )
  352.       return False;
  353.  
  354.    lKeyBuffer = GiveMemoryToProcess(lQueueProcess);
  355.  
  356.    // if timeout then reading from screen
  357.    lTimeout = (ReadingScreen = (3 < va_arg())) ? pReadTimeout : 20000;
  358.    poke(lKeyBuffer,ReadingScreen ? 0xFACE : 0xFEED,UWORD16);
  359.  
  360.    // add keystroke as big buffer; but must first give memory to server
  361.    poke(lKeyBuffer+2,pBuffer,pBufferLen*2);
  362.    #define ORD_DOS32WRITEQUEUE   14
  363.    lRc = DynamicLink("QUECALLS",ORD_DOS32WRITEQUEUE,BIT32,CDECL,
  364.                      lQueueHandle,0,2+pBufferLen*2,lKeyBuffer,0);
  365.  
  366.    // close the queue
  367.    #define ORD_DOS32CLOSEQUEUE  11
  368.    assert( !DynamicLink("QUECALLS",ORD_DOS32CLOSEQUEUE,BIT32,CDECL,lQueueHandle) );
  369.  
  370.    if ( !lRc ) {
  371.       // wait until timeout for buffer to change from 0xFEEF
  372.       EndTime = clock() + lTimeout*CLOCKS_PER_SEC/1000;
  373.       lRc = 1; // assume failure
  374.       do {
  375.          suspend(334);  // wait 1/3 second
  376.          if ( !peek(lKeyBuffer,UWORD16) ) {
  377.             pBuffer = peek(lKeyBuffer+2,pBufferLen*2);
  378.             lRc = 0;
  379.             break;
  380.          }
  381.       } while ( clock() <= EndTime )
  382.    }
  383.  
  384.    TerminateGMSharedMemoryPointer();
  385.    return !lRc;
  386. }
  387.  
  388. ReadFullOS2Text(pFSSlaveSpec,pCol,pRow,pTimeout)
  389. {
  390.    lArgCount = va_arg();
  391.    lTimeout = lArgCount < 4 ? 15000 : pTimeout ;
  392.    #define MAX_ROWCOUNT    50
  393.    #define MAX_COLCOUNT    80
  394.    lBufferLen = MAX_ROWCOUNT * MAX_COLCOUNT + 2 + 2;
  395.    BLObSize(lBLOb,lBufferLen);
  396.    if ( !SendKeyBufferToFullOS2Server(pFSSlaveSpec,lBLOb,lBufferLen/2,lTimeout) )
  397.       return NULL;
  398.    lColCount = BLObGet(lBLOb,0,UWORD16);
  399.    lRowCount = BLObGet(lBLOb,2,UWORD16);
  400.    lDataLength = lColCount * lRowCount;
  401.    lData = BLObGet(lBLOb,4,lColCount * lRowCount);
  402.    if ( 1 < lArgCount ) {
  403.       pCol = lColCount;
  404.       pRow = lRowCount;
  405.    }
  406.    return lData;
  407. }
  408.  
  409.