home *** CD-ROM | disk | FTP | other *** search
- // TextBoss.lib - Functions for controlling a windowed DOS or windowed OS/2
- // ver.4 session. Read the screen and send keystrokes. These
- // routines work with both OS/2 and DOS windows alike, except
- // SendDosKey() and SendOS2Key(), and specific routines
- // for full-screen OS/2 sessions.
- //
- //**** KeyStroke(): Press and release a key or combination of keys
- // See KeyStroke in KEYPUSH.LIB. KeyStroke() can be used in most
- // situations to send keystrokes to windowed DOS sessions.
- //
- //***** ReadTextWindow(): Return contents of Text window in buffer
- // SYNTAX: string ReadTextWindow(int TextWindowHandle[,int DataLen])
- // string ReadTextWindow(string WindowTitle[,int DataLen])
- // WHERE: TextWindowHandle: Integer identifier for this window
- // TextWindowTitle: Partial text title of the window (case-insensitive)
- // DataLen: Length of string returned if not NULL
- // RETURN: Returns NULL if failed to read, else returns string containing the
- // contents of the Text window.
- //
- //
- //***** CopyTextBufferToLines(): Convert Text window string to lines
- // SYNTAX: string[] CopyTextBufferToLines(string Buffer,int LineCount)
- // WHERE: Buffer: Text buffer as returned by ReadTextWindow()
- // LineCount: Return number of lines in the returned array
- // MODIFY: Linecount is set to number of returned lines
- // RETURN: Returns an array of strings where each element represents
- // the next row of the Text screen.
- //
- //
- //***** PasteToTextWindow(): Send characters to a Text window's keyboard
- // SYNTAX: void PasteToTextWindow(int TextWindowHandle,string String)
- // void PasteToTextWindow(string WindowTitle,string String)
- // WHERE: TextWindowHandle: Integer identifier for this window
- // TextWindowTitle: Partial text title of the window (case-insensitive)
- // String: String of characters to paste into the Text window
- // NOTE: If this function fails after about 15 calls, and won't work again,
- // then call IBM at 1-800-992-4777 and ask for fix for APAR PJ11939.
- // new report # 3X128,PSZ
- //
- //
- //**** SendDosKey(): Send keystrokes (key and scancode) to DOS window running ServeOS2
- // SYNTAX: bool SendDosKey(string ServerSpec,string AsciiBuffer)
- // bool SendDosKey(string ServerSpec,int KeyCode)
- // bool SendDosKey(string ServerSpec,int[] KeyCodes,KeyCount)
- // bool SendDosKey(string ServerSpec,int KeyCode,K_CTRL or K_ALT or K_SHIFT)
- // WHERE: ServerSpec: Unique 8.3 name that ServeOS2 was started with
- // AsciiBuffer: Character string to send, will translate to KeyCode
- // KeyCode: ScanCode is high byte, and CharCode is low byte; if not ScanCode
- // then this function will determine one
- // KeyCodes: An array of ScanCode/CharCode key codes
- // KeyCount: How many keys in the KeyCodes array
- // K_CTRL or K_ALT or K_SHIFT: Use one of these pre-defined values to send code that
- // this key was held while Key is pressed
- // RETURN: Return True if communication with DOS works, else False
- // NOTE: You cannot send more than 255 keys in one call
- //
- //
- //**** SendOS2Key(): Send keystrokes (key and scancode) to OS/2 window
- // SYNTAX: bool SendOS2Key(WindowSpec,string AsciiBuffer)
- // bool SendOS2Key(WindowSpec,int KeyCode)
- // bool SendOS2Key(WindowSpec,int[] KeyCodes,KeyCount)
- // bool SendOS2Key(WindowSpec,int KeyCode,K_CTRL or K_ALT or K_SHIFT)
- // WHERE: WindowSpec: integer window handle, or partial title string
- // AsciiBuffer: Character string to send, will translate to KeyCode
- // KeyCode: ScanCode is high byte, and CharCode is low byte; if not ScanCode
- // then this function will determine one
- // KeyCodes: An array of ScanCode/CharCode key codes
- // KeyCount: How many keys in the KeyCodes array
- // K_CTRL | K_ALT | K_SHIFT: Use one of these pre-defined values to send code that
- // this key was held while Key is pressed
- // RETURN: Return True if communication with window works, else False
- //
- //
- //**** SendFullOS2Key(): Send keystrokes (key and scancode) to full-screen OS/2
- //**** session running FSSlave.cmm
- // SYNTAX: bool SendFullOS2Key(string FSSlaveSpec,string AsciiBuffer)
- // bool SendFullOS2Key(string FSSlaveSpec,int KeyCode)
- // bool SendFullOS2Key(string FSSlaveSpec,int[] KeyCodes,KeyCount)
- // bool SendFullOS2Key(string FSSlaveSpec,int KeyCode,K_CTRL or K_ALT or K_SHIFT)
- // WHERE: FSSlaveSpec: Unique 8.3 name that FSSlave.cmm was started with
- // AsciiBuffer: Character string to send, will translate to KeyCode
- // KeyCode: ScanCode is high byte, and CharCode is low byte; if not ScanCode
- // then this function will determine one
- // KeyCodes: An array of ScanCode/CharCode key codes
- // KeyCount: How many keys in the KeyCodes array
- // K_CTRL or K_ALT or K_SHIFT: Use one of these pre-defined values to send code that
- // this key was held while Key is pressed
- // RETURN: Return True if communication with FSSlave.cmm works, else False
- // NOTE: This function returns before all keystrokes have been removed by
- // FSServer.cmm
- //
- //
- //**** ReadFullOS2Text(): Read contents of OS/2 full-screen text window
- // SYNTAX: string ReadFullOS2Text(string FSSlaveSpec[,int Col,int Row[,int Timeout]])
- // WHERE: FSSlaveSpec: Unique 8.3 name that FSSlave.cmm was started with
- // Col,Row: If specified, set how many columns and rows of data
- // Timeout: Time to wait, in milliseconds, for data to be filled, if
- // not supplied then use a long default
- // RETURN: Returns NULL if failed to read, else returns string containing the
- // contents of the full-screen OS/2 text window.
- //
- //
-
- #define K_CTRL 1
- #define K_ALT 2
- #define K_SHIFT 3
-
- #define K_F1 0x3B00
- #define K_F2 0x3C00
- #define K_F3 0x3D00
- #define K_F4 0x3E00
- #define K_F5 0x3F00
- #define K_F6 0x4000
- #define K_F7 0x4100
- #define K_F8 0x4200
- #define K_F9 0x4300
- #define K_F10 0x4400
- #define K_INS 0x5200
- #define K_DEL 0x4300
- #define K_UP 0x4800
- #define K_DOWN 0x5000
- #define K_LEFT 0x4B00
- #define K_RIGHT 0x4D00
- #define K_PGUP 0x4900
- #define K_PGDN 0x5100
- #define K_END 0x4F00
- #define K_HOME 0x4700
-
- #define K_ESC 0x011B
- #define K_SHIFT_TAB 0x0F00
-
-
- #include <WinTools.lib>
- #include <ClipBrd.lib>
- #include <WinMsg.lib>
- #include <FileIO.lib>
- #include <NamePipe.lib>
- #include <ScanCode.lib>
- #include <GiveMem.lib>
-
- ReadTextWindow(pWindowSpec,pDataLen)
- {
- lTextWindowData = NULL; // assume failure
- lDataLen = 0;
- if ( (lReadHandle = GetWindowHandle(pWindowSpec)) ) {
-
- // Clear the clipboard, so we'll know when new data is here
- PutClipboardData(NULL);
-
- // Send MENU message to the Window to paste all data into the clipboard
- #define WM_SYSCOMMAND 0x0021
- #define CMDSRC_MENU 2
- #define COPY_ALL_COMMAND 0x9E
- WinSendMsg(lReadHandle,WM_SYSCOMMAND,COPY_ALL_COMMAND,CMDSRC_MENU);
-
- if ( NULL != (lTextWindowData = GetClipboardData(CF_TEXT,lDataLen)) )
- lDataLen = strlen(lTextWindowData);
-
- }
- if ( 1 < va_arg() )
- pDataLen = lDataLen;
- return lTextWindowData;
- }
-
-
- CopyTextBufferToLines(pBuffer,pLineCount)
- {
- for ( lBuf = pBuffer, pLineCount = 0; lBuf[0];
- pLineCount++, lBuf += lStringLen + 1 ) {
- lStringLen = strcspn(lBuf,"\n");
- strncpy(lLines[pLineCount],lBuf,lStringLen);
- }
- return lLines;
- }
-
-
- PasteToTextWindow(pWindowSpec,pString)
- {
- if ( (lTypeHandle = GetWindowHandle(pWindowSpec)) ) {
-
- // Put the pString data into the clipboard
- PutClipboardData(pString,1+strlen(pString),CF_TEXT);
-
- // Send menu message to paste from the clipboard
- #define PASTE_COMMAND 0x9F
- WinPostMsg(lTypeHandle,WM_SYSCOMMAND,PASTE_COMMAND,CMDSRC_MENU,False);
- }
- }
-
- BuildScanCharBuffer(pArgCount,pKeyCode,pHoldKey,pKeyCount)
- // return buffer containing scan-code/keycode, or NULL if error.
- // pArgCount shows how many; set pKeyCount to keys in buffer
- {
- // Build lBuffer based on type of input
- lHoldAKeyDown = ( 2 < pArgCount );
- lBuffer[0] = '\0'; // initialize lBuffer as a byte buffer
- if ( 1 == DataDimension(pKeyCode) ) {
- if ( CMM_BYTE == DataType(pKeyCode) ) {
- // pKeyCode is an ascii string, for all of string add this key code
- // and look up its scan code too
- for ( pKeyCount = 0; pKeyCode[pKeyCount]; pKeyCount++ ) {
- // char code is written first, then scan code
- lBuffer[pKeyCount*2] = pKeyCode[pKeyCount];
- lBuffer[1+(pKeyCount*2)] = GetScanCode(pKeyCode[pKeyCount]);
- }
- } else {
- // this is an array of pkeycode, scancode and charcode
- for ( pKeyCount = 0; pKeyCount < pHoldKey; pKeyCount++ ) {
- // char code is written first, then scan code
- lBuffer[pKeyCount*2] = pKeyCode[pKeyCount] & 0xFF;
- lBuffer[1+(pKeyCount*2)] = (pKeyCode[pKeyCount] >> 8) & 0xFF;
- }
- }
- } else {
- // pKeyCode is a single key if no scan code then must get it
- pKeyCount = 1;
- lCharCode = pKeyCode & 0xFF;
- lScanCode = (pKeyCode & 0xFF00) >> 8;
- if ( 0 == lScanCode )
- lScanCode = GetScanCode(lCharCode);
- if ( lHoldAKeyDown ) {
- // adjust keys for pHoldKey
- switch( pHoldKey ) {
- case K_CTRL:
- if ( 'A' <= toupper(lCharCode) && toupper(lCharCode) <= 'Z' )
- lCharCode -= 'A' - 1;
- else if ( K_F1 <= pKeyCode && pKeyCode <= K_F10 )
- lScanCode += 0x23;
- else {
- switch ( lScanCode ) {
- case K_LEFT: lScanCode = 0x73; break;
- case K_RIGHT: lScanCode = 0x74; break;
- case K_PGUP: lScanCode = 0x84; break;
- case K_PGDN: lScanCode = 0x76; break;
- case K_END: lScanCode = 0x77; break;
- case K_HOME: lScanCode = 0x75; break;
- }
- }
- break;
- case K_ALT:
- if ( 'A' <= toupper(lCharCode) && toupper(lCharCode) <= 'Z' )
- lCharCode = 0;
- else if ( K_F1 <= pKeyCode && pKeyCode <= K_F10 )
- lScanCode += 0x2D;
- else if ( 0x02 <= ScanCode && ScanCode <= 0x0D )
- lScanCode += 0x76, lCharCode = 0;
- break;
- case K_SHIFT:
- if ( islower(lCharCode) )
- lCharCode = toupper(lCharCode);
- else if ( K_F1 <= pKeyCode && pKeyCode <= K_F10 )
- lScanCode += 0x19;
- break;
- default:
- printf("\aHoldKey = %d unknown!\a\n",pHoldKey); abort();
- }
- }
- lBuffer[0] = lCharCode;
- lBuffer[1] = lScanCode;
- }
- return ( 0 == pKeyCount ) ? NULL : lBuffer ;
- }
-
- SendDosKey(pServerSpec,pKeyCode,pHoldKey)
- {
- lArgCount = va_arg();
- lBuffer = BuildScanCharBuffer(lArgCount,pKeyCode,2<lArgCount?pHoldKey:NULL,lKeyCount);
- if ( !lBuffer || 255 < lKeyCount ) return False;
- return SendKeyBufferToDOSServer(pServerSpec,lBuffer,lKeyCount);
- }
-
- SendKeyBufferToDOSServer(pPipeName,pBuffer,pBufferLen/*max 255*/)
- {
- bool lSuccess = False; // assume failure
- sprintf(lFullName,"\\PIPE\\%s",pPipeName);
-
- if ( !DosCreateNPipe(lFullName,lPipeHandle,
- NP_ACCESS_DUPLEX | NP_NOINHERIT,
- NP_NOWAIT | NP_TYPE_BYTE | NP_UNLIMITED_INSTANCES | NP_READMODE_BYTE,
- 4096, 0, 0) ) {
- // Give the DOS program up to 10 seconds to open the file
- for ( lrepeat = 10 * 10; lRepeat--; ) {
- suspend(100);
- if ( !DosConnectNPipe(lPipeHandle) ) {
- lSuccess = True;
- break;
- }
- }
- if ( lSuccess ) {
-
- // change pipe to blocking state to make sure reads and writes are
- // finished
- DosSetNPHState(lPipeHandle,NP_WAIT | NP_READMODE_BYTE);
-
- _SendBuf[0] = byte(pBufferLen);
- memcpy(_SendBuf+1,pBuffer,2*pBufferLen);
- if ( DosWrite(lPipeHandle,_SendBuf,2*pBufferLen+1,lBytesSent)
- || lBytesSent != 2*pBufferLen+1 ) {
- lSuccess = False;
- } else {
- // Will be finished when DOS closes the file, which will
- // break the pipe. A READ will hang until pipe is broken.
- lDummyBuf[0] = '\0';
- DosRead(lPipeHandle,lDummyBuf,1,lByteRead);
- }
- DosDisconnectNPipe(lPipeHandle);
- }
- DosClose(lPipeHandle);
- }
- return(lSuccess);
- }
-
- SendOS2Key(pWindowSpec,pKeyCode,pHoldKey)
- {
- lArgCount = va_arg();
- lBuffer = BuildScanCharBuffer(lArgCount,pKeyCode,2<lArgCount?pHoldKey:NULL,lKeyCount);
- if ( !lBuffer ) return False;
-
- lWindowHandle = GetWindowHandle(pWindowSpec);
- if ( !lWindowHandle ) return False;
-
- // the window to send keystrokes to is the FID_CLIENT window
- #define FID_CLIENT 0x8008
- #define ORD_WIN32WINDOWFROMID 899
- lWindowHandle = DynamicLink("PMWIN",ORD_WIN32WINDOWFROMID,BIT32,CDECL,
- lWindowHandle,FID_CLIENT);
- if ( !lWindowHandle ) return False;
-
- lParam1 = 1 << 16;
- for ( lKey = 0; lKey < lKeyCount; lKey++, lBuffer += 2 ) {
- #define WM_CHAR 0x007a
- WinPostMsg(lWindowHandle,WM_CHAR,lParam1,BLObGet(lBuffer,0,UWORD16));
- }
- return True;
- }
-
- SendFullOS2Key(pFSSlaveSpec,pKeyCode,pHoldKey)
- {
- lArgCount = va_arg();
- lBuffer = BuildScanCharBuffer(lArgCount,pKeyCode,2<lArgCount?pHoldKey:NULL,lKeyCount);
- return SendKeyBufferToFullOS2Server(pFSSlaveSpec,lBuffer,lKeyCount);
- }
-
- SendKeyBufferToFullOS2Server(pQueueName,pBuffer,pBufferLen,pReadTimeout)
- { // if ReadTimeout then waiting for text to be passed back
- sprintf(lQueueName,"\\QUEUES\\%s",pQueueName);
-
- // open queue to send messages
- #define ORD_DOS32OPENQUEUE 15
- if ( DynamicLink("QUECALLS",ORD_DOS32OPENQUEUE,BIT32,CDECL,
- lQueueProcess,lQueueHandle,lQueueName) )
- return False;
-
- lKeyBuffer = GiveMemoryToProcess(lQueueProcess);
-
- // if timeout then reading from screen
- lTimeout = (ReadingScreen = (3 < va_arg())) ? pReadTimeout : 20000;
- poke(lKeyBuffer,ReadingScreen ? 0xFACE : 0xFEED,UWORD16);
-
- // add keystroke as big buffer; but must first give memory to server
- poke(lKeyBuffer+2,pBuffer,pBufferLen*2);
- #define ORD_DOS32WRITEQUEUE 14
- lRc = DynamicLink("QUECALLS",ORD_DOS32WRITEQUEUE,BIT32,CDECL,
- lQueueHandle,0,2+pBufferLen*2,lKeyBuffer,0);
-
- // close the queue
- #define ORD_DOS32CLOSEQUEUE 11
- assert( !DynamicLink("QUECALLS",ORD_DOS32CLOSEQUEUE,BIT32,CDECL,lQueueHandle) );
-
- if ( !lRc ) {
- // wait until timeout for buffer to change from 0xFEEF
- EndTime = clock() + lTimeout*CLOCKS_PER_SEC/1000;
- lRc = 1; // assume failure
- do {
- suspend(334); // wait 1/3 second
- if ( !peek(lKeyBuffer,UWORD16) ) {
- pBuffer = peek(lKeyBuffer+2,pBufferLen*2);
- lRc = 0;
- break;
- }
- } while ( clock() <= EndTime )
- }
-
- TerminateGMSharedMemoryPointer();
- return !lRc;
- }
-
- ReadFullOS2Text(pFSSlaveSpec,pCol,pRow,pTimeout)
- {
- lArgCount = va_arg();
- lTimeout = lArgCount < 4 ? 15000 : pTimeout ;
- #define MAX_ROWCOUNT 50
- #define MAX_COLCOUNT 80
- lBufferLen = MAX_ROWCOUNT * MAX_COLCOUNT + 2 + 2;
- BLObSize(lBLOb,lBufferLen);
- if ( !SendKeyBufferToFullOS2Server(pFSSlaveSpec,lBLOb,lBufferLen/2,lTimeout) )
- return NULL;
- lColCount = BLObGet(lBLOb,0,UWORD16);
- lRowCount = BLObGet(lBLOb,2,UWORD16);
- lDataLength = lColCount * lRowCount;
- lData = BLObGet(lBLOb,4,lColCount * lRowCount);
- if ( 1 < lArgCount ) {
- pCol = lColCount;
- pRow = lRowCount;
- }
- return lData;
- }
-