home *** CD-ROM | disk | FTP | other *** search
/ ftp.wwiv.com / ftp.wwiv.com.zip / ftp.wwiv.com / pub / MISC / LSW270SR.ZIP / fsutil.c < prev    next >
Text File  |  2004-04-11  |  12KB  |  309 lines

  1. /*
  2.  *      Copyright (C) 1997-2004 Andrei Los.
  3.  *      This file is part of the lSwitcher source package.
  4.  *      lSwitcher is free software; you can redistribute it and/or modify
  5.  *      it under the terms of the GNU General Public License as published
  6.  *      by the Free Software Foundation, in version 2 as it comes in the
  7.  *      "COPYING" file of the lSwitcher main distribution.
  8.  *      This program is distributed in the hope that it will be useful,
  9.  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11.  *      GNU General Public License for more details.
  12.  */
  13.  
  14. #include "lswitch.h"
  15. #include "common.h"
  16. #include "fsutil.h"
  17.  
  18. #include <string.h>
  19. #include <stdio.h>
  20. #include <process.h>
  21.  
  22. static HMONITOR hmonKbd = (HMONITOR)0;
  23. static MONIN monInBuf = {0};
  24. static MONOUT monOutBuf = {0};
  25.  
  26.  
  27.  
  28. VOID FSMonitor(VOID *plswData)
  29. { static USHORT usCount;
  30.   static KEYPACKET keybuf;
  31.   ULONG ulPostCount;
  32.  
  33.   DosSetPrty(PRTYS_THREAD,PRTYC_TIMECRITICAL,+31,0);
  34.  
  35.   while (DosWaitEventSem(((PLSWDATA)plswData)->hevRunning,0)==ERROR_TIMEOUT) {
  36.     usCount = sizeof(keybuf);
  37.     if (DosMonRead((PBYTE)&monInBuf,DCWW_WAIT,(PBYTE)&keybuf,&usCount)) break;
  38.     DosMonWrite((PBYTE)&monOutBuf,(PBYTE)&keybuf,usCount);
  39.  
  40. /* keybuf.mnflags>>8 is the scan code; check for the Tab key release*/
  41.     if ((keybuf.cp.fsState>>8)==(((PLSWDATA)plswData)->Settings.ucPopupHotKey==1?1:2) &&
  42.         (keybuf.mnflags>>8)==(SCAN_TAB | 0x80)) {
  43.       if (keybuf.cp.fsState & 3)
  44.         DosPostEventSem(((PLSWDATA)plswData)->hevShift);
  45.       else
  46.         DosResetEventSem(((PLSWDATA)plswData)->hevShift,&ulPostCount);
  47.       DosPostEventSem(((PLSWDATA)plswData)->hevPopup);
  48.       break;
  49.     }
  50.   }
  51.  
  52. }
  53.  
  54. VOID FSMonDispat(VOID *pParm)
  55. { PLSWDATA plswData;
  56.   SEL selGSeg,selLSeg;
  57.   PGINFOSEG GSeg;
  58.   UCHAR ucCurrId=0,ucId;
  59.   ULONG ulPostCount;
  60.  
  61.   plswData = (PLSWDATA)pParm;
  62.   DosSetPriority(PRTYS_THREAD,PRTYC_TIMECRITICAL,+31,0);
  63.  
  64.   DosGetInfoSeg(&selGSeg,&selLSeg);
  65.   GSeg=(PGINFOSEG)((selGSeg &~7)<<13);
  66.  
  67.   if (DosCreateEventSem(SEMFSPOPUPNAME,&plswData->hevPopup,0,0)) return;
  68.   if (DosCreateEventSem(SEMSHIFTNAME,&plswData->hevShift,0,0)) return;
  69.  
  70.   while(DosWaitEventSem(plswData->hevRunning,10L)==ERROR_TIMEOUT) {
  71.     /* if we popup in PM reset the semaphore and post a triggering message;
  72.      if we popup in FS create a thread which will monitor the keyboard and
  73.      display the popup menu, post the semaphore one more time so that we do
  74.      not accidentally create one more such thread because the first one didn't
  75.      have time to issue VioPopUp and thus change current FS session;
  76.      the semaphore will be reset when a keyboard monitor for this thread is
  77.      created */
  78.     if (DosWaitEventSem(plswData->hevPopup,200L)==0 &&
  79.         (DosQueryEventSem(plswData->hevPopup,&ulPostCount),ulPostCount==1)) {
  80.       if (plswData->Settings.bPMPopupInFS) {
  81.         DosQueryEventSem(plswData->hevShift,&ulPostCount);
  82.         WinPostMsg(plswData->hwndPopup,WM_COMMAND,
  83.                    MPFROMSHORT(ulPostCount>0 ? CMD_SCROLLLEFTFROMFS : CMD_SCROLLRIGHTFROMFS),
  84.                    MPFROM2SHORT(CMDSRC_OTHER,FALSE));
  85.         DosResetEventSem(plswData->hevPopup,&ulPostCount);
  86.       } else {
  87.         DosPostEventSem(plswData->hevPopup);
  88.         plswData->itidFSMon=_beginthread(FSPopUp,NULL,0x4000,plswData);
  89.       }
  90.     }
  91.  
  92.     if ((ucId=GSeg->sgCurrent)!=ucCurrId) {
  93.       ucCurrId=ucId;
  94.       if (hmonKbd!=0) { DosMonClose(hmonKbd); hmonKbd=0; }
  95.  
  96.       if (DosMonOpen("KBD$",&hmonKbd)==0) {
  97.         monInBuf.cb=sizeof(MONIN); monOutBuf.cb=sizeof(MONOUT);
  98.         if (DosMonReg(hmonKbd,(PBYTE)&monInBuf,(PBYTE)&monOutBuf,1,ucCurrId)==0) {
  99.           if (DosQueryEventSem(plswData->hevPopup,&ulPostCount),ulPostCount==0)
  100.             plswData->itidFSMon=_beginthread(FSMonitor,NULL,0x4000,plswData);
  101.         } else {
  102.           DosMonClose(hmonKbd); hmonKbd=0;
  103.         }
  104.       } else
  105.         hmonKbd=0;
  106.       DosResetEventSem(plswData->hevPopup,&ulPostCount);
  107.     }
  108.  
  109.   }
  110.  
  111.   DosSleep(200);
  112.   if (hmonKbd!=0) DosMonClose(hmonKbd);
  113. }
  114.  
  115.  
  116. /* this function returns the number of the item with given line number
  117.  counting from top in the popup menu */
  118. SHORT ItemNumFromLineNum(LSWDATA *plswData,USHORT usLineNum)
  119. { SHORT item;
  120.  
  121.   item = usLineNum+plswData->iShift+
  122.     (plswData->Settings.bScrollItems ? plswData->usCurrItem : 0)-
  123.     (min(MAXTEXTITEMS,plswData->usItems)-1)/2;
  124.  
  125.   AdjustItem(item,plswData->usItems);
  126.   return item;
  127. }
  128.  
  129. /* this thread monitors keyboard activity during the popup */
  130. VOID FSPopUp(VOID *pParm)
  131. { static USHORT usCount;
  132.   static KEYPACKET keybuf;
  133.   UCHAR ucScan;
  134.   USHORT usCounter,usPopOpt;
  135.   ULONG ulPostCount;
  136.   BOOL bDoSwitch, bForward, bNowSticky;
  137.   PLSWDATA plswData;
  138.  
  139.  
  140.   plswData = (PLSWDATA)pParm;
  141.  
  142. //  DosEnterCritSec();
  143.   DosSetPriority(PRTYS_THREAD,PRTYC_TIMECRITICAL,+31,0);
  144.  
  145.   InitTaskArr(plswData,TRUE,FALSE,TRUE);
  146.  
  147.   if (DosQueryEventSem(plswData->hevShift,&ulPostCount),ulPostCount > 0)
  148.     plswData->usCurrItem = plswData->usItems-1;
  149.   else
  150.     plswData->usCurrItem=1;
  151.  
  152.   usPopOpt = 1;
  153.   VioPopUp(&usPopOpt,0);
  154.  
  155.   /* wait until monitor dispatcher registeres a monitor for the popup session and
  156.    resets the semaphore */
  157.   usCounter = 0;
  158.   while (DosQueryEventSem(plswData->hevPopup,&ulPostCount),ulPostCount!=0) {
  159.     DosSleep(5);
  160.     usCounter++;
  161.     if (usCounter>200) {
  162.       VioEndPopUp(0);
  163.       return;
  164.     }
  165.   }
  166.  
  167.   FSPopupMenu(plswData,0);
  168.  
  169.   bDoSwitch = FALSE; bNowSticky = FALSE;
  170.  
  171.   while (1) {
  172.     usCount = sizeof(keybuf);
  173.     if (DosMonRead((PBYTE)&monInBuf,DCWW_WAIT,(PBYTE)&keybuf,&usCount)) break;
  174.     DosMonWrite((PBYTE)&monOutBuf,(PBYTE)&keybuf,usCount);
  175. //    printf("%x %x %x\n",keybuf.cp.fbStatus,keybuf.cp.fsState,keybuf.mnflags>>8);
  176.  
  177.     ucScan = keybuf.mnflags>>8;
  178.     if (ucScan == (SCAN_TAB | 0x80) || ucScan == SCAN_UP || ucScan == SCAN_DOWN) {
  179.       bForward = ((ucScan == (SCAN_TAB | 0x80) && !(keybuf.cp.fsState & 3)) || /*check shift status */
  180.                   ucScan == SCAN_DOWN);
  181.       if (bForward) {
  182.         if (plswData->usCurrItem<plswData->usItems-1) plswData->usCurrItem++; else plswData->usCurrItem=0;
  183.       } else {
  184.         if (plswData->usCurrItem>0) plswData->usCurrItem--; else plswData->usCurrItem=plswData->usItems-1;
  185.       }
  186.  
  187.       if (!plswData->Settings.bScrollItems && plswData->usItems>MAXTEXTITEMS &&
  188.           plswData->usCurrItem==
  189.             ItemNumFromLineNum(plswData, bForward ? MAXTEXTITEMS : -1)) {
  190.  
  191.         plswData->iShift += (SHORT)(bForward ? MAXTEXTITEMS : -MAXTEXTITEMS)/3;
  192.         plswData->iShift -= plswData->iShift/(SHORT)plswData->usItems*plswData->usItems;
  193.  
  194.         FSPopupMenu(plswData,0);
  195.       } else
  196.         FSPopupMenu(plswData,bForward ? 1 : -1);
  197.  
  198.     } else if (ucScan==(((plswData->Settings.bStickyPopup||bNowSticky)?SCAN_ENTER:
  199.                          plswData->Settings.ucPopupHotKey==0?SCAN_ALT:
  200.                          plswData->Settings.ucPopupHotKey==1?SCAN_CTRL:SCAN_WINLEFT)|0x80)) { /*Enter, Ctrl or Alt or LeftWin release */
  201.       bDoSwitch = TRUE;
  202.       break;
  203.     } else if (ucScan == (SCAN_SPACE | 0x80) ||  /* space bar release */
  204.                ((plswData->Settings.bStickyPopup||bNowSticky) && ucScan == SCAN_ESC))
  205.       break;
  206.     else if ((plswData->Settings.ucPopupHotKey==0 && ucScan == (SCAN_CTRL|0x80)) ||
  207.              (plswData->Settings.ucPopupHotKey==1 && ucScan == (SCAN_ALT|0x80)) ||
  208.              (plswData->Settings.ucPopupHotKey==2 && (ucScan == (SCAN_CTRL|0x80)||
  209.                                                       ucScan == (SCAN_ALT|0x80))))
  210.       bNowSticky = TRUE;
  211.   }
  212. //  DosExitCritSec();
  213.   VioEndPopUp(0);
  214.  
  215.   if (bDoSwitch)
  216.     WinPostMsg(plswData->hwndPopup,WM_COMMAND,MPFROMSHORT(CMD_SWITCHFROMFS),
  217.                MPFROM2SHORT(CMDSRC_OTHER,FALSE));
  218. }
  219.  
  220.  
  221. /* this function displays fullscreen popup menu.
  222.  cmd==0: initialize menu, cmd==1 move cursor to the next item, cmd==-1 to the
  223.  previous item */
  224. void FSPopupMenu(LSWDATA *plswData,SHORT cmd)
  225. { static UCHAR ucAttr,ucLineBuf[TEXTSCRWID+1],ucTitle[NAMELEN],
  226.     ucCell[2]={32,MENUATTR}, ucMenuHgt, ucLineLen, ucMenuXLeft, ucMenuXRight,
  227.     ucMenuYTop, ucMenuYBottom;
  228.   USHORT k,usItem;
  229.   SHORT iLinesAboveSel;
  230.   VIOCURSORINFO CursorInfo;
  231.  
  232.   if (cmd==0) {
  233.     memset(&CursorInfo,0,sizeof(VIOCURSORINFO));  CursorInfo.attr=-1;
  234.     VioSetCurType(&CursorInfo,0);
  235.   }
  236.  
  237.   if (plswData->Settings.bOldPopup) {
  238.     if (cmd!=0) {
  239.       memset(ucLineBuf,0,sizeof(ucLineBuf));
  240.       GetItemTitle(plswData->TaskArr[plswData->usCurrItem].hsw,ucLineBuf,sizeof(ucLineBuf),TRUE);
  241.       ucLineBuf[TEXTSCRWID-1]=0; k=0; while (ucLineBuf[k]) k++;
  242.       memmove(&ucLineBuf[(TEXTSCRWID-k)>>1],ucLineBuf,k);
  243.       memset(ucLineBuf,0,(TEXTSCRWID-k)>>1);
  244.       ucAttr=MENUATTR;
  245.       VioWrtCharStrAtt(ucLineBuf,TEXTSCRWID,0,0,&ucAttr,0);
  246.     }
  247.     return;
  248.   }
  249.  
  250.   iLinesAboveSel = (min(MAXTEXTITEMS,plswData->usItems)-1)/2-plswData->iShift+
  251.     (plswData->Settings.bScrollItems ? 0 : plswData->usCurrItem);
  252.  
  253.   while (iLinesAboveSel > min(MAXTEXTITEMS,plswData->usItems)-1 || iLinesAboveSel < 0)
  254.     iLinesAboveSel -= (iLinesAboveSel<0?-1:1)*plswData->usItems;
  255.  
  256.   if (cmd==0) {
  257.     ucLineLen = 0;
  258.     for (k = 0; k < plswData->usItems; k++) {
  259.       GetItemTitle(plswData->TaskArr[k].hsw,ucTitle,sizeof(ucTitle),TRUE);
  260.       if (strlen(ucTitle)>ucLineLen) ucLineLen=strlen(ucTitle);
  261.     }
  262.     ucLineLen += 2;
  263.     ucMenuHgt = min(MAXTEXTITEMS,plswData->usItems)+2;
  264.     ucMenuXLeft = TEXTSCRWID/2-ucLineLen/2;
  265.     ucMenuYTop = TEXTSCRHGT/2-ucMenuHgt/2;
  266.     ucMenuXRight = ucMenuXLeft+ucLineLen;
  267.     ucMenuYBottom = ucMenuYTop+ucMenuHgt;
  268.  
  269.     for (k = 0; k < ucMenuHgt; k++) {
  270.       if (k==0) {
  271.         memset(ucLineBuf,205,ucLineLen); ucLineBuf[0]=201; ucLineBuf[ucLineLen-1]=187;
  272.       } else if (k==ucMenuHgt-1) {
  273.         memset(ucLineBuf,205,ucLineLen); ucLineBuf[0]=200; ucLineBuf[ucLineLen-1]=188;
  274.       } else {
  275.         usItem = ItemNumFromLineNum(plswData,k-1); //-1 takes care of the frame
  276.         GetItemTitle(plswData->TaskArr[usItem].hsw,ucTitle,sizeof(ucTitle),TRUE);
  277.         sprintf(ucLineBuf,"%c%-*s%c",186,ucLineLen-2,ucTitle,186);
  278.       }
  279.       ucAttr = MENUATTR;
  280.       VioWrtCharStrAtt(ucLineBuf,ucLineLen,ucMenuYTop+k,ucMenuXLeft,&ucAttr,0);
  281.     }
  282.   } else {
  283.     if (plswData->Settings.bScrollItems) {
  284.       if (cmd==1)
  285.         VioScrollUp(ucMenuYTop+1,ucMenuXLeft+1,ucMenuYBottom-2,ucMenuXRight-2,1,ucCell,0);
  286.       else
  287.         VioScrollDn(ucMenuYTop+1,ucMenuXLeft+1,ucMenuYBottom-2,ucMenuXRight-2,1,ucCell,0);
  288.  
  289.       usItem = ItemNumFromLineNum(plswData,cmd==1 ? ucMenuHgt-3 : 0);
  290.       GetItemTitle(plswData->TaskArr[usItem].hsw,ucTitle,sizeof(ucTitle),TRUE);
  291.       sprintf(ucLineBuf,"%c%-*s%c",186,ucLineLen-2,ucTitle,186);
  292.       ucAttr=MENUATTR;
  293.       VioWrtCharStrAtt(ucLineBuf,ucLineLen,cmd==1 ? ucMenuYBottom-2 : ucMenuYTop+1,
  294.                        ucMenuXLeft,&ucAttr,0);
  295.       VioWrtNAttr(&ucAttr,ucLineLen-2,ucMenuYTop+iLinesAboveSel+(cmd==1 ? 0 : 2),
  296.                   ucMenuXLeft+1,0);
  297.     } else {
  298.       ucAttr=MENUATTR;
  299.       VioWrtNAttr(&ucAttr,ucLineLen-2,ucMenuYTop+iLinesAboveSel+
  300.                   (cmd==1
  301.                    ? (iLinesAboveSel==0 ? ucMenuHgt-2 : 0)
  302.                    : (iLinesAboveSel==ucMenuHgt-3 ? 1-iLinesAboveSel : 2)),
  303.                   ucMenuXLeft+1,0);
  304.     }
  305.   }
  306.   ucAttr=CURSORATTR;
  307.   VioWrtNAttr(&ucAttr,ucLineLen-2,ucMenuYTop+iLinesAboveSel+1,ucMenuXLeft+1,0);
  308. }
  309.