home *** CD-ROM | disk | FTP | other *** search
- //********************************************************************
- //*** FSSlave.cmm - Full-screen OS/2 keystroke slave. Receive ***
- //*** ver.1 keystrokes for program running in full-screen. ***
- //********************************************************************
-
- #define DEFAULT_KEYDELAY 2000
-
- Instructions()
- {
- puts(`FSSlave.cmm - Keystroke slave for full-screen OS/2 sessions`)
- puts(``)
- puts(`SYNTAX: CEnvi FSSlave.cmm [Options] <SlaveName> [Commands...]`)
- puts(``)
- puts(`WHERE: SlaveName - Unique slave name (conform to 8.3 file spec)`)
- puts(``)
- puts(`OPTIONS: /KEYDELAY=MilliTime - Approximate time between checks for`)
- printf(" keystrokes if the keyboard buffer has been empty: default=%d\n",DEFAULT_KEYDELAY);
- puts(``)
- puts(`EXAMPLES: START /FS /F /N CEnvi.exe FSSlave NOTES`)
- puts(``)
- ErrorPrintf("");
- }
-
- ErrorPrintf(pString/*...*/)
- {
- printf("\a");
- va_start(va_list,pString);
- vprintf(pString,va_list);
- printf("\n\aPress any key to exit...");
- while( kbhit() ) getch();
- getch();
- printf("\n");
- exit(EXIT_FAILURE);
- }
-
- #include <OptParms.lib>
-
- main(argc,argv)
- {
- Delay = OptionalParameter(argc,argv,"KEYDELAY",lTemp)
- ? atoi(lTemp) : DEFAULT_KEYDELAY ;
-
- if ( argc < 2 )
- Instructions();
-
- // first paramter is the SlaveName
- strcpy(SlaveName,argv[1]);
-
- // if any more parameters then they are program to run, else default to
- // OS2_SHELL or COMSPEC
- if ( 2 < argc ) {
- argv += 2;
- argc -= 2;
- } else {
- if ( !(argv[0] = getenv("OS2_SHELL"))
- && !(argv[0] = getenv("COMSPEC")) )
- ErrorPrintf("Could not get shell via %s or %s.","OS2_SHELL","COMSPEC");
- argc = 1;
- }
-
- // we must be running full-screen, or this won't work
- MustBeFullScreen();
-
- // start their program running
- CmdChild = ( argc == 1 )
- ? spawn(P_NOWAIT,argv[0])
- : spawn(P_NOWAIT,argv[0],argv+1);
- if ( -1 == CmdChild )
- ErrorPrintf("Error executing %s",argv[0]);
-
- // characters for keyboard will be received in a queue
- if ( !StartReceiveQueue(Queue,SlaveName) )
- ErrorPrintf("Unable to create message queue for \"%s\".",SlaveName);
-
- // Setup a keyboard monitor to read and pass on keystrokes
- if ( !StartKeyboardMonitor(Kbd) )
- ErrorPrintf("Unable to start keyboard monitor.");
-
- // stay in this loop as long as the child is running
- DelayTime = 0;
- while ( IsProcessRunning(CmdChild) ) {
-
- // while keys are available, keep stuffing them
- DelayTime += 100;
- while ( PassKeycodes(Kbd,GetStuffKeycode(Queue)) )
- DelayTime = 0; // key, so do next check quickly
-
- suspend(DelayTime = min(DelayTime,Delay));
- }
-
- // close keyboard monitor and msg queue, then all done
- EndKeyboardMonitor(Kbd);
- EndReceiveQueue(Queue);
- return(EXIT_SUCCESS);
- }
-
-
- MustBeFullScreen()
- {
- #define SESSION_WINDOWABLEVIO 2
- #define ORD_DOS32GETINFOBLOCKS 312
- DynamicLink("doscalls",ORD_DOS32GETINFOBLOCKS,BIT32,CDECL,
- ThreadInfoBlock,ProcessInfoBlock)
- SessionType = peek(ProcessInfoBlock + (6 * 4),UWORD32);
- if ( SessionType == SESSION_WINDOWABLEVIO )
- ErrorPrintf("FSSlave.cmm must run in a full-screen session.");
- }
-
- IsProcessRunning(pProcessID)
- {
- if ( lList = ProcessList(False) ) {
- for ( li = GetArraySpan(lList); 0 <= li; li-- ) {
- if ( pProcessID == lList[li].id )
- return(True);
- }
- }
- return False;
- }
-
- DosSetPriority(pScope,pPriorityClass,pPriorityDelta,pID)
- {
- #define PRTYS_THREAD 2
- #define PRTYC_REGULAR 2
- #define PRTYC_TIMECRITICAL 3
- #define ORD_DOS32SETPRIORITY 236
- return DynamicLink("doscalls",ORD_DOS32SETPRIORITY,BIT32,CDECL,
- pScope,pPriorityClass,pPriorityDelta,pID);
- }
-
- //***********************************************************
- //********************** MESSAGE QUEUE **********************
- //***********************************************************
-
- StartKeyboardMonitor(pKbd)
- {
- #define ORD_DOSMONOPEN 4
- lRC = DynamicLink("MONCALLS",ORD_DOSMONOPEN,BIT16,PASCAL,"KBD$",lHandle);
- if ( (lRC & 0xFFFF) )
- return False;
- pKbd.Handle = lHandle;
-
- // need an input monitor buffer, and output monitor buffer
- #define MONITOR_BUFFER_SIZE 2 + 18 + 108
- BLObSize(pKbd.MonInBuf,MONITOR_BUFFER_SIZE+1000);
- memset(pKbd.MonInBuf,0,MONITOR_BUFFER_SIZE);
- BLObPut(pKbd.MonInBuf,0,MONITOR_BUFFER_SIZE,UWORD16);
- BLObSize(pKbd.MonOutBuf,MONITOR_BUFFER_SIZE+1000);
- memset(pKbd.MonOutBuf,0,MONITOR_BUFFER_SIZE);
- BLObPut(pKbd.MonOutBuf,0,MONITOR_BUFFER_SIZE,UWORD16);
-
- // initialize monitor I/O buffers
- assert( !DosSetPriority(PRTYS_THREAD,PRTYC_TIMECRITICAL,0,0) );
- #define MONITOR_BEGIN 0x0001
- #define ORD_DOSMONREG 5
- if ( 0xFFFF & DynamicLink("MONCALLS",ORD_DOSMONREG,BIT16,PASCAL,
- pKbd.Handle,pKbd.MonInBuf,pKbd.MonOutBuf,
- MONITOR_BEGIN,Info().Session) )
- return False;
- assert( !DosSetPriority(PRTYS_THREAD,PRTYC_REGULAR,0,0) );
-
- return True;
- }
-
- EndKeyboardMonitor(pKbd)
- {
- #define ORD_DOSMONCLOSE 3
- DynamicLink("MONCALLS",ORD_DOSMONCLOSE,BIT16,PASCAL,pKbd.Handle);
- }
-
- DosMonRead(pMonitorBuffer,pWaitFlag,pDataBuffer,pByteCount)
- {
- #define ORD_DOSMONREAD 2
- BLObPut(lByteCount,pByteCount,UWORD16);
- lRC = 0xFFFF & DynamicLink("MONCALLS",ORD_DOSMONREAD,BIT16,PASCAL,
- pMonitorBuffer,pWaitFlag,pDataBuffer,lByteCount);
- pByteCount = BLObGet(lByteCount,0,UWORD16);
- return lRC;
- }
-
- PassKeycodes(pKbd,pStuffKey) // return True if key pressed or faked
- { // else False for no keys
- // use a key packet to monitor buffer
- #define KEYPACKET_SIZE 2 + 10 + 2
- BLObSize(lKeyPacket,KEYPACKET_SIZE);
-
- lCount = KEYPACKET_SIZE;
- if ( pStuffKey ) {
- memset(lKeyPacket,0,KEYPACKET_SIZE);
- BLObPut(lKeyPacket,2,pStuffKey,UWORD16);
- } else {
- // read next from keyboard
- #define IO_WAIT 0
- #define IO_NOWAIT 1
- if ( DosMonRead(pKbd.MonInBuf,IO_NOWAIT,lKeyPacket,lCount) )
- return False;
- //printf("mnflags = %04X\n",BLObGet(lKeyPacket,0,UWORD16));
- //printf("Keycode = %04X\n",BLObGet(lKeyPacket,2,UWORD16));
- //printf("fbStatus = %02X\n",BLObGet(lKeyPacket,4,UWORD8));
- //printf("bNlsShift = %02X\n",BLObGet(lKeyPacket,5,UWORD8));
- //printf("fsState = %04X\n",BLObGet(lKeyPacket,6,UWORD16));
- //printf("time = %08X\n",BLObGet(lKeyPacket,8,UWORD32));
- //printf("ddflags = %04X\n\n",BLObGet(lKeyPacket,12,UWORD16));
- }
-
- #define ORD_DOSMONWRITE 1
- DynamicLink("MONCALLS",ORD_DOSMONWRITE,BIT16,PASCAL,
- pKbd.MonOutBuf,lKeyPacket,lCount);
- return True;
- }
-
- // typedef struct _KBDKEYINFO /* kbci */
- // {
- // UCHAR chChar;
- // UCHAR chScan;
- // UCHAR fbStatus;
- // UCHAR bNlsShift;
- // USHORT fsState;
- // ULONG time;
- // }KBDKEYINFO;
- //
- // typedef struct _keypacket
- // {
- // USHORT mnflags;
- // KBDKEYINFO cp;
- // USHORT ddflags;
- // } KEYPACKET;
-
- //************************************************************
- //***************** CONSOLE KEYBOARD MONITOR *****************
- //************************************************************
-
- StartReceiveQueue(pQueue,pQueueName)
- {
- sprintf(lQueueName,"\\QUEUES\\%s",pQueueName);
- #define QUEUE_FIFO 0
- #define QUEUE_LIFO 1
- #define ORD_DOS32CREATEQUEUE 16
- if ( DynamicLink("QUECALLS",ORD_DOS32CREATEQUEUE,BIT32,CDECL,
- lQueueHandle,QUEUE_FIFO,lQueueName) )
- return False;
- pQueue.Handle = lQueueHandle;
- pQueue.KeyCount = 0; // no keys in buffer
- return True;
- }
-
- EndReceiveQueue(pQueue)
- {
- #define ORD_DOS32CLOSEQUEUE 11
- DynamicLink("QUECALLS",ORD_DOS32CLOSEQUEUE,BIT32,CDECL,pQueue.Handle);
- }
-
- GetStuffKeycode(pQueue)
- {
- lKeyCode = 0; // assume no key
-
- // if there is nothing in the queue then return 0
- #define ORD_DOS32QUERYQUEUE 12
- if ( !DynamicLink("QUECALLS",ORD_DOS32QUERYQUEUE,BIT32,CDECL,
- pQueue.Handle,lQueueCount)
- && lQueueCount ) {
-
- // read the next key character from the queue
- #define ORD_DOS32READQUEUE 9
- #define DCWW_WAIT 0
- #define DCWW_NOWAIT 1
- BLObPut(lRequest,0,Info().Process,UWORD32);
- if ( !DynamicLink("QUECALLS",ORD_DOS32READQUEUE,BIT32,CDECL,
- pQueue.Handle,lRequest,lDataLength,lDataPtr,
- 0,DCWW_WAIT,lPriority,0) ) {
-
- if ( 0xFACE == peek(lDataPtr,UWORD16) ) {
- ReadScreenIntoMemory(lDataPtr+2);
- } else {
- // the keys will be copied to our keybuffer
- BLObPut(pQueue.KeyBuffer,2*pQueue.KeyCount,
- peek(lDataPtr+2,lDataLength-2),lDataLength-2);
- pQueue.KeyCount += (lDataLength-2) / 2;
- }
- // put 0 at memory to show it's done
- poke(lDataPtr,0,UWORD16);
- // that memory was given to use, and so free it
- #define ORD_DOS32FREEMEM 304
- DynamicLink("DOSCALLS",ORD_DOS32FREEMEM,BIT32,CDECL,lDataPtr);
- }
- }
-
- if ( pQueue.KeyCount ) {
- lKeyCode = BLObGet(pQueue.KeyBuffer,0,UWORD16);
- pQueue.KeyBuffer += 2;
- if ( !(--pQueue.KeyCount) )
- undefine(pQueue.KeyBuffer);
- }
-
- return lKeyCode;
- }
-
- ReadScreenIntoMemory(pMem)
- {
- #define MAX_ROW_COUNT 50
- #define MAX_COL_COUNT 80
- #define ORD_VIOGETMODE 21
- // get size of screen
- BLObSize(lVioMode,8);
- BLObPut(lVioMode,0,8,UWORD16);
- DynamicLink("VIOCALLS",ORD_VIOGETMODE,BIT16,PASCAL,lVioMode,0);
- lColCount = min(MAX_COL_COUNT,BLObGet(lVioMode,4,UWORD16));
- lRowCount = min(MAX_ROW_COUNT,BLObGet(lVioMode,6,UWORD16));
-
- poke(pMem,lColCount,UWORD16);
- poke(pMem+2,lRowCount,UWORD16);
-
- #define ORD_VIOREADCHARSTR 30
- BLObSize(lBuf,lRowCount*lColCount);
- BLObPut(lSize,0,lRowCount*lColCount,UWORD16);
- lRc = DynamicLink("VIOCALLS",ORD_VIOREADCHARSTR,BIT16,PASCAL,
- lBuf,lSize,0,0,0);
- poke(pMem+4,lBuf,lRowCount*lColCount);
- }
-