home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / cenvi23.zip / FSSLAVE.CMM < prev    next >
Text File  |  1994-12-04  |  10KB  |  320 lines

  1. //********************************************************************
  2. //*** FSSlave.cmm - Full-screen OS/2 keystroke slave.  Receive     ***
  3. //*** ver.2         keystrokes for program running in full-screen. ***
  4. //********************************************************************
  5.  
  6. #define DEFAULT_KEYDELAY   2000
  7.  
  8. Instructions()
  9. {
  10.    puts(`FSSlave.cmm - Keystroke slave for full-screen OS/2 sessions`)
  11.    puts(``)
  12.    puts(`SYNTAX: CEnvi2 FSSlave.cmm [Options] <SlaveName> [Commands...]`)
  13.    puts(``)
  14.    puts(`WHERE: SlaveName - Unique slave name (conform to 8.3 file spec)`)
  15.    puts(``)
  16.    puts(`OPTIONS: /KEYDELAY=MilliTime - Approximate time between checks for`)
  17.    printf("            keystrokes if the keyboard buffer has been empty: default=%d\n",DEFAULT_KEYDELAY);
  18.    puts(``)
  19.    puts(`EXAMPLES: START /FS /F /N CEnvi2.exe FSSlave NOTES`)
  20.    puts(``)
  21.    ErrorPrintf("");
  22. }
  23.  
  24. ErrorPrintf(pString/*...*/)
  25. {
  26.    printf("\a");
  27.    va_start(va_list,pString);
  28.    vprintf(pString,va_list);
  29.    printf("\n\aPress any key to exit...");
  30.    while( kbhit() ) getch();
  31.    getch();
  32.    printf("\n");
  33.    exit(EXIT_FAILURE);
  34. }
  35.  
  36. #include <OptParms.lib>
  37.  
  38. main(argc,argv)
  39. {
  40.    Delay = OptionalParameter(argc,argv,"KEYDELAY",lTemp)
  41.          ? atoi(lTemp) : DEFAULT_KEYDELAY ;
  42.  
  43.    if ( argc < 2 )
  44.       Instructions();
  45.  
  46.    // first paramter is the SlaveName
  47.    strcpy(SlaveName,argv[1]);
  48.  
  49.    // if any more parameters then they are program to run, else default to
  50.    // OS2_SHELL or COMSPEC
  51.    if ( 2 < argc ) {
  52.       argv += 2;
  53.       argc -= 2;
  54.    } else {
  55.       if ( !(argv[0] = getenv("OS2_SHELL"))
  56.         && !(argv[0] = getenv("COMSPEC")) )
  57.          ErrorPrintf("Could not get shell via %s or %s.","OS2_SHELL","COMSPEC");
  58.       argc = 1;
  59.    }
  60.  
  61.    // we must be running full-screen, or this won't work
  62.    MustBeFullScreen();
  63.  
  64.    // start their program running
  65.    CmdChild = ( argc == 1 )
  66.             ? spawn(P_NOWAIT,argv[0])
  67.             : spawn(P_NOWAIT,argv[0],argv+1);
  68.    if ( -1 == CmdChild )
  69.       ErrorPrintf("Error executing %s",argv[0]);
  70.  
  71.    // characters for keyboard will be received in a queue
  72.    if ( !StartReceiveQueue(Queue,SlaveName) )
  73.       ErrorPrintf("Unable to create message queue for \"%s\".",SlaveName);
  74.  
  75.    // Setup a keyboard monitor to read and pass on keystrokes
  76.    if ( !StartKeyboardMonitor(Kbd) )
  77.       ErrorPrintf("Unable to start keyboard monitor.");
  78.  
  79.    // stay in this loop as long as the child is running
  80.    DelayTime = 0;
  81.    while ( IsProcessRunning(CmdChild) ) {
  82.  
  83.       // while keys are available, keep stuffing them
  84.       DelayTime += 100;
  85.       while ( PassKeycodes(Kbd,GetStuffKeycode(Queue)) )
  86.          DelayTime = 0; // key, so do next check quickly
  87.  
  88.       suspend(DelayTime = min(DelayTime,Delay));
  89.    }
  90.  
  91.    // close keyboard monitor and msg queue, then all done
  92.    EndKeyboardMonitor(Kbd);
  93.    EndReceiveQueue(Queue);
  94.    return(EXIT_SUCCESS);
  95. }
  96.  
  97.  
  98. MustBeFullScreen()
  99. {
  100.    #define SESSION_WINDOWABLEVIO 2
  101.    #define ORD_DOS32GETINFOBLOCKS   312
  102.    DynamicLink("doscalls",ORD_DOS32GETINFOBLOCKS,BIT32,CDECL,
  103.                ThreadInfoBlock,ProcessInfoBlock)
  104.    SessionType = peek(ProcessInfoBlock + (6 * 4),UWORD32);
  105.    if ( SessionType == SESSION_WINDOWABLEVIO )
  106.       ErrorPrintf("FSSlave.cmm must run in a full-screen session.");
  107. }
  108.  
  109. IsProcessRunning(pProcessID)
  110. {
  111.    if ( lList = ProcessList(False) ) {
  112.       for ( li = GetArraySpan(lList); 0 <= li; li-- ) {
  113.          if ( pProcessID == lList[li].id )
  114.             return(True);
  115.       }
  116.    }
  117.    return False;
  118. }
  119.  
  120. DosSetPriority(pScope,pPriorityClass,pPriorityDelta,pID)
  121. {
  122.    #define PRTYS_THREAD       2
  123.    #define PRTYC_REGULAR      2
  124.    #define PRTYC_TIMECRITICAL 3
  125.    #define ORD_DOS32SETPRIORITY     236
  126.    return DynamicLink("doscalls",ORD_DOS32SETPRIORITY,BIT32,CDECL,
  127.                       pScope,pPriorityClass,pPriorityDelta,pID);
  128. }
  129.  
  130. //***********************************************************
  131. //********************** MESSAGE QUEUE **********************
  132. //***********************************************************
  133.  
  134. StartKeyboardMonitor(pKbd)
  135. {
  136.    #define ORD_DOSMONOPEN  4
  137.    lRC = DynamicLink("MONCALLS",ORD_DOSMONOPEN,BIT16,PASCAL,"KBD$",lHandle);
  138.    if ( (lRC & 0xFFFF) )
  139.       return False;
  140.    pKbd.Handle = lHandle & 0xFFFF;
  141.  
  142.    // need an input monitor buffer, and output monitor buffer
  143.    #define MONITOR_BUFFER_SIZE  2 + 18 + 108
  144.    BLObSize(pKbd.MonInBuf,MONITOR_BUFFER_SIZE+1000);
  145.    memset(pKbd.MonInBuf,0,MONITOR_BUFFER_SIZE);
  146.    BLObPut(pKbd.MonInBuf,0,MONITOR_BUFFER_SIZE,UWORD16);
  147.    BLObSize(pKbd.MonOutBuf,MONITOR_BUFFER_SIZE+1000);
  148.    memset(pKbd.MonOutBuf,0,MONITOR_BUFFER_SIZE);
  149.    BLObPut(pKbd.MonOutBuf,0,MONITOR_BUFFER_SIZE,UWORD16);
  150.  
  151.    // initialize monitor I/O buffers
  152.    assert( !DosSetPriority(PRTYS_THREAD,PRTYC_TIMECRITICAL,0,0) );
  153.    #define MONITOR_BEGIN   0x0001
  154.    #define ORD_DOSMONREG   5
  155.    if ( 0xFFFF & DynamicLink("MONCALLS",ORD_DOSMONREG,BIT16,PASCAL,
  156.                              pKbd.Handle,pKbd.MonInBuf,pKbd.MonOutBuf,
  157.                              MONITOR_BEGIN,Info().Session) )
  158.       return False;
  159.    assert( !DosSetPriority(PRTYS_THREAD,PRTYC_REGULAR,0,0) );
  160.  
  161.    return True;
  162. }
  163.  
  164. EndKeyboardMonitor(pKbd)
  165. {
  166.    #define ORD_DOSMONCLOSE 3
  167.    DynamicLink("MONCALLS",ORD_DOSMONCLOSE,BIT16,PASCAL,pKbd.Handle);
  168. }
  169.  
  170. DosMonRead(pMonitorBuffer,pWaitFlag,pDataBuffer,pByteCount)
  171. {
  172.    #define ORD_DOSMONREAD  2
  173.    BLObPut(lByteCount,pByteCount,UWORD16);
  174.    lRC = 0xFFFF & DynamicLink("MONCALLS",ORD_DOSMONREAD,BIT16,PASCAL,
  175.                               pMonitorBuffer,pWaitFlag,pDataBuffer,lByteCount);
  176.    pByteCount = BLObGet(lByteCount,0,UWORD16);
  177.    return lRC;
  178. }
  179.  
  180. PassKeycodes(pKbd,pStuffKey)  // return True if key pressed or faked
  181. {                             // else False for no keys
  182.    // use a key packet to monitor buffer
  183.    #define KEYPACKET_SIZE  2 + 10 + 2
  184.    BLObSize(lKeyPacket,KEYPACKET_SIZE);
  185.  
  186.    lCount = KEYPACKET_SIZE;
  187.    if ( pStuffKey ) {
  188.       memset(lKeyPacket,0,KEYPACKET_SIZE);
  189.       BLObPut(lKeyPacket,2,pStuffKey,UWORD16);
  190.    } else {
  191.       // read next from keyboard
  192.       #define IO_WAIT      0
  193.       #define IO_NOWAIT    1
  194.       if ( DosMonRead(pKbd.MonInBuf,IO_NOWAIT,lKeyPacket,lCount) )
  195.          return False;
  196.       //printf("mnflags = %04X\n",BLObGet(lKeyPacket,0,UWORD16));
  197.       //printf("Keycode = %04X\n",BLObGet(lKeyPacket,2,UWORD16));
  198.       //printf("fbStatus = %02X\n",BLObGet(lKeyPacket,4,UWORD8));
  199.       //printf("bNlsShift = %02X\n",BLObGet(lKeyPacket,5,UWORD8));
  200.       //printf("fsState = %04X\n",BLObGet(lKeyPacket,6,UWORD16));
  201.       //printf("time = %08X\n",BLObGet(lKeyPacket,8,UWORD32));
  202.       //printf("ddflags = %04X\n\n",BLObGet(lKeyPacket,12,UWORD16));
  203.    }
  204.  
  205.    #define ORD_DOSMONWRITE 1
  206.    DynamicLink("MONCALLS",ORD_DOSMONWRITE,BIT16,PASCAL,
  207.                pKbd.MonOutBuf,lKeyPacket,lCount);
  208.    return True;
  209. }
  210.  
  211. //   typedef  struct _KBDKEYINFO      /* kbci */
  212. //   {
  213. //      UCHAR    chChar;
  214. //      UCHAR    chScan;
  215. //      UCHAR    fbStatus;
  216. //      UCHAR    bNlsShift;
  217. //      USHORT   fsState;
  218. //      ULONG    time;
  219. //   }KBDKEYINFO;
  220. //
  221. // typedef struct _keypacket
  222. //   {
  223. //    USHORT            mnflags;
  224. //    KBDKEYINFO        cp;
  225. //    USHORT            ddflags;
  226. //   } KEYPACKET;
  227.  
  228. //************************************************************
  229. //***************** CONSOLE KEYBOARD MONITOR *****************
  230. //************************************************************
  231.  
  232. StartReceiveQueue(pQueue,pQueueName)
  233. {
  234.    sprintf(lQueueName,"\\QUEUES\\%s",pQueueName);
  235.    #define QUEUE_FIFO   0
  236.    #define QUEUE_LIFO   1
  237.    #define ORD_DOS32CREATEQUEUE  16
  238.    if ( DynamicLink("QUECALLS",ORD_DOS32CREATEQUEUE,BIT32,CDECL,
  239.                     lQueueHandle,QUEUE_FIFO,lQueueName) )
  240.       return False;
  241.    pQueue.Handle = lQueueHandle;
  242.    pQueue.KeyCount = 0; // no keys in buffer
  243.    return True;
  244. }
  245.  
  246. EndReceiveQueue(pQueue)
  247. {
  248.    #define ORD_DOS32CLOSEQUEUE  11
  249.    DynamicLink("QUECALLS",ORD_DOS32CLOSEQUEUE,BIT32,CDECL,pQueue.Handle);
  250. }
  251.  
  252. GetStuffKeycode(pQueue)
  253. {
  254.    lKeyCode = 0;  // assume no key
  255.  
  256.    // if there is nothing in the queue then return 0
  257.    #define ORD_DOS32QUERYQUEUE   12
  258.    if ( !DynamicLink("QUECALLS",ORD_DOS32QUERYQUEUE,BIT32,CDECL,
  259.                      pQueue.Handle,lQueueCount)
  260.      && lQueueCount ) {
  261.  
  262.       // read the next key character from the queue
  263.       #define ORD_DOS32READQUEUE 9
  264.       #define DCWW_WAIT          0
  265.       #define DCWW_NOWAIT        1
  266.       BLObPut(lRequest,0,Info().Process,UWORD32);
  267.       if ( !DynamicLink("QUECALLS",ORD_DOS32READQUEUE,BIT32,CDECL,
  268.                         pQueue.Handle,lRequest,lDataLength,lDataPtr,
  269.                         0,DCWW_WAIT,lPriority,0) ) {
  270.  
  271.          if ( 0xFACE == peek(lDataPtr,UWORD16) ) {
  272.             ReadScreenIntoMemory(lDataPtr+2);
  273.          } else {
  274.             // the keys will be copied to our keybuffer
  275.             BLObPut(pQueue.KeyBuffer,2*pQueue.KeyCount,
  276.                     peek(lDataPtr+2,lDataLength-2),lDataLength-2);
  277.             pQueue.KeyCount += (lDataLength-2) / 2;
  278.          }
  279.          // put 0 at memory to show it's done
  280.          poke(lDataPtr,0,UWORD16);
  281.          // that memory was given to use, and so free it
  282.          #define ORD_DOS32FREEMEM   304
  283.          DynamicLink("DOSCALLS",ORD_DOS32FREEMEM,BIT32,CDECL,lDataPtr);
  284.       }
  285.    }
  286.  
  287.    if ( pQueue.KeyCount ) {
  288.       lKeyCode = BLObGet(pQueue.KeyBuffer,0,UWORD16);
  289.       pQueue.KeyBuffer += 2;
  290.       if ( !(--pQueue.KeyCount) )
  291.          undefine(pQueue.KeyBuffer);
  292.    }
  293.  
  294.    return lKeyCode;
  295. }
  296.  
  297. ReadScreenIntoMemory(pMem)
  298. {
  299.    #define MAX_ROW_COUNT   50
  300.    #define MAX_COL_COUNT   80
  301.    #define ORD_VIOGETMODE  21
  302.    // get size of screen
  303.    BLObSize(lVioMode,8);
  304.    BLObPut(lVioMode,0,8,UWORD16);
  305.    DynamicLink("VIOCALLS",ORD_VIOGETMODE,BIT16,PASCAL,lVioMode,0);
  306.    lColCount = min(MAX_COL_COUNT,BLObGet(lVioMode,4,UWORD16));
  307.    lRowCount = min(MAX_ROW_COUNT,BLObGet(lVioMode,6,UWORD16));
  308.  
  309.    poke(pMem,lColCount,UWORD16);
  310.    poke(pMem+2,lRowCount,UWORD16);
  311.  
  312.    #define ORD_VIOREADCHARSTR 30
  313.    BLObSize(lBuf,lRowCount*lColCount);
  314.    BLObPut(lSize,0,lRowCount*lColCount,UWORD16);
  315.    lRc = DynamicLink("VIOCALLS",ORD_VIOREADCHARSTR,BIT16,PASCAL,
  316.                      lBuf,lSize,0,0,0);
  317.    poke(pMem+4,lBuf,lRowCount*lColCount);
  318. }
  319.  
  320.