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 >
Wrap
Text File
|
2004-04-11
|
12KB
|
309 lines
/*
* Copyright (C) 1997-2004 Andrei Los.
* This file is part of the lSwitcher source package.
* lSwitcher is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation, in version 2 as it comes in the
* "COPYING" file of the lSwitcher main distribution.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "lswitch.h"
#include "common.h"
#include "fsutil.h"
#include <string.h>
#include <stdio.h>
#include <process.h>
static HMONITOR hmonKbd = (HMONITOR)0;
static MONIN monInBuf = {0};
static MONOUT monOutBuf = {0};
VOID FSMonitor(VOID *plswData)
{ static USHORT usCount;
static KEYPACKET keybuf;
ULONG ulPostCount;
DosSetPrty(PRTYS_THREAD,PRTYC_TIMECRITICAL,+31,0);
while (DosWaitEventSem(((PLSWDATA)plswData)->hevRunning,0)==ERROR_TIMEOUT) {
usCount = sizeof(keybuf);
if (DosMonRead((PBYTE)&monInBuf,DCWW_WAIT,(PBYTE)&keybuf,&usCount)) break;
DosMonWrite((PBYTE)&monOutBuf,(PBYTE)&keybuf,usCount);
/* keybuf.mnflags>>8 is the scan code; check for the Tab key release*/
if ((keybuf.cp.fsState>>8)==(((PLSWDATA)plswData)->Settings.ucPopupHotKey==1?1:2) &&
(keybuf.mnflags>>8)==(SCAN_TAB | 0x80)) {
if (keybuf.cp.fsState & 3)
DosPostEventSem(((PLSWDATA)plswData)->hevShift);
else
DosResetEventSem(((PLSWDATA)plswData)->hevShift,&ulPostCount);
DosPostEventSem(((PLSWDATA)plswData)->hevPopup);
break;
}
}
}
VOID FSMonDispat(VOID *pParm)
{ PLSWDATA plswData;
SEL selGSeg,selLSeg;
PGINFOSEG GSeg;
UCHAR ucCurrId=0,ucId;
ULONG ulPostCount;
plswData = (PLSWDATA)pParm;
DosSetPriority(PRTYS_THREAD,PRTYC_TIMECRITICAL,+31,0);
DosGetInfoSeg(&selGSeg,&selLSeg);
GSeg=(PGINFOSEG)((selGSeg &~7)<<13);
if (DosCreateEventSem(SEMFSPOPUPNAME,&plswData->hevPopup,0,0)) return;
if (DosCreateEventSem(SEMSHIFTNAME,&plswData->hevShift,0,0)) return;
while(DosWaitEventSem(plswData->hevRunning,10L)==ERROR_TIMEOUT) {
/* if we popup in PM reset the semaphore and post a triggering message;
if we popup in FS create a thread which will monitor the keyboard and
display the popup menu, post the semaphore one more time so that we do
not accidentally create one more such thread because the first one didn't
have time to issue VioPopUp and thus change current FS session;
the semaphore will be reset when a keyboard monitor for this thread is
created */
if (DosWaitEventSem(plswData->hevPopup,200L)==0 &&
(DosQueryEventSem(plswData->hevPopup,&ulPostCount),ulPostCount==1)) {
if (plswData->Settings.bPMPopupInFS) {
DosQueryEventSem(plswData->hevShift,&ulPostCount);
WinPostMsg(plswData->hwndPopup,WM_COMMAND,
MPFROMSHORT(ulPostCount>0 ? CMD_SCROLLLEFTFROMFS : CMD_SCROLLRIGHTFROMFS),
MPFROM2SHORT(CMDSRC_OTHER,FALSE));
DosResetEventSem(plswData->hevPopup,&ulPostCount);
} else {
DosPostEventSem(plswData->hevPopup);
plswData->itidFSMon=_beginthread(FSPopUp,NULL,0x4000,plswData);
}
}
if ((ucId=GSeg->sgCurrent)!=ucCurrId) {
ucCurrId=ucId;
if (hmonKbd!=0) { DosMonClose(hmonKbd); hmonKbd=0; }
if (DosMonOpen("KBD$",&hmonKbd)==0) {
monInBuf.cb=sizeof(MONIN); monOutBuf.cb=sizeof(MONOUT);
if (DosMonReg(hmonKbd,(PBYTE)&monInBuf,(PBYTE)&monOutBuf,1,ucCurrId)==0) {
if (DosQueryEventSem(plswData->hevPopup,&ulPostCount),ulPostCount==0)
plswData->itidFSMon=_beginthread(FSMonitor,NULL,0x4000,plswData);
} else {
DosMonClose(hmonKbd); hmonKbd=0;
}
} else
hmonKbd=0;
DosResetEventSem(plswData->hevPopup,&ulPostCount);
}
}
DosSleep(200);
if (hmonKbd!=0) DosMonClose(hmonKbd);
}
/* this function returns the number of the item with given line number
counting from top in the popup menu */
SHORT ItemNumFromLineNum(LSWDATA *plswData,USHORT usLineNum)
{ SHORT item;
item = usLineNum+plswData->iShift+
(plswData->Settings.bScrollItems ? plswData->usCurrItem : 0)-
(min(MAXTEXTITEMS,plswData->usItems)-1)/2;
AdjustItem(item,plswData->usItems);
return item;
}
/* this thread monitors keyboard activity during the popup */
VOID FSPopUp(VOID *pParm)
{ static USHORT usCount;
static KEYPACKET keybuf;
UCHAR ucScan;
USHORT usCounter,usPopOpt;
ULONG ulPostCount;
BOOL bDoSwitch, bForward, bNowSticky;
PLSWDATA plswData;
plswData = (PLSWDATA)pParm;
// DosEnterCritSec();
DosSetPriority(PRTYS_THREAD,PRTYC_TIMECRITICAL,+31,0);
InitTaskArr(plswData,TRUE,FALSE,TRUE);
if (DosQueryEventSem(plswData->hevShift,&ulPostCount),ulPostCount > 0)
plswData->usCurrItem = plswData->usItems-1;
else
plswData->usCurrItem=1;
usPopOpt = 1;
VioPopUp(&usPopOpt,0);
/* wait until monitor dispatcher registeres a monitor for the popup session and
resets the semaphore */
usCounter = 0;
while (DosQueryEventSem(plswData->hevPopup,&ulPostCount),ulPostCount!=0) {
DosSleep(5);
usCounter++;
if (usCounter>200) {
VioEndPopUp(0);
return;
}
}
FSPopupMenu(plswData,0);
bDoSwitch = FALSE; bNowSticky = FALSE;
while (1) {
usCount = sizeof(keybuf);
if (DosMonRead((PBYTE)&monInBuf,DCWW_WAIT,(PBYTE)&keybuf,&usCount)) break;
DosMonWrite((PBYTE)&monOutBuf,(PBYTE)&keybuf,usCount);
// printf("%x %x %x\n",keybuf.cp.fbStatus,keybuf.cp.fsState,keybuf.mnflags>>8);
ucScan = keybuf.mnflags>>8;
if (ucScan == (SCAN_TAB | 0x80) || ucScan == SCAN_UP || ucScan == SCAN_DOWN) {
bForward = ((ucScan == (SCAN_TAB | 0x80) && !(keybuf.cp.fsState & 3)) || /*check shift status */
ucScan == SCAN_DOWN);
if (bForward) {
if (plswData->usCurrItem<plswData->usItems-1) plswData->usCurrItem++; else plswData->usCurrItem=0;
} else {
if (plswData->usCurrItem>0) plswData->usCurrItem--; else plswData->usCurrItem=plswData->usItems-1;
}
if (!plswData->Settings.bScrollItems && plswData->usItems>MAXTEXTITEMS &&
plswData->usCurrItem==
ItemNumFromLineNum(plswData, bForward ? MAXTEXTITEMS : -1)) {
plswData->iShift += (SHORT)(bForward ? MAXTEXTITEMS : -MAXTEXTITEMS)/3;
plswData->iShift -= plswData->iShift/(SHORT)plswData->usItems*plswData->usItems;
FSPopupMenu(plswData,0);
} else
FSPopupMenu(plswData,bForward ? 1 : -1);
} else if (ucScan==(((plswData->Settings.bStickyPopup||bNowSticky)?SCAN_ENTER:
plswData->Settings.ucPopupHotKey==0?SCAN_ALT:
plswData->Settings.ucPopupHotKey==1?SCAN_CTRL:SCAN_WINLEFT)|0x80)) { /*Enter, Ctrl or Alt or LeftWin release */
bDoSwitch = TRUE;
break;
} else if (ucScan == (SCAN_SPACE | 0x80) || /* space bar release */
((plswData->Settings.bStickyPopup||bNowSticky) && ucScan == SCAN_ESC))
break;
else if ((plswData->Settings.ucPopupHotKey==0 && ucScan == (SCAN_CTRL|0x80)) ||
(plswData->Settings.ucPopupHotKey==1 && ucScan == (SCAN_ALT|0x80)) ||
(plswData->Settings.ucPopupHotKey==2 && (ucScan == (SCAN_CTRL|0x80)||
ucScan == (SCAN_ALT|0x80))))
bNowSticky = TRUE;
}
// DosExitCritSec();
VioEndPopUp(0);
if (bDoSwitch)
WinPostMsg(plswData->hwndPopup,WM_COMMAND,MPFROMSHORT(CMD_SWITCHFROMFS),
MPFROM2SHORT(CMDSRC_OTHER,FALSE));
}
/* this function displays fullscreen popup menu.
cmd==0: initialize menu, cmd==1 move cursor to the next item, cmd==-1 to the
previous item */
void FSPopupMenu(LSWDATA *plswData,SHORT cmd)
{ static UCHAR ucAttr,ucLineBuf[TEXTSCRWID+1],ucTitle[NAMELEN],
ucCell[2]={32,MENUATTR}, ucMenuHgt, ucLineLen, ucMenuXLeft, ucMenuXRight,
ucMenuYTop, ucMenuYBottom;
USHORT k,usItem;
SHORT iLinesAboveSel;
VIOCURSORINFO CursorInfo;
if (cmd==0) {
memset(&CursorInfo,0,sizeof(VIOCURSORINFO)); CursorInfo.attr=-1;
VioSetCurType(&CursorInfo,0);
}
if (plswData->Settings.bOldPopup) {
if (cmd!=0) {
memset(ucLineBuf,0,sizeof(ucLineBuf));
GetItemTitle(plswData->TaskArr[plswData->usCurrItem].hsw,ucLineBuf,sizeof(ucLineBuf),TRUE);
ucLineBuf[TEXTSCRWID-1]=0; k=0; while (ucLineBuf[k]) k++;
memmove(&ucLineBuf[(TEXTSCRWID-k)>>1],ucLineBuf,k);
memset(ucLineBuf,0,(TEXTSCRWID-k)>>1);
ucAttr=MENUATTR;
VioWrtCharStrAtt(ucLineBuf,TEXTSCRWID,0,0,&ucAttr,0);
}
return;
}
iLinesAboveSel = (min(MAXTEXTITEMS,plswData->usItems)-1)/2-plswData->iShift+
(plswData->Settings.bScrollItems ? 0 : plswData->usCurrItem);
while (iLinesAboveSel > min(MAXTEXTITEMS,plswData->usItems)-1 || iLinesAboveSel < 0)
iLinesAboveSel -= (iLinesAboveSel<0?-1:1)*plswData->usItems;
if (cmd==0) {
ucLineLen = 0;
for (k = 0; k < plswData->usItems; k++) {
GetItemTitle(plswData->TaskArr[k].hsw,ucTitle,sizeof(ucTitle),TRUE);
if (strlen(ucTitle)>ucLineLen) ucLineLen=strlen(ucTitle);
}
ucLineLen += 2;
ucMenuHgt = min(MAXTEXTITEMS,plswData->usItems)+2;
ucMenuXLeft = TEXTSCRWID/2-ucLineLen/2;
ucMenuYTop = TEXTSCRHGT/2-ucMenuHgt/2;
ucMenuXRight = ucMenuXLeft+ucLineLen;
ucMenuYBottom = ucMenuYTop+ucMenuHgt;
for (k = 0; k < ucMenuHgt; k++) {
if (k==0) {
memset(ucLineBuf,205,ucLineLen); ucLineBuf[0]=201; ucLineBuf[ucLineLen-1]=187;
} else if (k==ucMenuHgt-1) {
memset(ucLineBuf,205,ucLineLen); ucLineBuf[0]=200; ucLineBuf[ucLineLen-1]=188;
} else {
usItem = ItemNumFromLineNum(plswData,k-1); //-1 takes care of the frame
GetItemTitle(plswData->TaskArr[usItem].hsw,ucTitle,sizeof(ucTitle),TRUE);
sprintf(ucLineBuf,"%c%-*s%c",186,ucLineLen-2,ucTitle,186);
}
ucAttr = MENUATTR;
VioWrtCharStrAtt(ucLineBuf,ucLineLen,ucMenuYTop+k,ucMenuXLeft,&ucAttr,0);
}
} else {
if (plswData->Settings.bScrollItems) {
if (cmd==1)
VioScrollUp(ucMenuYTop+1,ucMenuXLeft+1,ucMenuYBottom-2,ucMenuXRight-2,1,ucCell,0);
else
VioScrollDn(ucMenuYTop+1,ucMenuXLeft+1,ucMenuYBottom-2,ucMenuXRight-2,1,ucCell,0);
usItem = ItemNumFromLineNum(plswData,cmd==1 ? ucMenuHgt-3 : 0);
GetItemTitle(plswData->TaskArr[usItem].hsw,ucTitle,sizeof(ucTitle),TRUE);
sprintf(ucLineBuf,"%c%-*s%c",186,ucLineLen-2,ucTitle,186);
ucAttr=MENUATTR;
VioWrtCharStrAtt(ucLineBuf,ucLineLen,cmd==1 ? ucMenuYBottom-2 : ucMenuYTop+1,
ucMenuXLeft,&ucAttr,0);
VioWrtNAttr(&ucAttr,ucLineLen-2,ucMenuYTop+iLinesAboveSel+(cmd==1 ? 0 : 2),
ucMenuXLeft+1,0);
} else {
ucAttr=MENUATTR;
VioWrtNAttr(&ucAttr,ucLineLen-2,ucMenuYTop+iLinesAboveSel+
(cmd==1
? (iLinesAboveSel==0 ? ucMenuHgt-2 : 0)
: (iLinesAboveSel==ucMenuHgt-3 ? 1-iLinesAboveSel : 2)),
ucMenuXLeft+1,0);
}
}
ucAttr=CURSORATTR;
VioWrtNAttr(&ucAttr,ucLineLen-2,ucMenuYTop+iLinesAboveSel+1,ucMenuXLeft+1,0);
}