/* This function is called from two threads, one each to monitor the
 * keyboard and mouse messages.
 * All packets are passed on unchanged.  The thread just clears a
 * semaphore to alert the main background process that there has been some
 * activity, which means it won't blank or will restore the screen if
 * it is already blanked.
 *
 * Parameter is name of device to be monitored.
 */
void CALLBACK
MonitorThread(NPSZ npName)
{
   int             rc;
   MONIN           mnin;        /* monitor buffers */
   MONOUT          mnout;
   HMONITOR        hmon;
   char            bDataBuf[sizeof(MONIN)];  /* buffer used */
   USHORT          cbDataBufLen;
   PIDINFO         pidi;

   /* It has to be time-critical, so it doesn't impact response. */
   DosGetPID(&pidi);
   DosSetPrty(PRTYS_THREAD, PRTYC_TIMECRITICAL, 0, pidi.tid);

   /* Initialize the lengths of the monitor buffer structures. */
   mnin.cb = sizeof(MONIN);
   mnout.cb = sizeof(MONOUT);

   /*
    * Register for the current session.
    */
   TRACE(tpMonOpen, TRUE, 0, npName);
   if (rc = DosMonOpen(npName, &hmon))
      ERRORCHK("DosMonOpen", rc);
   TRACE(tpMonReg, TRUE, 0, npName);
   rc = DosMonReg(hmon,
                  (PBYTE) & mnin,
                  (PBYTE) & mnout,
                  MONITOR_BEGIN, sgMonitor);
   TRACE(tpMonReg, FALSE, rc, npName);
   if (rc == 0)
      /*
       * Loop, passing on data and signalling main thread.
       */
      for (;;) {
         cbDataBufLen = sizeof(MONIN);
         if (DosMonRead((PBYTE) & mnin, DCWW_WAIT, bDataBuf, &cbDataBufLen))
            break;
         /* We shouldn't get a length 0 return, but best to check, before
          * testing the first byte... */
         if (cbDataBufLen > 0) {
            if (DosMonWrite((PBYTE) & mnout, bDataBuf, cbDataBufLen))
               break;
            /* Test for open/close/flush packets and ignore them;
             * they don't represent mouse/keyboard actions. */
            if (!(bDataBuf[0] & 0x07)) {
               TRACE(tpMonAction, FALSE, cbDataBufLen, npName);
               DosSemClear(&pSharedseg->semAction);
            }
         }
      }
   else {
      /* Failed to register */
      WtiLStrCpy(bDataBuf, "DosMonReg for ");
      WtiLStrCat(bDataBuf, npName);
      ERRORCHK(bDataBuf, rc);
   }

   /* If blanked, undo it, whatever the reason we're leaving... */
   if (pSharedseg->bBlanked)
      DosSemClear(&pSharedseg->semAction);

   /* Told to withdraw */
   DosExit(EXIT_THREAD, 0);
}
void os2KbdMonitorThread(void* arg)
{
	struct KeyPacket packet;
	APIRET rc;
	USHORT length,print_flag;
	ULONG queueParam;
	HMONITOR hKbdMonitor;
	MONIN monInbuf;
	MONOUT monOutbuf;
	char queueName[128];

#if 0
	monInbuf=(MONIN *)_tmalloc(2*sizeof(MONIN));
	if (monInbuf==NULL) {
		xf86Msg(X_ERROR,
			"Could not allocate memory in kbd monitor thread!\n");
		exit(1);
	}
	monOutbuf=(MONOUT *) &monInbuf[1];
#endif

	monInbuf.cb=sizeof(MONIN);
	monOutbuf.cb=sizeof(MONOUT);

	rc = DosMonOpen("KBD$",&hKbdMonitor);
	xf86Msg(X_INFO,"Opened kbd monitor, rc=%d\n",rc);
 	rc = DosMonReg(hKbdMonitor,
		       (PBYTE)&monInbuf,(PBYTE)&monOutbuf,(USHORT)2,(USHORT)-1);
	xf86Msg(X_INFO,"Kbd monitor registered, rc=%d\n",rc);
	if (rc) {
		DosMonClose(hKbdMonitor);
		exit(1);
	}

	/* create a queue */
	sprintf(queueName,"\\QUEUES\\XF86KBD\\%d",getpid());
	rc = DosCreateQueue(&hKbdQueue,0L,queueName);
	xf86Msg(X_INFO,"Kbd Queue created, rc=%d\n",rc);
	(void)DosPurgeQueue(hKbdQueue);

	while (1) {
		length = sizeof(packet);
		rc = DosMonRead((PBYTE)&monInbuf,0,(PBYTE)&packet,&length);
		if (rc)	{
			xf86Msg(X_ERROR,
				"DosMonRead returned bad RC! rc=%d\n",rc);
			DosMonClose(hKbdMonitor);
			exit(1);
		}
		queueParam = packet.mnflags+(packet.ddflags<<16);
		if (packet.mnflags&0x7F00)
			DosWriteQueue(hKbdQueue,queueParam,0L,NULL,0L);
			/*xf86Msg(X_INFO,"Wrote a char to queue, rc=%d\n",rc); */
		print_flag = packet.ddflags & 0x1F;

		/*xf86Msg(X_INFO,"Kbd Monitor: Key press %d, scan code %d, ddflags %d\n",
			  packet.mnflags&0x8000,(packet.mnflags&0x7F00)>>8,packet.ddflags); 
		*/

		/* This line will swallow print-screen keypresses */
		if (print_flag == 0x13 || print_flag == 0x14 || 
		    print_flag == 0x15 || print_flag == 0x16)
			rc = 0;
		else
			rc = DosMonWrite((PBYTE)&monOutbuf,(PBYTE)&packet,length); 
		if (rc) {
			xf86Msg(X_ERROR,
				"DosMonWrite returned bad RC! rc=%d\n",rc);
			DosMonClose(hKbdMonitor);
			exit(1);
		}
	}

	DosCloseQueue(hKbdQueue);
	DosMonClose(hKbdMonitor);
}