home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.wwiv.com
/
ftp.wwiv.com.zip
/
ftp.wwiv.com
/
pub
/
MISC
/
LSW270SR.ZIP
/
lswitch.c
< prev
next >
Wrap
C/C++ Source or Header
|
2004-04-11
|
37KB
|
964 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 "settings.h"
#include "taskbar.h"
#include "common.h"
#include "fsutil.h"
#include "prmdlg.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <process.h>
#include <ctype.h>
#include <unikbd.h>
/* we subclass the window procedure of the popup window frame */
static MRESULT EXPENTRY FrameWndProc(HWND hwnd,ULONG msg,MPARAM mp1,MPARAM mp2)
{
switch (msg) {
case WM_ADJUSTWINDOWPOS: {
SWP *pswp;
LSWDATA *plswData;
#ifndef XWORKPLACE
plswData = WinQueryWindowPtr(WinWindowFromID(hwnd,FID_CLIENT),0);
#else
plswData = ((PXCENTERWIDGET)WinQueryWindowPtr(WinWindowFromID(hwnd,FID_CLIENT),0))->pUser;
#endif
pswp = PVOIDFROMMP(mp1);
if (!plswData->bNowActive) {
/* make sure we are not brought to top or activated as a result of other
windows repositioning */
if (pswp->fl & SWP_ZORDER) pswp->fl &= ~SWP_ZORDER;
if (pswp->fl & SWP_ACTIVATE) pswp->fl &= ~SWP_ACTIVATE;
if (pswp->fl & SWP_SHOW)
WinPostMsg(plswData->hwndPopup,WM_COMMAND,MPFROMSHORT(CMD_SHOWSETTINGS),MPFROM2SHORT(CMDSRC_OTHER,FALSE));
}
}
default:
return ((PFNWP)WinQueryWindowPtr(hwnd,0))(hwnd,msg,mp1,mp2);
}
}
/* This function returns the bottom left corner coords of the usNum number
icon counting from the top left corner in the popup window */
VOID IconPosFromNumber(LSWDATA *plswData,USHORT usNum,USHORT *usPosX, USHORT *usPosY)
{ USHORT usLine,usLines,usGapX,usGapY,usIconsPerLine;
RECTL rcl;
ULONG cxIcon,cyIcon;
usIconsPerLine = min(plswData->usItems,MAXICONSINLINE);
usLine = usNum/MAXICONSINLINE+1;
usLines = min(ICONLINES,(plswData->usItems-1)/MAXICONSINLINE+1);
cxIcon = WinQuerySysValue(HWND_DESKTOP, SV_CXICON);
cyIcon = WinQuerySysValue(HWND_DESKTOP, SV_CYICON);
usGapX = cxIcon*ICONSPACINGX;
usGapY = cyIcon*ICONSPACINGY;
WinQueryWindowRect(plswData->hwndPopClient,&rcl);
*usPosX = rcl.xRight/2-
cxIcon*(usIconsPerLine-(usIconsPerLine%2==0?1:0))/2-
(usIconsPerLine-1)/2*usGapX+(usNum-(usLine-1)*MAXICONSINLINE)*(cxIcon+usGapX);
*usPosY = rcl.yTop-2*cyIcon*SELBOXOFFSET-SELBOXLINEWIDTH-
usLine*cyIcon-(usLine-1)*usGapY-WinQuerySysValue(HWND_DESKTOP,SV_CYSCREEN)/200;//popup window border size
}
/* This function returns the number of the item in the TaskArr from the number
of its icon counting from the top left corner in the popup window */
SHORT ItemNumFromIconNum(LSWDATA *plswData,SHORT iNum)
{ SHORT iItemNum;
USHORT usLines;
usLines = min(ICONLINES,(plswData->usItems-1)/MAXICONSINLINE+1);
iItemNum = plswData->iShift+iNum-
(min(MAXICONSINLINE,plswData->usItems)-1)/2-(usLines-1)/2*MAXICONSINLINE+
(plswData->Settings.bScrollItems ? plswData->usCurrItem : 0);
AdjustItem(iItemNum,plswData->usItems);
return iItemNum;
}
/* This function returns the number of the icon in the popup window
counting from the top left corner from the corresponding item number in the
TaskArr. */
SHORT IconNumFromItemNum(LSWDATA *plswData, USHORT usNum)
{ USHORT usLines, usLastIconNum;
SHORT iIconNum;
usLastIconNum = min(plswData->usItems,MAXICONSINLINE*ICONLINES)-1;
usLines = min(ICONLINES,(plswData->usItems-1)/MAXICONSINLINE+1);
iIconNum = usNum-plswData->iShift+
(min(MAXICONSINLINE,plswData->usItems)-1)/2+(usLines-1)/2*MAXICONSINLINE-
(plswData->Settings.bScrollItems ? plswData->usCurrItem : 0);
while (iIconNum > usLastIconNum || iIconNum < 0)
if (iIconNum > usLastIconNum)
iIconNum -= plswData->usItems;
else if (iIconNum < 0)
iIconNum += plswData->usItems;
return iIconNum;
}
/* This function returns the number of the item in the TaskArr
whose icon in the popup window is currently under the mouse pointer.
-1 is returned if mouse pointer does not point on any icon*/
SHORT ItemNumFromPos(LSWDATA *plswData, USHORT usX, USHORT usY)
{ USHORT usItemNum;
USHORT usPosX,usPosY,usGapX,usGapY,usCol,usRow;
ULONG cxIcon,cyIcon;
cxIcon = WinQuerySysValue(HWND_DESKTOP, SV_CXICON);
cyIcon = WinQuerySysValue(HWND_DESKTOP, SV_CYICON);
usGapX = cxIcon*ICONSPACINGX;
usGapY = cyIcon*ICONSPACINGY;
IconPosFromNumber(plswData,0,&usPosX,&usPosY);
usPosY+=cyIcon; //top left corner instead of the bottom left
usCol = (usX-usPosX)/(cxIcon+usGapX)+1;
usRow = (usPosY-usY)/(cyIcon+usGapY)+1;
usItemNum = ItemNumFromIconNum(plswData,(usRow-1)*MAXICONSINLINE+usCol-1);
/* check if mouse points on an icon */
if ((usRow-1)*MAXICONSINLINE+usCol<=plswData->usItems &&
usX>=usPosX+(usCol-1)*(cxIcon+usGapX) && usX<=usPosX+usCol*(cxIcon+usGapX)-usGapX &&
usY<=usPosY-(usRow-1)*(cyIcon+usGapY) && usY>=usPosY-usRow*(cyIcon+usGapY)+usGapY)
return usItemNum;
else
return -1;
}
VOID MakeHintStr(LSWDATA *plswData,USHORT usItem,UCHAR *ucStr,USHORT usStrLen)
{ UCHAR ucBuf[32],ucCmd[32],*pucTilde,ucHot;
USHORT k,l;
WinLoadString(plswData->hab,plswData->hmodRes,STRID_HINTS,usStrLen,ucStr);
for (k = CMD_HIDE; k <= CMD_CLOSE; k++)
if (MenuNeedsItem(plswData,usItem,k,ucBuf,sizeof(ucBuf),FALSE) && k!=CMD_MOVE) {
if ((pucTilde = strchr(ucBuf,'~'))!=NULL) {
memmove(pucTilde,pucTilde+1,strlen(pucTilde));
if (plswData->Settings.ucLanguage == RUSSIAN) {
if (*pucTilde >= 160 && *pucTilde <= 175)
ucHot = *pucTilde - 32;
else if (*pucTilde >= 224 && *pucTilde <= 239)
ucHot = *pucTilde - 80;
else
ucHot = *pucTilde;
} else
ucHot = toupper(*pucTilde);
}
if (plswData->Settings.ucLanguage == RUSSIAN) {
for (l=0; l < strlen(ucBuf); l++)
if (ucBuf[l] >= 128 && ucBuf[l]<= 143)
ucBuf[l] += 32;
else if (ucBuf[l] >= 144 && ucBuf[l] <= 159)
ucBuf[l] += 80;
} else if (plswData->Settings.ucLanguage != GERMAN)
strlwr(ucBuf);
sprintf(ucCmd," %c:%s",ucHot,ucBuf);
strncat(ucStr,ucCmd,usStrLen-strlen(ucStr)-1);
}
}
VOID AdjustPopupWin(LSWDATA *plswData,BOOL bInit)
{ USHORT cxPopup,cyPopup,cxIcon,cyIcon,usLines,usPosX,usPosY,
usTxtHgtTitle,usTxtHgtHints, usPopupBorderSize;
RECTL rcl;
HWND hwndTitle,hwndHints;
HPS hps;
POINTL aptl[TXTBOX_COUNT],ptl;
UCHAR ucBuf[2*NAMELEN];
SWP swp;
cxIcon = WinQuerySysValue(HWND_DESKTOP, SV_CXICON);
cyIcon = WinQuerySysValue(HWND_DESKTOP, SV_CYICON);
usPopupBorderSize=WinQuerySysValue(HWND_DESKTOP,SV_CYSCREEN)/200;
hwndTitle = WinWindowFromID(plswData->hwndPopClient,ID_TITLESTR);
hwndHints = WinWindowFromID(plswData->hwndPopClient,ID_HINTSTR);
if (bInit) {
WinSetPresParam(plswData->hwndPopClient,PP_BACKGROUNDCOLORINDEX,
sizeof(plswData->Settings.lBackColor),
&plswData->Settings.lBackColor);
WinSetPresParam(hwndTitle,PP_FONTNAMESIZE,
strlen(plswData->Settings.ucTitleFont)+1,
plswData->Settings.ucTitleFont);
WinSetPresParam(hwndTitle,PP_BACKGROUNDCOLOR,
sizeof(plswData->Settings.lBackColor),
&plswData->Settings.lBackColor);
WinSetPresParam(hwndTitle,PP_FOREGROUNDCOLOR,
sizeof(plswData->Settings.lTitleRGBCol),
&plswData->Settings.lTitleRGBCol);
WinSetPresParam(hwndHints,PP_BACKGROUNDCOLOR,
sizeof(plswData->Settings.lBackColor),
&plswData->Settings.lBackColor);
WinSetPresParam(hwndHints,PP_FOREGROUNDCOLOR,
sizeof(plswData->Settings.lHintsRGBCol),
&plswData->Settings.lHintsRGBCol);
WinSetAccelTable(plswData->hab,plswData->Settings.bStickyPopup?plswData->haccNoAlt:
plswData->Settings.ucPopupHotKey==0?plswData->haccAlt:
plswData->Settings.ucPopupHotKey==1?plswData->haccCtrl:plswData->haccNoAlt,
plswData->hwndPopup);
}
hps = WinGetPS(hwndTitle);
GpiQueryTextBox(hps,1L,"M",TXTBOX_COUNT,aptl);
WinReleasePS(hps);
usTxtHgtTitle = aptl[TXTBOX_TOPLEFT].y-aptl[TXTBOX_BOTTOMLEFT].y;
hps = WinGetPS(hwndHints);
GpiQueryTextBox(hps,1L,"M",TXTBOX_COUNT,aptl);
WinReleasePS(hps);
usTxtHgtHints = aptl[TXTBOX_TOPLEFT].y-aptl[TXTBOX_BOTTOMLEFT].y;
GetItemTitle(plswData->TaskArr[plswData->usCurrItem].hsw,ucBuf,sizeof(ucBuf),FALSE);
WinSetWindowText(hwndTitle,ucBuf);
MakeHintStr(plswData,plswData->usCurrItem,ucBuf,sizeof(ucBuf));
WinSetWindowText(hwndHints,ucBuf);
WinSendMsg(plswData->hwndPopup,WM_QUERYBORDERSIZE,MPFROMP(&ptl),0);
cxPopup = cxIcon*MAXICONSINLINE+cxIcon*(MAXICONSINLINE+2)*ICONSPACINGX+2*ptl.x+2*usPopupBorderSize;
usLines = plswData->Settings.bOldPopup ? 1 :
min(ICONLINES,(plswData->usItems-1)/MAXICONSINLINE+1);
cyPopup = usLines*cyIcon+(usLines-1)*cyIcon*ICONSPACINGY+
usTxtHgtTitle*
((plswData->Settings.bShowHints || plswData->Settings.bOldPopup) ? 2: 3)/2+
((plswData->Settings.bShowHints && !plswData->Settings.bOldPopup) ? usTxtHgtHints : 0)+
4*cyIcon*SELBOXOFFSET+2*SELBOXLINEWIDTH+
2*ptl.y+2*usPopupBorderSize;
WinQueryWindowPos(plswData->hwndPopup,&swp);
plswData->usPopupWinHideX=swp.x; plswData->usPopupWinHideY=swp.y;
WinSetWindowPos(plswData->hwndPopup, HWND_TOP,
(WinQuerySysValue(HWND_DESKTOP, SV_CXSCREEN)-cxPopup)/2,
(WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN)-cyPopup)/2,
cxPopup, cyPopup,
SWP_MOVE | SWP_SIZE |
(bInit? (SWP_ACTIVATE | SWP_ZORDER | SWP_SHOW) : 0));
// not sure if this is needed but sometimes the popup window hides immediately
// after showing. Maybe it doesn't get focus and WM_TIMER hides it, let's
// observe if this happens ever is we set the focus explicitly
if (bInit) WinSetFocus(HWND_DESKTOP,plswData->hwndPopClient);
WinQueryWindowRect(plswData->hwndPopClient,&rcl);
if (plswData->Settings.bOldPopup) {
WinSetWindowPos(hwndTitle, 0, cxIcon+cxIcon*ICONSPACINGX, 1,
rcl.xRight-cxIcon-cxIcon*ICONSPACINGX-2, rcl.yTop-2,
SWP_SIZE | SWP_MOVE);
WinSetWindowPos(hwndHints,0,0,0,0,0,SWP_SIZE | SWP_MOVE);
} else {
IconPosFromNumber(plswData, (usLines-1)*MAXICONSINLINE, &usPosX,&usPosY);
WinSetWindowPos(hwndTitle, 0,
1+usPopupBorderSize,
1+usPopupBorderSize+(plswData->Settings.bShowHints ? usTxtHgtHints : 0),
rcl.xRight-2-2*usPopupBorderSize,
usTxtHgtTitle*(plswData->Settings.bShowHints ? 2 : 3)/2,
SWP_SIZE | SWP_MOVE);
WinSetWindowPos(hwndHints,0,
plswData->Settings.bShowHints ? 1+usPopupBorderSize : 0,
plswData->Settings.bShowHints ? 1+usPopupBorderSize : 0,
plswData->Settings.bShowHints ? rcl.xRight-2-2*usPopupBorderSize : 0,
plswData->Settings.bShowHints ? usTxtHgtHints : 0,
SWP_SIZE | SWP_MOVE);
}
WinInvalidateRect(plswData->hwndPopClient,NULL,TRUE);
}
/* popup client window procedure */
static MRESULT EXPENTRY PopupWndProc(HWND hwnd,ULONG msg,MPARAM mp1,MPARAM mp2)
{ static ULONG cxIcon,cyIcon,cyPointer;
static HWND hwndTitle,hwndHints;
static BOOL bNowSticky=FALSE;
static USHORT usScrollCnt=0;
LSWDATA *plswData;
MRESULT mrc=0;
if (msg!=WM_CREATE)
#ifndef XWORKPLACE
plswData = WinQueryWindowPtr(hwnd,0);
#else
plswData = ((PXCENTERWIDGET)WinQueryWindowPtr(hwnd,0))->pUser;
#endif
switch (msg) {
case WM_HSCROLL:
case WM_VSCROLL:
usScrollCnt=++usScrollCnt%plswData->Settings.usScrollDiv;
if (usScrollCnt==0 && (SHORT2FROMMP(mp2)==SB_LINELEFT || SHORT2FROMMP(mp2)==SB_LINERIGHT))
WinPostMsg(hwnd,WM_COMMAND,MPFROMSHORT(SHORT2FROMMP(mp2)==SB_LINELEFT?CMD_SCROLLLEFT:CMD_SCROLLRIGHT),MPFROM2SHORT(CMDSRC_OTHER,FALSE));
break;
case WM_BUTTON1CLICK: {
SHORT iItemNum;
if (!plswData->Settings.bOldPopup &&
(iItemNum=ItemNumFromPos(plswData,SHORT1FROMMP(mp1),SHORT2FROMMP(mp1)))>=0) {
plswData->usCurrItem=iItemNum;
WinInvalidateRect(hwnd,NULL,FALSE);
DosSleep(50);
ProcessCommand(CMD_SWITCHFROMPM,CMDSRC_OTHER,plswData, FALSE,FALSE);
mrc=(MRESULT)TRUE;
}
break;
}
case WM_BUTTON2CLICK:
if (!plswData->Settings.bOldPopup &&
(plswData->iMenuAtItem=
ItemNumFromPos(plswData,SHORT1FROMMP(mp1),SHORT2FROMMP(mp1)))>=0) {
ShowMenu(plswData, plswData->iMenuAtItem,FALSE,FALSE);
ShowBubble(plswData,0,0,0,-1,NULL);
mrc=(MRESULT)TRUE;
}
break;
case WM_CHAR: {
USHORT usFlags;
UCHAR ucScan;
usFlags = SHORT1FROMMP(mp1); ucScan = CHAR4FROMMP(mp1);
if (plswData->bNowActive && (usFlags & KC_SCANCODE) && (usFlags & KC_KEYUP)) {
if ((plswData->Settings.ucPopupHotKey==0 && (ucScan==SCAN_CTRL || ucScan==SCAN_RIGHTCTRL)) ||
(plswData->Settings.ucPopupHotKey==1 && (ucScan==SCAN_ALT || ucScan==SCAN_RIGHTALT)) ||
(plswData->Settings.ucPopupHotKey==2 && (ucScan==SCAN_CTRL || ucScan==SCAN_RIGHTCTRL ||
ucScan==SCAN_ALT || ucScan==SCAN_RIGHTALT))) {
bNowSticky=TRUE;
WinSetAccelTable(plswData->hab,plswData->haccNoAlt, plswData->hwndPopup);
break;
}
// left alt, ctrl or winkey release, switch to the selected window
if (ucScan==((plswData->Settings.bStickyPopup||bNowSticky)?SCAN_ENTER:
plswData->Settings.ucPopupHotKey==0?SCAN_ALT:
plswData->Settings.ucPopupHotKey==1?SCAN_CTRL:SCAN_WINLEFT))
ProcessCommand(CMD_SWITCHFROMPM,CMDSRC_OTHER,plswData, FALSE,FALSE);
}
break;
}
case WM_COMMAND:
switch (SHORT1FROMMP(mp1)) {
case CMD_SCROLLLEFT:
case CMD_SCROLLRIGHT:
case CMD_SCROLLUP:
case CMD_SCROLLDOWN:
case CMD_SCROLLLEFTFROMFS:
case CMD_SCROLLRIGHTFROMFS: {
USHORT usPrevSel, usMaxIcons, usPosX, usPosY;
RECTL rcl,rcl1,rcl2;
BOOL bUpdateAll,bFullScreenInit,bForward,bNeedScroll;
UCHAR ucBuf[2*NAMELEN];
SHORT iCurrItem;
bFullScreenInit = SHORT1FROMMP(mp1)==CMD_SCROLLLEFTFROMFS ||
SHORT1FROMMP(mp1)==CMD_SCROLLRIGHTFROMFS;
if (!plswData->bNowActive) {
InitTaskArr(plswData,bFullScreenInit,FALSE,TRUE);
if (plswData->usItems == 0) break;
}
usMaxIcons = MAXICONSINLINE*ICONLINES;
usPrevSel = plswData->usCurrItem;
bForward = SHORT1FROMMP(mp1)==CMD_SCROLLRIGHT ||
SHORT1FROMMP(mp1)==CMD_SCROLLRIGHTFROMFS ||
SHORT1FROMMP(mp1)==CMD_SCROLLDOWN;
bNeedScroll = FALSE;
switch SHORT1FROMMP(mp1) {
case CMD_SCROLLLEFT:
case CMD_SCROLLLEFTFROMFS: iCurrItem = usPrevSel - 1; break;
case CMD_SCROLLRIGHT:
case CMD_SCROLLRIGHTFROMFS: iCurrItem = usPrevSel + 1; break;
case CMD_SCROLLUP:
case CMD_SCROLLDOWN: {
SHORT iRow;
USHORT usRows,usCol,usIconNum;
usIconNum = IconNumFromItemNum(plswData,usPrevSel);
usRows = min(ICONLINES,(plswData->usItems-1)/MAXICONSINLINE+1);
if (usRows == 1) { iCurrItem = usPrevSel; break; }
iRow = usIconNum/MAXICONSINLINE;
usCol = usIconNum-iRow*MAXICONSINLINE;
if (plswData->usItems <= usMaxIcons) {
if (SHORT1FROMMP(mp1) == CMD_SCROLLUP)
if (iRow == 0) iRow = usRows-1; else iRow--;
else
if (iRow == usRows-1) iRow = 0; else iRow++;
iCurrItem = usPrevSel+min(iRow*MAXICONSINLINE+usCol,plswData->usItems-1)-
usIconNum;
} else {
iCurrItem = usPrevSel +
(SHORT1FROMMP(mp1) == CMD_SCROLLUP ? -MAXICONSINLINE : MAXICONSINLINE);
bNeedScroll = (iRow==ICONLINES-1 && bForward) || (iRow==0 && !bForward);
}
break;
}
}
AdjustItem(iCurrItem,plswData->usItems);
plswData->usCurrItem = iCurrItem;
/* check if the number of items is larger than fits in the window and we are
at a window end so we need to scroll */
if (!plswData->Settings.bScrollItems && plswData->usItems>usMaxIcons &&
(plswData->usCurrItem ==
ItemNumFromIconNum(plswData,bForward ? usMaxIcons : -1) ||
bNeedScroll)) {
plswData->iShift += (SHORT)(bForward ? MAXICONSINLINE : -MAXICONSINLINE);
plswData->iShift -= plswData->iShift/(SHORT)plswData->usItems*plswData->usItems;
bUpdateAll = TRUE;
} else
bUpdateAll = FALSE;
if (!plswData->bNowActive) {
// this must be just before adjusting the window, otherwise if it's after,
// the subclassed frame window proc won't let us do repositioning;
// if it's much before, the WM_TIMER might have time to hide the window
plswData->bNowActive = TRUE; bNowSticky = FALSE;
if (bFullScreenInit) WinSwitchToProgram(plswData->hswitch);
AdjustPopupWin(plswData,TRUE);
} else {
if (plswData->Settings.bScrollItems || plswData->Settings.bOldPopup ||
bUpdateAll) {
WinQueryWindowRect(hwnd,&rcl);
if (plswData->Settings.bOldPopup) {
WinSetRect(plswData->hab,&rcl,1,1,rcl.xRight-2,rcl.yTop-2);
} else {
WinQueryWindowRect(hwndHints,&rcl1);
WinSetRect(plswData->hab,&rcl,1,1+rcl1.yTop,rcl.xRight-2,rcl.yTop-2);
}
} else {
IconPosFromNumber(plswData, IconNumFromItemNum(plswData,usPrevSel),
&usPosX,&usPosY);
WinSetRect(plswData->hab,&rcl1, usPosX-cxIcon*SELBOXOFFSET-SELBOXLINEWIDTH,
usPosY-cyIcon*SELBOXOFFSET-SELBOXLINEWIDTH,
usPosX+cxIcon+cxIcon*SELBOXOFFSET+SELBOXLINEWIDTH,
usPosY+cyIcon+cyIcon*SELBOXOFFSET+SELBOXLINEWIDTH);
IconPosFromNumber(plswData, IconNumFromItemNum(plswData,plswData->usCurrItem),
&usPosX,&usPosY);
WinSetRect(plswData->hab,&rcl2, usPosX-cxIcon*SELBOXOFFSET-SELBOXLINEWIDTH,
usPosY-cyIcon*SELBOXOFFSET-SELBOXLINEWIDTH,
usPosX+cxIcon+cxIcon*SELBOXOFFSET+SELBOXLINEWIDTH,
usPosY+cyIcon+cyIcon*SELBOXOFFSET+SELBOXLINEWIDTH);
WinUnionRect(plswData->hab,&rcl,&rcl1,&rcl2);
}
WinInvalidateRect(hwnd,&rcl,FALSE);
GetItemTitle(plswData->TaskArr[plswData->usCurrItem].hsw,ucBuf,sizeof(ucBuf),FALSE);
WinSetWindowText(hwndTitle,ucBuf);
MakeHintStr(plswData,plswData->usCurrItem,ucBuf,sizeof(ucBuf));
WinSetWindowText(hwndHints,ucBuf);
}
break;
}
default:
if (plswData->bNowActive &&
(SHORT1FROMMP(mp1)==CMD_SWITCHFROMPM || SHORT1FROMMP(mp1)==CMD_CANCELPOPUP || SHORT1FROMMP(mp1)==CMD_CANCELPOPUP1)) {
UCHAR ucBuf[128];
usScrollCnt=0;
WinQueryPresParam(hwndTitle,PP_FONTNAMESIZE,0,NULL,sizeof(ucBuf),ucBuf,QPF_NOINHERIT);
strncpy(plswData->Settings.ucTitleFont,ucBuf,sizeof(plswData->Settings.ucTitleFont));
WinQueryPresParam(hwndHints,PP_FONTNAMESIZE,0,NULL,sizeof(ucBuf),ucBuf,QPF_NOINHERIT);
strncpy(plswData->Settings.ucHintsFont,ucBuf,sizeof(plswData->Settings.ucHintsFont));
WinQueryPresParam(hwndTitle,PP_FOREGROUNDCOLOR,0,NULL,sizeof(ucBuf),ucBuf,QPF_NOINHERIT);
plswData->Settings.lTitleRGBCol = ucBuf[0]+ucBuf[1]*256+ucBuf[2]*65536;
WinQueryPresParam(hwndHints,PP_FOREGROUNDCOLOR,0,NULL,sizeof(ucBuf),ucBuf,QPF_NOINHERIT);
plswData->Settings.lHintsRGBCol = ucBuf[0]+ucBuf[1]*256+ucBuf[2]*65536;
}
ProcessCommand(SHORT1FROMMP(mp1),SHORT1FROMMP(mp2),plswData, FALSE,FALSE);
}
break;
case WM_CREATE: {
DosGetNamedSharedMem((PVOID*)&plswData,SHAREMEM_NAME,PAG_READ | PAG_WRITE);
WinStartTimer(plswData->hab, hwnd, 0, BUBBLETIMERINTERVAL);
plswData->hwndMenu = WinCreateMenu(HWND_DESKTOP, NULL);
WinSetPresParam(plswData->hwndMenu,PP_FONTNAMESIZE,7,"8.Helv");
hwndTitle = WinCreateWindow(hwnd,WC_STATIC,"",
WS_VISIBLE | SS_TEXT | DT_CENTER | DT_VCENTER,
0,0,0,0,hwnd,HWND_TOP,ID_TITLESTR,NULL,NULL);
hwndHints = WinCreateWindow(hwnd,WC_STATIC,"",
WS_VISIBLE | SS_TEXT | DT_CENTER | DT_VCENTER,
0,0,0,0,hwnd,HWND_TOP,ID_HINTSTR,NULL,NULL);
WinSetPresParam(hwndHints,PP_FONTNAMESIZE,strlen(plswData->Settings.ucHintsFont)+1,plswData->Settings.ucHintsFont);
#ifndef XWORKPLACE
WinSetWindowPtr(hwnd, 0, plswData);
#else
WinSetWindowPtr(hwnd, 0, plswData->pWidget);
#endif
DosFreeMem(plswData);
}
case WM_SYSVALUECHANGED:
cxIcon = WinQuerySysValue(HWND_DESKTOP, SV_CXICON);
cyIcon = WinQuerySysValue(HWND_DESKTOP, SV_CYICON);
cyPointer=WinQuerySysValue(HWND_DESKTOP, SV_CYPOINTER);
break;
case WM_MENUEND:
WinSetWindowPos(plswData->hwndMenu,HWND_BOTTOM,0,0,0,0,SWP_ZORDER);
if (plswData->bNowActive) WinSetFocus(HWND_DESKTOP,hwnd);
break;
case WM_ERASEBACKGROUND:
mrc = (MRESULT)FALSE;
break;
case WM_PAINT: {
HPS hps;
RECTL rclUpdate, rclWnd, rclSelBox;
USHORT k,usPosX,usPosY,usItemNum,usBorderSize,usR,usB,usG;
POINTL ptl;
hps = WinBeginPaint(hwnd,NULLHANDLE,&rclUpdate);
WinQueryWindowRect(hwnd, &rclWnd);
GpiCreateLogColorTable(hps, 0, LCOLF_RGB, 0, 0, NULL);
WinFillRect(hps,&rclUpdate,plswData->Settings.lBackColor);
usBorderSize=WinQuerySysValue(HWND_DESKTOP,SV_CYSCREEN)/200;
usR=(plswData->Settings.lBackColor&0xFF0000)>>16,
usG=(plswData->Settings.lBackColor&0xFF00)>>8,
usB=(plswData->Settings.lBackColor&0xFF);
for (k=1;k<=usBorderSize;k++) {
ULONG ulColor;
ulColor=(230-usB)/usBorderSize*(/*usBorderSize-*/k)+usB+
((230-usG)/usBorderSize*(/*usBorderSize-*/k)+usG)*256+
((230-usR)/usBorderSize*(/*usBorderSize-*/k)+usR)*65536;
WinDrawBorder(hps,&rclWnd,1,1,ulColor,ulColor,0);
rclWnd.xLeft+=1; rclWnd.xRight-=1; rclWnd.yBottom+=1; rclWnd.yTop-=1;
}
if (plswData->Settings.bOldPopup) {
WinDrawPointer(hps,rclWnd.xLeft+cxIcon*ICONSPACINGX,
(rclWnd.yTop+rclWnd.yBottom-cyIcon)/2,
plswData->TaskArr[plswData->usCurrItem].hIcon,DP_NORMAL);
} else {
/* Draw icons */
for (k = 0; k < min(MAXICONSINLINE*ICONLINES,plswData->usItems); k++) {
IconPosFromNumber(plswData,k,&usPosX,&usPosY);
usItemNum = ItemNumFromIconNum(plswData,k);
WinDrawPointer(hps, usPosX, usPosY, plswData->TaskArr[usItemNum].hIcon,DP_NORMAL|
(plswData->TaskArr[usItemNum].fl&(SWP_HIDE|SWP_MINIMIZE))?DP_HALFTONED:0);
/* Draw selection box */
if (usItemNum == plswData->usCurrItem) {
WinSetRect(plswData->hab,&rclSelBox,
usPosX-cxIcon*SELBOXOFFSET-1, usPosY-cyIcon*SELBOXOFFSET-1,
usPosX+cxIcon*SELBOXOFFSET+cxIcon+1,usPosY+cyIcon*SELBOXOFFSET+cyIcon+1);
WinDrawBorder(hps,&rclSelBox,SELBOXLINEWIDTH,SELBOXLINEWIDTH,
plswData->Settings.lSunkenFrameColor,
plswData->Settings.lRaisedFrameColor,DB_DEPRESSED);
}
}
}
WinEndPaint(hps);
break;
}
case LSWM_WNDSTATECHANGED:
if (SHORT2FROMMP(mp1) & (SWP_RESTORE|SWP_MAXIMIZE|SWP_SHOW))
MinimizeHideAll(plswData, TRUE, HWNDFROMMP(mp2));
case LSWM_WNDICONCHANGED: {
USHORT k,usPosX,usPosY;
RECTL rcl;
UCHAR ucBuf[150];
BOOL bNeedUpdate;
if (!plswData->bNowActive) break;
for (k=0;k<plswData->usItems;k++)
if (plswData->TaskArr[k].hwnd==HWNDFROMMP(mp2)) {
if (msg==LSWM_WNDICONCHANGED) {
plswData->TaskArr[k].hIcon=LONGFROMMP(mp1);
WinSendMsg(HWNDFROMMP(mp2),WM_NULL,0,0); // to make sure the icon handle has become valid
bNeedUpdate = TRUE;
} else {
bNeedUpdate = UpdateWinFlags(&plswData->TaskArr[k].fl, SHORT2FROMMP(mp1));
if (plswData->TaskArr[MAXITEMS-1].hwnd == plswData->TaskArr[k].hwnd)
plswData->TaskArr[MAXITEMS-1].fl = plswData->TaskArr[k].fl;
if (k==plswData->usCurrItem && bNeedUpdate) {
MakeHintStr(plswData,k,ucBuf,sizeof(ucBuf)); //change hints to reflect the changed task state
WinSetWindowText(hwndHints,ucBuf);
}
}
if (bNeedUpdate) {
IconPosFromNumber(plswData, IconNumFromItemNum(plswData,k), &usPosX,&usPosY);
WinSetRect(plswData->hab,&rcl,usPosX,usPosY,usPosX+cxIcon,usPosY+cyIcon);
WinInvalidateRect(hwnd,&rcl,FALSE);
}
break;
}
break;
}
case LSWM_SWITCHLISTCHANGED: {
USHORT k;
UCHAR ucBuf[NAMELEN];
if (!plswData->bNowActive) break;
for (k=0;k<plswData->usItems;k++) {
if (plswData->TaskArr[k].hsw!=LONGFROMMP(mp2)) continue;
if (LONGFROMMP(mp1)==2) ShowBubble(plswData,k,0,0,11,NULL); //update bubble
if (LONGFROMMP(mp1)==2 && k==plswData->usCurrItem) {
GetItemTitle(plswData->TaskArr[k].hsw,ucBuf,sizeof(ucBuf),FALSE);
WinSetWindowText(hwndTitle,ucBuf);
}
if ((LONGFROMMP(mp1)==2 &&
(GetItemTitle(plswData->TaskArr[k].hsw,ucBuf,sizeof(ucBuf),FALSE),
IsInSkipList(&plswData->Settings,ucBuf,FALSE))) ||
LONGFROMMP(mp1)==3) {
memmove(&plswData->TaskArr[k],&plswData->TaskArr[k+1],sizeof(SWITEM)*(plswData->usItems-k-1));
plswData->usItems--;
if (plswData->usItems==0)
ProcessCommand(CMD_CANCELPOPUP1,CMDSRC_OTHER,plswData, FALSE,FALSE);//cancel popup and don't return to original session
else if (WinQueryFocus(HWND_DESKTOP)==plswData->hwndPopClient && !plswData->Settings.bOldPopup)
AdjustPopupWin(plswData,FALSE);
break;
}
}
break;
}
case WM_PRESPARAMCHANGED: {
LONG lParam, lValue;
UCHAR ucBuf[64];
lParam = LONGFROMMP(mp1);
if (!(lParam==PP_FOREGROUNDCOLOR || lParam==PP_BACKGROUNDCOLOR) ||
(LONG)WinQueryPresParam(hwnd,lParam,0,NULL,sizeof(ucBuf),ucBuf,QPF_NOINHERIT)==0)
break;
lValue = ucBuf[0]+ucBuf[1]*256+ucBuf[2]*65536;
switch(lParam) {
case PP_BACKGROUNDCOLOR:
plswData->Settings.lBackColor = plswData->Settings.lTitleRGBCol =
plswData->Settings.lHintsRGBCol = lValue;
WinSetPresParam(hwndTitle,PP_BACKGROUNDCOLOR,4,&lValue);
WinSetPresParam(hwndHints,PP_BACKGROUNDCOLOR,4,&lValue);
WinInvalidateRect(hwnd,NULL,TRUE);
break;
}
break;
}
case WM_TIMER: {
static SHORT iMouseIsAtItem;
POINTL ptl;
SWP swp1,swp2;
HWND hwndFocus;
if (plswData->bNowActive) {
if (WinQueryFocus(HWND_DESKTOP) == plswData->hwndPopClient &&
WinQueryWindow(HWND_DESKTOP,QW_TOP) != plswData->hwndPopup)
WinSetWindowPos(plswData->hwndPopup,WinIsWindowVisible(plswData->hwndBubble)?
plswData->hwndBubble:HWND_TOP,0,0,0,0,SWP_ZORDER);
hwndFocus = WinQueryFocus(HWND_DESKTOP);
if (hwndFocus != plswData->hwndPopClient && hwndFocus != plswData->hwndMenu &&
WinQueryWindow(hwndFocus,QW_OWNER) != plswData->hwndMenu)
ProcessCommand(CMD_CANCELPOPUP1,CMDSRC_OTHER,plswData, FALSE,FALSE);//cancel popup and don't return to original session
else if (!(plswData->Settings.bStickyPopup||bNowSticky) &&
(WinGetPhysKeyState(HWND_DESKTOP,(plswData->Settings.ucPopupHotKey==0?SCAN_ALT:
plswData->Settings.ucPopupHotKey==1?SCAN_CTRL:
SCAN_WINLEFT)) & 0x8000)==0)
ProcessCommand(CMD_SWITCHFROMPM,CMDSRC_OTHER,plswData, FALSE,FALSE);
}
/* check if mouse pointer is inside the popup window and above an icon */
if (plswData->bNowActive && (WinQueryPointerPos(HWND_DESKTOP,&ptl),
WinQueryWindowPos(plswData->hwndPopup,&swp1),WinQueryWindowPos(hwnd,&swp2),
(ptl.x>=swp1.x+swp2.x && ptl.y>=swp1.y+swp2.y &&
ptl.x<=swp1.x+swp2.x+swp2.cx && ptl.y<=swp1.y+swp2.y+swp2.cy)) &&
(iMouseIsAtItem=
ItemNumFromPos(plswData,ptl.x-swp1.x-swp2.x,ptl.y-swp1.y-swp2.y))>=0 &&
!WinIsWindowVisible(plswData->hwndMenu))
ShowBubble(plswData,iMouseIsAtItem,ptl.x,ptl.y-cyPointer-1,1,NULL);
else
ShowBubble(plswData,0,0,0,-1,NULL);
break;
}
default:
mrc = WinDefWindowProc(hwnd, msg, mp1, mp2);
}
return mrc;
}
LONG SwitcherInit(HAB hab, HMQ hmq, UCHAR *ucErrMsg, USHORT usMsgLen, PVOID *ppData, USHORT usFunc)
{ ULONG flFrameFlags,ulHookVer;
LONG rc,rc1 = 0;
LSWDATA *plswData;
UCHAR ucFName[CCHMAXPATH], ucResLang,ucFound=0,ucLangStr[32];
SWCNTRL swctl;
// usFunc is 0 for app initialization, 1 and for widget phases 1 and 2 initialization
if (usFunc != 1)
DosSetPriority(PRTYS_THREAD,PRTYC_TIMECRITICAL,+31,0);
if (usFunc != 2) {
//need to loop so that search handle is closed
while (FindResDll(ucFName, sizeof(ucFName), &ucResLang, ucLangStr, sizeof(ucLangStr)))
if (ucResLang!=0) ucFound=1;
if (!ucFound) {
strncpy(ucErrMsg,"Could not find resource DLL or resource DLL invalid error",usMsgLen);
return 1;
}
ulHookVer = lswHookGetVersion();
if (LOUCHAR(LOUSHORT(ulHookVer)) < LASTHOOKVERMAJOROK ||
HIUCHAR(LOUSHORT(ulHookVer)) < LASTHOOKVERMINOROK ||
LOUCHAR(HIUSHORT(ulHookVer)) < LASTHOOKREVISIONOK) {
strncpy(ucErrMsg,"Wrong hook DLL version error",usMsgLen);
return 1;
}
if (!WinRegisterClass(hab,LSWPOPUPCLASS,PopupWndProc,CS_SAVEBITS|CS_SYNCPAINT,sizeof(PLSWDATA))) {
strncpy(ucErrMsg,"WinRegisterClass(lswPopupClass) error",usMsgLen);
return WinGetLastError(hab);
}
if ((rc = DosAllocSharedMem((VOID*)&plswData,SHAREMEM_NAME,sizeof(LSWDATA),PAG_COMMIT | PAG_READ | PAG_WRITE))!=0) {
strncpy(ucErrMsg,"DosAllocSharedMem error",usMsgLen);
return rc;
}
memset(plswData,0,sizeof(LSWDATA));
*ppData = (PVOID)plswData;
#ifdef XWORKPLACE
plswData->bWidget = TRUE;
#endif
plswData->hab = hab;
plswData->hmq = hmq;
GetIniFileName(ucFName,sizeof(ucFName));
if (LoadSettings(hab,ucFName,&plswData->Settings)!=0) rc1=LSWERRCANTLOADSETTINGS;
if (rc1==0 && !CheckSettings(&plswData->Settings)) rc1=LSWERROLDSETTINGS;
if (rc1 < 0)
InitSettings(&plswData->Settings);
else if (plswData->Settings.sTskBarCX>WinQuerySysValue(HWND_DESKTOP,SV_CXSCREEN)+2) {
plswData->Settings.sTskBarX = -TSKBARFRAMEWIDTH;
if (plswData->Settings.bTaskBarTopScr)
plswData->Settings.sTskBarY = WinQuerySysValue(HWND_DESKTOP,SV_CYSCREEN)-plswData->Settings.sTskBarCY+TSKBARFRAMEWIDTH;
else
plswData->Settings.sTskBarY = -TSKBARFRAMEWIDTH;
plswData->Settings.sTskBarCX = WinQuerySysValue(HWND_DESKTOP,SV_CXSCREEN)+2*TSKBARFRAMEWIDTH;
plswData->Settings.sTskBarCY = WinQuerySysValue(HWND_DESKTOP,SV_CYICON)/2+4+2*BUTTONBORDERWIDTH+2+2*TSKBARFRAMEWIDTH;
}
}
if (usFunc != 1) {
#ifdef XWORKPLACE
if (usFunc==2) plswData=(PLSWDATA)(*ppData);
#endif
if ((plswData->hmodRes=LoadResource(plswData->Settings.ucLanguage, plswData, TRUE))==0) {
strncpy(ucErrMsg,"Could not load resources ",usMsgLen);
return 1;
}
if ((rc = DosCreateEventSem(SEMRUNNINGNAME,&plswData->hevRunning,0,0)) ||
(rc = DosCreateEventSem(SEMCTRLTABNAME,&plswData->hevCtrlTab,0,
(plswData->Settings.ucPopupHotKey==1))) ||
(rc = DosCreateEventSem(SEMWINTABNAME,&plswData->hevWinTab,0,
(plswData->Settings.ucPopupHotKey==2)))) {
strncpy(ucErrMsg,"DosCreateEventSem",usMsgLen);
return rc;
}
flFrameFlags = FCF_BORDER;
#ifndef XWORKPLACE
flFrameFlags |= FCF_TASKLIST | FCF_ICON;
#endif
plswData->hwndPopup = WinCreateStdWindow(HWND_DESKTOP,0,&flFrameFlags,
LSWPOPUPCLASS,"",
0,0,ID_POPUPWIN,&plswData->hwndPopClient);
if (plswData->hwndPopup==NULLHANDLE) {
strncpy(ucErrMsg,"WinCreateStdWin(lswPopupWin)",usMsgLen);
return WinGetLastError(hab);
}
plswData->usPopupWinHideX=POPUPWINHIDEPOSX;
plswData->usPopupWinHideY=POPUPWINHIDEPOSY;
WinSetWindowPos(plswData->hwndPopup,HWND_BOTTOM, plswData->usPopupWinHideX, plswData->usPopupWinHideY,
0, 0, SWP_MOVE | SWP_SIZE | SWP_SHOW | SWP_DEACTIVATE | SWP_ZORDER);
WinSetWindowPtr(plswData->hwndPopup, 0, (VOID *)WinSubclassWindow(plswData->hwndPopup, FrameWndProc));
plswData->hwndBubble = WinCreateWindow(HWND_DESKTOP,WC_STATIC,"",
SS_TEXT | DT_CENTER | DT_VCENTER,
0,0,0,0,0,HWND_BOTTOM,ID_BUBBLE,NULL,NULL);
WinSetPresParam(plswData->hwndBubble,PP_FONTNAMESIZE,7,"8.Helv");
WinSetPresParam(plswData->hwndBubble,PP_BACKGROUNDCOLOR,
sizeof(plswData->Settings.lBubbleRGBCol),
&plswData->Settings.lBubbleRGBCol);
WinSetPresParam(plswData->hwndBubble,PP_FOREGROUNDCOLOR,
sizeof(plswData->Settings.lBubbleTextRGBCol),
&plswData->Settings.lBubbleTextRGBCol);
WinCreateWindow(plswData->hwndBubble,WC_STATIC,"",SS_HALFTONEFRAME,
0,0,0,0,0,HWND_TOP,ID_BUBBLEFRAME,NULL,NULL);
if ((plswData->itidFSDispat = _beginthread(FSMonDispat,NULL,0x4000,plswData))<0) {
strncpy(ucErrMsg,"_beginthread",usMsgLen);
return plswData->itidFSDispat;
}
if ((rc = lswHookInit(plswData)) < 0) {
strncpy(ucErrMsg,"lswHookInit",usMsgLen);
return (-rc);
}
#ifndef XWORKPLACE
plswData->hswitch = WinQuerySwitchHandle(plswData->hwndPopup, 0);
WinQuerySwitchEntry(plswData->hswitch, &swctl);
swctl.uchVisibility = plswData->Settings.bShowInWinList ? SWL_VISIBLE : SWL_INVISIBLE;
WinChangeSwitchEntry(plswData->hswitch, &swctl);
if (plswData->Settings.bTaskBarOn)
if ((rc = InitTaskBar(plswData,ucErrMsg,usMsgLen)) != 0)
return rc;
if ((rc = DosExitList(EXLST_ADD, (PFNEXITLIST)lswExitProc)) !=0 ) {
strncpy(ucErrMsg,"DosExitList",usMsgLen);
return rc;
}
#else
if (plswData->pWidget->pGlobals!=NULL) plswData->hswitch = WinQuerySwitchHandle(plswData->pWidget->pGlobals->hwndFrame, 0);
#endif
}
return rc1;
}
VOID SwitcherTerm(LSWDATA *plswData,USHORT usFunc)
{
// usFunc is 0 for app termination, 1 and 2 for widget phases 1 and 2 termination
if (usFunc!=2) {
lswHookTerm(plswData);
DosPostEventSem(plswData->hevRunning);
DosSleep(500);
#ifndef XWORKPLACE
DoneTaskBar(plswData);
#endif
DosCloseEventSem(plswData->hevShift);
DosCloseEventSem(plswData->hevPopup);
DosCloseEventSem(plswData->hevRunning);
DosCloseEventSem(plswData->hevCtrlTab);
DosCloseEventSem(plswData->hevWinTab);
WinDestroyWindow(plswData->hwndPopup);
if (plswData->bSettingsDlgOn) WinDestroyWindow(plswData->hwndParamDlg);
DosFreeModule(plswData->hmodRes);
}
#ifndef XWORKPLACE
WinDestroyMsgQueue(plswData->hmq);
WinTerminate(plswData->hab);
#endif
if (usFunc!=1)
DosFreeMem(plswData);
}
VOID APIENTRY lswExitProc()
{ LSWDATA *plswData;
DosGetNamedSharedMem((PVOID*)&plswData,SHAREMEM_NAME,PAG_READ | PAG_WRITE);
if (plswData!=NULL) SwitcherTerm(plswData,0);
DosExitList(EXLST_EXIT, (PFNEXITLIST)lswExitProc);
}