home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.wwiv.com
/
ftp.wwiv.com.zip
/
ftp.wwiv.com
/
pub
/
MISC
/
LSW270SR.ZIP
/
common.c
next >
Wrap
Text File
|
2004-04-11
|
52KB
|
1,432 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 <process.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include "common.h"
#include "msg.h"
#include "apm.h"
#include "prmdlg.h"
#include "settings.h"
#ifdef XWORKPLACE
#include "dlgids.h"
#endif
ULONG MapCommand(USHORT cmd)
{
switch (cmd) {
case CMD_HIDE: return MAKEULONG(SC_HIDE,SWP_HIDE);
case CMD_MAXIMIZE: return MAKEULONG(SC_MAXIMIZE,SWP_MAXIMIZE);
case CMD_MINIMIZE: return MAKEULONG(SC_MINIMIZE,SWP_MINIMIZE);
case CMD_RESTORE: return MAKEULONG(SC_RESTORE,SWP_RESTORE);
case CMD_SHOW: return MAKEULONG(0,SWP_SHOW);
case CMD_MOVE: return MAKEULONG(SC_MOVE,SWP_MOVE);
case CMD_CLOSE: return MAKEULONG(SC_CLOSE,0);
default: return 0;
}
}
/* This advanced killing Copyright (C)1996 by Holger.Veit@gmd.de */
HFILE OpenXF86(VOID)
{ HFILE hfd;
ULONG action;
if (DosOpen((PSZ)"/dev/fastio$", (PHFILE)&hfd, &action, 0, FILE_SYSTEM, FILE_OPEN,
OPEN_SHARE_DENYNONE|OPEN_FLAGS_NOINHERIT|OPEN_ACCESS_READONLY, 0)!=0)
return 0;
else
return hfd;
}
BOOL Death(PID pid)
{ HFILE hfd;
ULONG plen;
USHORT param;
if ((hfd=OpenXF86())==0) return FALSE;
param = pid;
if (DosDevIOCtl(hfd,0x76,0x65,(PULONG*)¶m,sizeof(USHORT),&plen,NULL,0,NULL)!=0) {
DosClose(hfd);
return FALSE;
}
DosClose(hfd);
return TRUE;
}
PID GetWPSPid(VOID)
{ HWND hwnd;
PID pid; TID tid;
if (hwnd=WinQueryWindow(HWND_DESKTOP,QW_BOTTOM),IsWindowClass(hwnd,"wpFolder window")) {
WinQueryWindowProcess(hwnd,&pid,&tid);
return pid;
} else
return 0;
}
SHORT TaskArrItemFromHsw(LSWDATA *plswData,USHORT hsw,BOOL bUseFilters)
{ SHORT iItem,k;
InitTaskArr(plswData,FALSE,TRUE,bUseFilters);
for(k=0,iItem=-1;k<plswData->usItems && iItem<0;k++)
if ((plswData->TaskArr[k].hsw & 0xFFFF)==hsw) iItem=k;
return iItem;
}
BOOL ChangeWindowPos(LSWDATA *plswData,SHORT iItemNum,USHORT cmd)
{ USHORT cmd1;
BOOL bDoIt;
cmd1=LOUSHORT(MapCommand(cmd));
bDoIt = ((cmd==CMD_KILL || cmd==CMD_DEATH || cmd==CMD_CLOSE || cmd==CMD_CLOSEQUIT) ? TRUE :
cmd == CMD_SHOW ? (!(plswData->TaskArr[iItemNum].fl & SWP_SHOW)):
WndHasControl(plswData->hab,plswData->TaskArr[iItemNum].hwnd,cmd1));
if (bDoIt) {
if (cmd==CMD_SHOW)
WinShowWindow(plswData->TaskArr[iItemNum].hwnd,TRUE);
else if (cmd==CMD_CLOSEQUIT)
WinPostMsg(plswData->TaskArr[iItemNum].hwnd, WM_QUIT, 0,0);
else if (cmd==CMD_KILL)
DosKillProcess(DKP_PROCESS,plswData->TaskArr[iItemNum].pid);
else if (cmd==CMD_DEATH)
Death(plswData->TaskArr[iItemNum].pid);
else
WinPostMsg(plswData->TaskArr[iItemNum].hwnd,WM_SYSCOMMAND,MPFROMSHORT(cmd1),MPFROM2SHORT(CMDSRC_OTHER,FALSE));
}
return bDoIt;
}
/* this procedure returns TRUE if the the popup menu for the usItem item in
the TaskArr needs the menu item usId. If yes, the title is returned also */
BOOL MenuNeedsItem(LSWDATA *plswData,USHORT usItem,USHORT usId,UCHAR *pszTitle,USHORT usLen,BOOL bGroup)
{ BOOL bNeedsItem=FALSE;
USHORT k;
if (bGroup && ((usId>=CMD_SWITCHFROMPM && usId<=CMD_CLOSE) || usId==CMD_ADDFILTER)) {
for (k=0;k<plswData->usItems && bNeedsItem==FALSE;k++) {
if (plswData->TaskArr[k].pid!=plswData->TaskArr[usItem].pid) continue;
if (usId==CMD_SHOW && (plswData->TaskArr[k].fl & SWP_HIDE))
bNeedsItem=TRUE;
else if (usId>=CMD_HIDE && usId<=CMD_CLOSE && usId!=CMD_MOVE) {
bNeedsItem = WndHasControl(plswData->hab,plswData->TaskArr[k].hwnd,LOUSHORT(MapCommand(usId)));
if (usId == CMD_HIDE) bNeedsItem &=(!(plswData->TaskArr[k].fl & SWP_HIDE));
}
}
} else {
if (usId == CMD_SWITCHFROMPM || usId == CMD_CLOSEQUIT)
bNeedsItem = TRUE;
else if (usId==CMD_KILL || usId==CMD_DEATH || usId==CMD_PRIORITY) {
bNeedsItem=(plswData->TaskArr[usItem].pid!=GetWPSPid());
if (usId==CMD_DEATH) {
HFILE hfd;
if ((hfd = OpenXF86())!=0) DosClose(hfd);
bNeedsItem &=(hfd!=0);
}
} else if (usId == CMD_ADDFILTER)
bNeedsItem = TRUE;
else if (usId == CMD_MOVE) {
bNeedsItem =
(!(plswData->TaskArr[usItem].fl & SWP_HIDE) &&
!IsMinToViewer(plswData->TaskArr[usItem].hwnd,plswData->TaskArr[usItem].fl) &&
WndHasControl(plswData->hab,plswData->TaskArr[usItem].hwnd,SC_MOVE));
} else if (usId == CMD_SHOW)
bNeedsItem = (plswData->TaskArr[usItem].fl & SWP_HIDE);
else
bNeedsItem = WndHasControl(plswData->hab,plswData->TaskArr[usItem].hwnd,LOUSHORT(MapCommand(usId)));
if (usId == CMD_HIDE) bNeedsItem &=(!(plswData->TaskArr[usItem].fl & SWP_HIDE));
}
if (bNeedsItem)
WinLoadString(plswData->hab,plswData->hmodRes,usId,usLen,pszTitle);
return bNeedsItem;
}
BOOL WndHasControl(HAB hab,HWND hwndToCheck,USHORT usControl)
{ HWND hwndSysMenu, hwndMinMax;
return
(WinIsWindow(hab,hwndToCheck) && WinIsWindowEnabled(hwndToCheck) &&
(
(
(hwndSysMenu=WinWindowFromID(hwndToCheck,FID_SYSMENU))!=NULLHANDLE &&
SHORT1FROMMR(WinSendMsg(hwndSysMenu,MM_ISITEMVALID,MPFROM2SHORT(usControl,TRUE),0))==TRUE
) ||
(
(hwndMinMax=WinWindowFromID(hwndToCheck,FID_MINMAX))!=NULLHANDLE &&
SHORT1FROMMR(WinSendMsg(hwndMinMax,MM_QUERYITEMCOUNT,0,0))>0 &&
(SHORT)WinSendMsg(hwndMinMax,MM_ITEMPOSITIONFROMID,MPFROM2SHORT(usControl,0),0)!=MIT_NONE
)
)
);
}
SHORT InsertMenuItem(HWND hwndMenu, HWND hwndSubMenu, SHORT iPosition, SHORT sItemId,
char *ItemTitle, SHORT afStyle, SHORT afAttr, ULONG hItem)
{ MENUITEM mi;
mi.iPosition = iPosition;
mi.afStyle = afStyle;
mi.afAttribute = afAttr;
mi.id = sItemId;
mi.hwndSubMenu = hwndSubMenu;
mi.hItem = hItem;
return SHORT1FROMMR(WinSendMsg(hwndMenu, MM_INSERTITEM, (MPARAM)&mi, (MPARAM)ItemTitle));
}
VOID InitTaskActionsMenu(HWND hwndMenu, LSWDATA *plswData,SHORT iMenuAtItem,BOOL bTaskBar,BOOL bGroup)
{ SHORT sItemId,sItemNum,sLastId,k,sAttr;
UCHAR ucBuf[64];
HWND hwndSubmenu;
sItemNum = SHORT1FROMMR(WinSendMsg(hwndMenu,MM_QUERYITEMCOUNT,0,0));
while (sItemNum > 0) {
sItemId = SHORT1FROMMR(WinSendMsg(hwndMenu,MM_ITEMIDFROMPOSITION,
MPFROMSHORT(sItemNum-1),0));
sItemNum = SHORT1FROMMR(WinSendMsg(hwndMenu,
sItemId==CMD_XCENTERSUBMENU?MM_REMOVEITEM:MM_DELETEITEM,
MPFROM2SHORT(sItemId,FALSE),0));
}
if (iMenuAtItem >= 0) { //neither an empty spot on the taskbar nor the Desktop button, show context menu
for (sItemId = CMD_SWITCHFROMPM,sLastId=0; sItemId <= CMD_MOVE; sItemId++) {
if (!bTaskBar && sItemId==CMD_MOVE)
continue;
if (MenuNeedsItem(plswData,iMenuAtItem,sItemId,ucBuf,sizeof(ucBuf),bGroup)) {
if ((sItemId == CMD_CLOSE || sItemId == CMD_KILL || sLastId==CMD_SWITCHFROMPM) &&
SHORT1FROMMR(WinSendMsg(hwndMenu,MM_QUERYITEMCOUNT,0,0))>0)
InsertMenuItem(hwndMenu, NULLHANDLE, MIT_END, 0, "", MIS_SEPARATOR, 0,0);
InsertMenuItem(hwndMenu, NULLHANDLE, MIT_END, sItemId, ucBuf, MIS_TEXT, 0,0);
sLastId=sItemId;
}
}
if (!IsDesktop(plswData->TaskArr[iMenuAtItem].hwnd)) {
WinLoadString(plswData->hab,plswData->hmodRes,CMD_CLOSE,sizeof(ucBuf),ucBuf);
if (SHORT1FROMMR(WinSendMsg(hwndMenu,MM_QUERYITEMCOUNT,0,0))>0)
InsertMenuItem(hwndMenu, NULLHANDLE, MIT_END, 0, "", MIS_SEPARATOR, 0,0);
hwndSubmenu = WinCreateMenu(hwndMenu, NULL);
if (hwndSubmenu != NULLHANDLE) {
WinSetWindowULong(hwndSubmenu,QWL_STYLE,
WinQueryWindowULong(hwndSubmenu,QWL_STYLE) | MS_CONDITIONALCASCADE);
sItemId=InsertMenuItem(hwndMenu, hwndSubmenu, MIT_END, CMD_CLOSE, ucBuf, MIS_TEXT|MIS_SUBMENU, 0,0);
if (sItemId != MIT_MEMERROR && sItemId != MIT_ERROR) {
sAttr = MIA_CHECKED;
if (MenuNeedsItem(plswData,iMenuAtItem,CMD_CLOSE,ucBuf,sizeof(ucBuf),bGroup)) {
InsertMenuItem(hwndSubmenu, NULLHANDLE, MIT_END, CMD_CLOSE, "SC_CLOSE", MIS_TEXT, MIA_CHECKED,0);
sAttr = 0;
}
InsertMenuItem(hwndSubmenu, NULLHANDLE, MIT_END, CMD_CLOSEQUIT, "WM_QUIT", MIS_TEXT, sAttr,0);
if (MenuNeedsItem(plswData,iMenuAtItem,CMD_KILL,ucBuf,sizeof(ucBuf),bGroup))
InsertMenuItem(hwndSubmenu, NULLHANDLE, MIT_END, CMD_KILL, ucBuf, MIS_TEXT, 0,0);
if (MenuNeedsItem(plswData,iMenuAtItem,CMD_DEATH,ucBuf,sizeof(ucBuf),bGroup))
InsertMenuItem(hwndSubmenu, NULLHANDLE, MIT_END, CMD_DEATH, ucBuf, MIS_TEXT, 0,0);
}
}
}
if (MenuNeedsItem(plswData,iMenuAtItem,CMD_PRIORITY,ucBuf,sizeof(ucBuf),bGroup)) {
InsertMenuItem(hwndMenu, NULLHANDLE, MIT_END, 0, "", MIS_SEPARATOR, 0,0);
InsertMenuItem(hwndMenu, NULLHANDLE, MIT_END, CMD_PRIORITY, ucBuf, MIS_TEXT, 0,0);
}
if (MenuNeedsItem(plswData,iMenuAtItem,CMD_ADDFILTER,ucBuf,sizeof(ucBuf),bGroup)) {
InsertMenuItem(hwndMenu, NULLHANDLE, MIT_END, 0, "", MIS_SEPARATOR, 0,0);
InsertMenuItem(hwndMenu, NULLHANDLE, MIT_END, CMD_ADDFILTER, ucBuf, MIS_TEXT, 0,0);
}
}
#ifndef XWORKPLACE
else { //iMenuAtItem==-1, either an empty spot on the taskbar or the Desktop button, show generic menu
WinLoadString(plswData->hab,plswData->hmodRes,STRID_RUN,sizeof(ucBuf),ucBuf);
InsertMenuItem(hwndMenu, NULLHANDLE, MIT_END, CMD_RUN, ucBuf, MIS_TEXT, 0,0);
InsertMenuItem(hwndMenu, NULLHANDLE, MIT_END, 0, "", MIS_SEPARATOR, 0,0);
WinLoadString(plswData->hab,plswData->hmodRes,STRID_SUSPEND,sizeof(ucBuf),ucBuf);
InsertMenuItem(hwndMenu, NULLHANDLE, MIT_END, CMD_SUSPEND, ucBuf, MIS_TEXT, 0,0);
InsertMenuItem(hwndMenu, NULLHANDLE, MIT_END, 0, "", MIS_SEPARATOR, 0,0);
WinLoadString(plswData->hab,plswData->hmodRes,STRID_SHOWSETTINGS,sizeof(ucBuf),ucBuf);
InsertMenuItem(hwndMenu, NULLHANDLE, MIT_END, CMD_SHOWSETTINGS, ucBuf, MIS_TEXT, 0,0);
WinLoadString(plswData->hab,plswData->hmodRes,STRID_QUIT,sizeof(ucBuf),ucBuf);
InsertMenuItem(hwndMenu, NULLHANDLE, MIT_END, CMD_QUIT, ucBuf, MIS_TEXT, 0,0);
}
#else
WinSetPresParam(plswData->pWidget->hwndContextMenu,PP_FONTNAMESIZE,7,"8.Helv");
if (bTaskBar && iMenuAtItem >= 0) {
// now set the old context menu as submenu;
InsertMenuItem(hwndMenu, NULLHANDLE, MIT_END, 0, "", MIS_SEPARATOR, 0,0);
WinLoadString(plswData->hab,plswData->hmodRes,STRID_XCENTERSUBMENU,sizeof(ucBuf),ucBuf);
InsertMenuItem(hwndMenu, plswData->pWidget->hwndContextMenu, MIT_END,
CMD_XCENTERSUBMENU, ucBuf, MIS_TEXT | MIS_SUBMENU, 0,0);
}
#endif
}
VOID ShowMenu(LSWDATA *plswData,SHORT iMenuAtItem,BOOL bTaskBar,BOOL bGroup)
{ POINTL ptl;
InitTaskActionsMenu(plswData->hwndMenu,plswData,iMenuAtItem,bTaskBar,bGroup);
WinQueryPointerPos(HWND_DESKTOP,&ptl);
#ifdef XWORKPLACE
WinPopupMenu(HWND_DESKTOP, bTaskBar?plswData->hwndTaskBarClient:plswData->hwndPopClient,
(iMenuAtItem<0&&bTaskBar)?plswData->pWidget->hwndContextMenu:plswData->hwndMenu,
ptl.x, ptl.y,0, PU_HCONSTRAIN | PU_VCONSTRAIN | PU_MOUSEBUTTON1 | PU_MOUSEBUTTON2 | PU_KEYBOARD);
#else
WinPopupMenu(HWND_DESKTOP, bTaskBar?plswData->hwndTaskBarClient:plswData->hwndPopClient,plswData->hwndMenu,
ptl.x, ptl.y,0, PU_HCONSTRAIN | PU_VCONSTRAIN | PU_MOUSEBUTTON1 | PU_MOUSEBUTTON2 | PU_KEYBOARD);
#endif
}
VOID ShowBubble(LSWDATA *plswData,SHORT iMouseIsAtItem,USHORT usX,USHORT usY,SHORT iFunc,UCHAR *ucTitle2)
{ static SHORT iMouseWasAtItem=-1,iCounter1=0,iBubbleAtItem=-1,iSource;
USHORT usSizeX,usSizeY;
POINTL aptl[TXTBOX_COUNT];
UCHAR ucTitle[NAMELEN];
HPS hps;
LONG cxScreen;
SWP swp;
if (iFunc>0) {
if (iFunc<=10) { //iFunc==11 -- update bubble text
if (iMouseIsAtItem == iMouseWasAtItem || iMouseWasAtItem < 0)
iCounter1+=BUBBLETIMERINTERVAL;
else
iCounter1=0;
iMouseWasAtItem = iMouseIsAtItem;
iSource=iFunc;
}
if ((iFunc<=10 && ((iCounter1 >= 800 /*ms*/&& iBubbleAtItem < 0) ||
(iBubbleAtItem >= 0 && iBubbleAtItem != iMouseIsAtItem))) ||
(iFunc==11 && iMouseIsAtItem==iBubbleAtItem)) {
if (ucTitle2==NULL)
GetItemTitle(plswData->TaskArr[iMouseIsAtItem].hsw,ucTitle,sizeof(ucTitle),FALSE);
else
strncpy(ucTitle,ucTitle2,sizeof(ucTitle)-1);
hps = WinGetPS(plswData->hwndBubble);
GpiQueryTextBox(hps,strlen(ucTitle),ucTitle,TXTBOX_COUNT,aptl);
WinReleasePS(hps);
if (iFunc==11) {
WinQueryWindowPos(plswData->hwndBubble,&swp);
usX = swp.x; usY = swp.y;
}
usSizeX = aptl[TXTBOX_TOPRIGHT].x-aptl[TXTBOX_TOPLEFT].x+8;
usSizeY = aptl[TXTBOX_TOPLEFT].y-aptl[TXTBOX_BOTTOMLEFT].y+4;
cxScreen=WinQuerySysValue(HWND_DESKTOP,SV_CXSCREEN);
if (usX+usSizeX>cxScreen) usX-=usX+usSizeX-cxScreen;
WinSetWindowPos(plswData->hwndBubble,HWND_TOP,
usX,usY,usSizeX,usSizeY,
SWP_MOVE | SWP_SIZE | SWP_SHOW | SWP_ZORDER);
WinSetWindowPos(WinWindowFromID(plswData->hwndBubble,ID_BUBBLEFRAME),0,0,0,
usSizeX,usSizeY, SWP_MOVE | SWP_SIZE | SWP_SHOW);
WinSetWindowText(plswData->hwndBubble,ucTitle);
iBubbleAtItem = iMouseIsAtItem;
} else if (iBubbleAtItem>=0 &&
(WinQueryWindowPos(plswData->hwndBubble,&swp),
aptl[0].x=swp.x,aptl[0].y=aptl[1].y=swp.y+swp.cy-1,aptl[1].x=swp.x+swp.cx-1,
WinWindowFromPoint(HWND_DESKTOP,&aptl[0],FALSE)!=plswData->hwndBubble ||
WinWindowFromPoint(HWND_DESKTOP,&aptl[1],FALSE)!=plswData->hwndBubble
)) {
WinSetWindowPos(plswData->hwndBubble,HWND_TOP,0,0,0,0,SWP_ZORDER);
WinInvalidateRect(plswData->hwndBubble,NULL,TRUE);
}
} else if (abs(iFunc)==iSource) {
UCHAR ucBuf[32];
if (WinIsWindowVisible(plswData->hwndBubble))
WinSetWindowPos(plswData->hwndBubble,HWND_BOTTOM,0,0,0,0,SWP_HIDE | SWP_ZORDER);
iBubbleAtItem = -1;
iMouseWasAtItem = -1;
iCounter1 = 0;
WinQueryPresParam(plswData->hwndBubble,PP_BACKGROUNDCOLOR,0,NULL,sizeof(ucBuf),ucBuf,QPF_NOINHERIT);
plswData->Settings.lBubbleRGBCol = ucBuf[0]+ucBuf[1]*256+ucBuf[2]*65536;
WinQueryPresParam(plswData->hwndBubble,PP_FOREGROUNDCOLOR,0,NULL,sizeof(ucBuf),ucBuf,QPF_NOINHERIT);
plswData->Settings.lBubbleTextRGBCol = ucBuf[0]+ucBuf[1]*256+ucBuf[2]*65536;
}
}
BOOL IsWindowClass(HWND hwnd,UCHAR *pszClassName)
{ UCHAR ucBuf[128];
WinQueryClassName(hwnd,sizeof(ucBuf),ucBuf);
return (strcmp(ucBuf,pszClassName)==0);
}
PVOID GetSwitchList(HAB hab,BOOL bInit,ULONG *ItemCount)
{ static PSWBLOCK pSwb=NULL;
static ULONG ulItemCount,ulRecCount=0;
if (bInit) {
ulRecCount++;
if (pSwb!=NULL) {
*ItemCount=ulItemCount;
return pSwb;
}
if ((ulItemCount = WinQuerySwitchList(hab, NULL, 0))==0 ||
(pSwb=malloc(sizeof(HSWITCH)+sizeof(SWENTRY)*ulItemCount))==NULL) {
return NULL;
}
/* get all switch entries in one call; calling WinQuerySwitchHandle/SwitchEntry
for each window turns out to be noticeably slower */
ulItemCount = WinQuerySwitchList(hab,pSwb,sizeof(HSWITCH)+sizeof(SWENTRY)*ulItemCount);
*ItemCount=ulItemCount;
return pSwb;
} else {
ulRecCount--;
if (ulRecCount==0) {
if (pSwb!=NULL) free(pSwb);
pSwb=NULL;
}
return NULL;
}
}
BOOL IsMinToViewer(HWND hwnd,ULONG flopt)
{
return
((flopt & SWP_MINIMIZE) && WinQueryWindowUShort(hwnd,QWS_YMINIMIZE)==33536);
}
//returns TRUE if any window part is currently within desktop (with some probability<100%)
BOOL IsInDesktop(HWND hwnd)
{ SWP swp;
USHORT usCXScreen=WinQuerySysValue(HWND_DESKTOP,SV_CXSCREEN),
usCYScreen=WinQuerySysValue(HWND_DESKTOP,SV_CYSCREEN);
WinQueryWindowPos(hwnd,&swp);
return (
(swp.x<usCXScreen && swp.y<usCYScreen && swp.x>=0 && swp.y>=0) ||
(swp.x+swp.cx<usCXScreen && swp.y<usCYScreen && swp.x+swp.cx>=0 && swp.y>=0) ||
(swp.x<usCXScreen && swp.y+swp.cy<usCYScreen && swp.x>=0 && swp.y+swp.cy>=0) ||
(swp.x+swp.cx<usCXScreen && swp.y+swp.cy<usCYScreen && swp.x+swp.cx>=0 && swp.y+swp.cy>=0) ||
(swp.x+swp.cx/2<usCXScreen && swp.y+swp.cy/2<usCYScreen && swp.x+swp.cx/2>=0 && swp.y+swp.cy/2>=0) ||
(swp.x+swp.cx/3<usCXScreen && swp.y+swp.cy/3<usCYScreen && swp.x+swp.cx/3>=0 && swp.y+swp.cy/3>=0) ||
(swp.x+swp.cx*2/3<usCXScreen && swp.y+swp.cy/3<usCYScreen && swp.x+swp.cx*2/3>=0 && swp.y+swp.cy/3>=0) ||
(swp.x+swp.cx/3<usCXScreen && swp.y+swp.cy*2/3<usCYScreen && swp.x+swp.cx/3>=0 && swp.y+swp.cy*2/3>=0) ||
(swp.x+swp.cx*2/3<usCXScreen && swp.y+swp.cy*2/3<usCYScreen && swp.x+swp.cx*2/3>=0 && swp.y+swp.cy*2/3>=0)
);
}
//get the virtual desktop number relative to the one on which the program was started
LONG GetCurrDesktop(LSWDATA *plswData)
{ USHORT usCXScreen=WinQuerySysValue(HWND_DESKTOP,SV_CXSCREEN),
usCYScreen=WinQuerySysValue(HWND_DESKTOP,SV_CYSCREEN);
SWP swp;
SHORT x,y;
if (plswData->bNowActive) return -1;
WinQueryWindowPos(plswData->hwndPopup,&swp);
x=(POPUPWINHIDEPOSX-swp.x)/usCXScreen;
y=(POPUPWINHIDEPOSY-swp.y)/usCYScreen;
return ((x<<8)+y);
}
VOID MinimizeHideAll(LSWDATA *plswData, BOOL bReset, HWND hwndReset)
{ SHORT i;
HSWITCH hswDesktop;
static USHORT usNumWin;
static BOOL bRestoreAll=FALSE;
static LONG lDskNum;
static HWND *hwndList=NULL;
if (bReset) {
if (hwndList!=NULL)
for (i=0;i<usNumWin;i++)
if (hwndReset==hwndList[i]) {
free(hwndList); hwndList=NULL;
bRestoreAll=FALSE;
break;
}
return;
}
if (!bRestoreAll) {
if (hwndList!=NULL) free(hwndList);
hswDesktop=plswData->TaskArr[plswData->usCurrItem].hsw;
InitTaskArr(plswData,FALSE,FALSE,FALSE);
if ((hwndList=malloc(plswData->usItems*sizeof(HWND)))!=NULL)
for (i = plswData->usItems-2,usNumWin=0; i >= 0; i--) {
//make sure the window is in the current virtual desktop and not minimized or hidden
if (!(plswData->TaskArr[i].fl&(SWP_MINIMIZE|SWP_HIDE))&&IsInDesktop(plswData->TaskArr[i].hwnd)) {
if (ChangeWindowPos(plswData,i,CMD_HIDE) || ChangeWindowPos(plswData,i,CMD_MINIMIZE))
hwndList[usNumWin++]=plswData->TaskArr[i].hwnd;
}
}
lDskNum=GetCurrDesktop(plswData);
WinSwitchToProgram(hswDesktop);
} else {
if (hwndList==NULL || lDskNum!=GetCurrDesktop(plswData)) return;
for (i=0;i<usNumWin;i++) {
WinSetWindowPos(hwndList[i],HWND_TOP,0,0,0,0,SWP_SHOW|SWP_ZORDER);
WinSwitchToProgram(WinQuerySwitchHandle(hwndList[i],0));
}
free(hwndList); hwndList=NULL;
}
bRestoreAll ^= TRUE;
}
VOID GetItemTitle(HSWITCH hsw,UCHAR *ucTitle,USHORT usLen,BOOL bSessNum)
{ SWCNTRL swctl;
USHORT k;
if (WinQuerySwitchEntry(hsw, &swctl)!=0) {
strcpy(ucTitle,"");
return;
}
if (bSessNum)
sprintf(ucTitle,"%.*s (0x%X)",usLen-6,swctl.szSwtitle,swctl.idProcess);
else
strncpy(ucTitle,swctl.szSwtitle,usLen-1);
for (k=0;k<strlen(ucTitle);k++)
if (ucTitle[k]=='\r' || ucTitle[k]=='\n') ucTitle[k]=' ';
}
HPOINTER GetItemIcon(HWND hwnd)
{ HPOINTER hIcon;
UCHAR *pszPath;
HWND hwnd1;
if ((hIcon=(HPOINTER)WinSendMsg(hwnd,WM_QUERYICON,0,0))!=NULLHANDLE)
return hIcon;
if (IsWindowClass((hwnd1=WinWindowFromID(hwnd,FID_CLIENT)),"SeamlessClass")) {
pszPath = (UCHAR *)WinQueryWindowULong(hwnd1,0L);
hIcon=WinLoadFileIcon(pszPath,FALSE);
} /*else {
ULONG ulItemCount;
LONG k;
PSWBLOCK pSwb;
PID pid;
TID tid;
if ((pSwb=GetSwitchList(0,TRUE,&ulItemCount))!=NULL) {
for (k=ulItemCount-1;k>=0 && hIcon==NULLHANDLE;k--) {
WinQueryWindowProcess(hwnd,&pid,&tid);
if (pSwb->aswentry[k].swctl.hwnd!=hwnd && pSwb->aswentry[k].swctl.idProcess==pid)
hIcon=(HPOINTER)WinSendMsg(pSwb->aswentry[k].swctl.hwnd,WM_QUERYICON,0,0);
}
GetSwitchList(0,FALSE,NULL);
}
}*/
if (hIcon == NULLHANDLE)
hIcon = WinQuerySysPointer(HWND_DESKTOP,SPTR_PROGRAM,FALSE);
return hIcon;
}
PSZ GetObjectName(USHORT usObjHandle)
{ UCHAR ucKey[16],*pucObjData,*substr=NULL,*pszName=NULL;
ULONG k,ulDataSize;
if ((pucObjData=malloc(ulDataSize=1024))==NULL) return NULL;
sprintf(ucKey,"%X",usObjHandle);
if (PrfQueryProfileData(HINI_USERPROFILE,"PM_Abstract:Objects",ucKey,pucObjData,&ulDataSize))
for (k=0,substr=NULL;substr==NULL && k<ulDataSize-strlen("WPAbstract");k++)
if ((substr=strstr(&pucObjData[k],"WPAbstract"))!=NULL) substr+=17;
if (substr!=NULL) pszName=strdup(substr);
free(pucObjData);
return pszName;
}
BOOL IsDesktop(HWND hwnd)
{
return (hwnd==WinQueryWindow(HWND_DESKTOP,QW_BOTTOM) &&
(IsWindowClass(hwnd,"wpFolder window")));
}
//Written by Staffan Ulfberg
char Match(char *string, char *pattern)
{
for (; '*'^*pattern; ++pattern, ++string) {
if (!*string)
return (!*pattern);
if (toupper(*string)^toupper(*pattern) && '?'^*pattern)
return FALSE;
}
/* two-line patch to prevent *too* much recursiveness: */
while('*' == pattern[1])
pattern++;
do {
if ( Match(string, pattern + 1) )
return TRUE;
} while (*string++);
return FALSE;
}
BOOL IsInSkipList(LSWSETTINGS *pSettings,UCHAR *ucTitle,BOOL bTskBar)
{ BOOL bFound;
USHORT j;
SKIPLIST *pSkipList;
pSkipList = bTskBar ? &pSettings->SkipListTskBar : &pSettings->SkipListPopup;
for (j = 0, bFound = FALSE;
j < MAXITEMS && (*pSkipList)[j]!=NULL &&
!(bFound=Match(ucTitle, (*pSkipList)[j]));
j++);
return bFound;
}
VOID InitTaskArr(LSWDATA *plswData,BOOL bFullScreen,BOOL bTaskBar,BOOL bUseFilters)
{ ULONG sidCurr,ulItemCount,ulItem;
PSWBLOCK pSwb;
HENUM henum;
HWND hwndNext,hwndActive;
SWP swp;
UCHAR ucIndex;
SWITEM ditem;
BOOL bFound,bIsCurrent;
sidCurr = 0;
hwndActive = NULLHANDLE;
plswData->usItems = plswData->usCurrItem = plswData->iShift = 0;
memset(plswData->TaskArr,0,sizeof(plswData->TaskArr));
if ((pSwb=GetSwitchList(plswData->hab,TRUE,&ulItemCount))==NULL) return;
/* get SID of the current fullscreen process */
if (bFullScreen) {
if (DosQuerySysInfo(24,24,&sidCurr,sizeof(sidCurr))!=0) sidCurr=0;
} else {
hwndActive = WinQueryActiveWindow(WinQueryDesktopWindow(plswData->hab,NULLHANDLE));
}
henum = WinBeginEnumWindows(WinQueryDesktopWindow(plswData->hab,NULLHANDLE));
while ((hwndNext = WinGetNextWindow(henum))!=NULLHANDLE && plswData->usItems < MAXITEMS-1) {
for (ulItem = 0, bFound = FALSE; ulItem < ulItemCount; ulItem++)
if ((bFound=(hwndNext == pSwb->aswentry[ulItem].swctl.hwnd))==TRUE) break;
if (!bFound || !WinIsWindow(plswData->hab,hwndNext) ||
pSwb->aswentry[ulItem].swctl.uchVisibility != SWL_VISIBLE)
continue;
WinQueryWindowPos(hwndNext,&swp);
bFound = (!bUseFilters || (sidCurr == pSwb->aswentry[ulItem].swctl.idSession ||
(((bTaskBar?plswData->Settings.bShowHiddenTskBar:plswData->Settings.bShowHidden) || !(swp.fl & SWP_HIDE)) &&
((bTaskBar?plswData->Settings.bShowViewerTskBar:plswData->Settings.bShowViewer) || !IsMinToViewer(hwndNext,swp.fl)))) &&
!IsInSkipList(&plswData->Settings, pSwb->aswentry[ulItem].swctl.szSwtitle,bTaskBar));
/* save the current entry in the last element of the array even if it's
not supposed to be switched to. It will be used if switching is cancelled */
bIsCurrent = ((!bFullScreen &&
(hwndNext == hwndActive ||
hwndNext == WinQueryWindow(hwndActive,QW_OWNER))) ||
(bFullScreen && pSwb->aswentry[ulItem].swctl.idSession == sidCurr));
if (bFound) {
ucIndex = plswData->usItems;
plswData->usItems++;
} else if (bIsCurrent)
ucIndex = MAXITEMS-1;
else
continue;
plswData->TaskArr[ucIndex].ulType = pSwb->aswentry[ulItem].swctl.bProgType;
plswData->TaskArr[ucIndex].fl = swp.fl;
plswData->TaskArr[ucIndex].hsw = pSwb->aswentry[ulItem].hswitch;
plswData->TaskArr[ucIndex].hwnd = hwndNext;
plswData->TaskArr[ucIndex].hIcon = GetItemIcon(hwndNext);
plswData->TaskArr[ucIndex].pid = pSwb->aswentry[ulItem].swctl.idProcess;
if (bFound && bIsCurrent) {
memcpy(&plswData->TaskArr[MAXITEMS-1],&plswData->TaskArr[ucIndex],sizeof(SWITEM));
/* make sure current session or window is in the 0th element of the TaskArr */
if (ucIndex != 0) {
memcpy(&ditem,&plswData->TaskArr[ucIndex],sizeof(ditem));
memmove(&plswData->TaskArr[1],&plswData->TaskArr[0],sizeof(ditem)*ucIndex);
memcpy(&plswData->TaskArr[0],&ditem,sizeof(ditem));
}
}
}
WinEndEnumWindows(henum);
GetSwitchList(0,FALSE,NULL);
if (plswData->TaskArr[MAXITEMS-1].hsw == 0)
plswData->TaskArr[MAXITEMS-1].hwnd = hwndActive;
}
BOOL AddFilter(LSWSETTINGS *pSettings,UCHAR *ucName,BOOL bTskBar)
{ SHORT iNum;
SKIPLIST *pSkipList;
pSkipList = bTskBar?&pSettings->SkipListTskBar:&pSettings->SkipListPopup;
if (strlen(ucName)==0 || IsInSkipList(pSettings,ucName,bTskBar)) return FALSE;
for (iNum=0; (*pSkipList)[iNum]!=NULL && iNum<MAXITEMS; iNum++);
if (iNum==MAXITEMS) return FALSE;
(*pSkipList)[iNum++]=strdup(ucName);
return TRUE;
}
BOOL RemoveFilter(LSWSETTINGS *pSettings,UCHAR *ucName,BOOL bTskBar)
{ SHORT iNum,k;
SKIPLIST *pSkipList;
pSkipList = bTskBar?&pSettings->SkipListTskBar:&pSettings->SkipListPopup;
for (iNum=0; (*pSkipList)[iNum]!=NULL && iNum<MAXITEMS; iNum++);
for (k = 0; k < iNum; k++)
if (strcmp((*pSkipList)[k],ucName)==0) {
free((*pSkipList)[k]);
memmove(&(*pSkipList)[k], &(*pSkipList)[k+1],
sizeof(pSettings->SkipListPopup[0])*(iNum-k-1));
(*pSkipList)[--iNum]=NULL;
return TRUE;
}
return FALSE;
}
USHORT RunCommand(LSWDATA *plswData,UCHAR *ucCommand,UCHAR *ucErrMsg,USHORT usErrMsgLen)
{ STARTDATA SData;
UCHAR k,ucCmdLine[_MAX_PATH]="",ucPath[_MAX_PATH],ucPgmInp[_MAX_PATH],
drive[_MAX_DRIVE],dir[_MAX_DIR],name[_MAX_FNAME],ext[_MAX_EXT],*args;
static UCHAR ucExtStr[4][4]={"bat\0","cmd\0","com\0","exe\0"};
APIRET rc;
PID pid;
ULONG ulSessID,ulAppType;
if ((args=strchr(ucCommand,' '))!=NULL) {
strcpy(ucCmdLine,args);
*args='\0';
}
strcpy(ucPath,ucCommand);
_splitpath(ucPath,drive,dir,name,ext);
for (k=0,rc=0;k<(strlen(ext)==0?4:1);k++) { //add an extension if needed and find if file exists
if (strlen(ext)==0) _makepath(ucPath,drive,dir,name,ucExtStr[k]);
ulAppType=0;
rc=DosQueryAppType(ucPath,&ulAppType);
if (rc==0 || rc==191 || rc==193)
break;
else
strncpy(ucPath,name,sizeof(ucPath));
}
memset(&SData,0,sizeof(SData));
SData.Length = sizeof(SData);
SData.Related = SSF_RELATED_INDEPENDENT;
SData.FgBg = SSF_FGBG_FORE;
SData.TraceOpt = SSF_TRACEOPT_NONE;
SData.InheritOpt = SSF_INHERTOPT_SHELL;
SData.PgmControl = SSF_CONTROL_VISIBLE;
SData.SessionType = SSF_TYPE_DEFAULT;
if (ulAppType==0x20 || strcmpi(ucPath + strlen(ucPath) - 4, ".BAT") == 0)
SData.SessionType = SSF_TYPE_WINDOWEDVDM;
if (ulAppType&(FAPPTYP_WINDOWSREAL|FAPPTYP_WINDOWSPROT|FAPPTYP_WINDOWSPROT31)) {
SData.PgmName="WINOS2.COM";
sprintf(ucPgmInp, "/3 %s %s", ucPath, ucCmdLine);
SData.SessionType = PROG_31_ENHSEAMLESSCOMMON;
} else if (rc!=0 || strcmpi(ucPath + strlen(ucPath) - 4, ".CMD") == 0) {
sprintf(ucPgmInp, "/C%s %s", ucPath, ucCmdLine);
} else {
SData.PgmName = ucPath;
strcpy(ucPgmInp, ucCmdLine);
}
SData.PgmInputs = ucPgmInp;
if ((rc=DosStartSession(&SData, &ulSessID, &pid))!=0) {
WinLoadString(plswData->hab,plswData->hmodRes,MSG_CANTEXECUTE,usErrMsgLen,ucErrMsg);
strncat(ucErrMsg,SData.PgmName,usErrMsgLen-strlen(ucErrMsg)-1);
return rc;
}
return 0;
}
VOID SetControlsFont(HWND hwnd,BOOL bDoTitleBar)
{ ULONG aulSysInfo[2]={0};
UCHAR ucFont[FACESIZE];
HWND hwndCtl;
HENUM henum;
DosQuerySysInfo(QSV_VERSION_MAJOR, QSV_VERSION_MINOR,aulSysInfo,sizeof(aulSysInfo));
strcpy(ucFont,(aulSysInfo[0]==20 && aulSysInfo[1]>=40)?DEFTITLEFONT4:DEFTITLEFONT3);
henum = WinBeginEnumWindows(hwnd);
while ((hwndCtl=WinGetNextWindow(henum))!=NULLHANDLE) {
if (!bDoTitleBar && IsWindowClass(hwndCtl,"#9")) continue;
WinSetPresParam(hwndCtl,PP_FONTNAMESIZE,strlen(ucFont)+1,ucFont);
}
WinEndEnumWindows(henum);
}
VOID GetStartupDir(UCHAR *ucDir,USHORT usLen)
{ PPIB ppib;
PTIB ptib;
SHORT k;
#ifndef XWORKPLACE
DosGetInfoBlocks(&ptib,&ppib);
DosQueryModuleName(ppib->pib_hmte, usLen, ucDir);
#else
DosQueryModuleName(hmodWidgetDll, usLen, ucDir);
#endif
for (k = strlen(ucDir)-1; ucDir[k] != '\\' && k >= 0; k--);
ucDir[k+1] = '\0';
}
BOOL queryAppInstance(VOID)
{ HEV hev;
if (hev=0, DosOpenEventSem(SEMRUNNINGNAME,&hev))
return FALSE;
else {
DosCloseEventSem(hev);
return TRUE;
}
}
BOOL UpdateWinFlags(ULONG *OldFlags,ULONG NewFlags)
{ BOOL bNeedUpdate;
NewFlags &= (SWP_MINIMIZE|SWP_MAXIMIZE|SWP_RESTORE|SWP_SHOW|SWP_HIDE|
SWP_ACTIVATE|SWP_DEACTIVATE);
bNeedUpdate = (((NewFlags & SWP_MINIMIZE) && !(*OldFlags & SWP_MINIMIZE)) ||
((NewFlags & SWP_ACTIVATE) && !(*OldFlags & SWP_ACTIVATE)) ||
((NewFlags & SWP_DEACTIVATE) && !(*OldFlags & SWP_DEACTIVATE)) ||
((NewFlags & SWP_SHOW) && !(*OldFlags & SWP_SHOW)) ||
((NewFlags & SWP_HIDE) && !(*OldFlags & SWP_HIDE)) ||
((NewFlags & SWP_RESTORE) && (*OldFlags & SWP_MINIMIZE)) ||
((NewFlags & SWP_MAXIMIZE) && (*OldFlags & SWP_MINIMIZE))
);
*OldFlags |= NewFlags;
if (NewFlags & SWP_MINIMIZE) *OldFlags &= (~(SWP_RESTORE|SWP_MAXIMIZE));
if (NewFlags & SWP_RESTORE) *OldFlags &= (~(SWP_MINIMIZE|SWP_MAXIMIZE));
if (NewFlags & SWP_MAXIMIZE) *OldFlags &= (~(SWP_MINIMIZE|SWP_RESTORE));
if (NewFlags & SWP_HIDE) *OldFlags &= (~SWP_SHOW);
if (NewFlags & SWP_SHOW) *OldFlags &= (~SWP_HIDE);
if (NewFlags & SWP_ACTIVATE) *OldFlags &= (~SWP_DEACTIVATE);
if (NewFlags & SWP_DEACTIVATE) *OldFlags &= (~SWP_ACTIVATE);
return bNeedUpdate;
}
VOID MakeFitStr(HPS hps,UCHAR *ucStr,USHORT usStrLen, USHORT usStrWid)
{ USHORT k,usLen;
POINTL aptl[TXTBOX_COUNT], ptlStart, *ptlStr;
usLen = strlen(ucStr);
ptlStr = malloc(sizeof(POINTL)*(usLen+1));
ptlStart.x = ptlStart.y = 0;
GpiQueryCharStringPosAt(hps, &ptlStart, 0, usLen, ucStr, NULL, ptlStr);
if (ptlStr[usLen].x <= usStrWid) {
free(ptlStr);
return;
}
GpiQueryTextBox(hps,2,"..",TXTBOX_COUNT,aptl);
k = usLen;
do {
k--;
} while (ptlStr[k].x+(aptl[TXTBOX_BOTTOMRIGHT].x-aptl[TXTBOX_BOTTOMLEFT].x) >
usStrWid && k > 0);
ucStr[k]='\0';
if (k > 0) strncat(ucStr,"..",usStrLen-k-2);
free(ptlStr);
}
USHORT FindResDll(UCHAR *ucDllName, USHORT usNameLen, UCHAR *ucLang, UCHAR *ucLangStr, USHORT usLangStrLen)
{ static UCHAR ucDir[_MAX_PATH],ucName[_MAX_PATH],ucErr[32];
static HDIR hdir = HDIR_CREATE;
HMODULE hmodRes;
FILEFINDBUF3 FindBuffer = {0};
ULONG ulResultBufLen, ulFindCount;
APIRET rc;
RESVERPROC *ResVerProc;
ULONG ulVer;
ulResultBufLen = sizeof(FILEFINDBUF3);
ulFindCount = 1;
*ucLang = 0;
if (hdir == HDIR_CREATE) {
GetStartupDir(ucDir,sizeof(ucDir));
sprintf(ucName,"%s*.dll",ucDir);
rc = DosFindFirst(ucName, &hdir, FILE_NORMAL, &FindBuffer, ulResultBufLen, &ulFindCount, FIL_STANDARD);
} else
rc = DosFindNext(hdir, &FindBuffer, ulResultBufLen, &ulFindCount);
if (rc == 0) {
sprintf(ucName,"%s%s",ucDir,FindBuffer.achName);
if (DosLoadModule(ucErr, sizeof(ucErr), ucName, &hmodRes)==0) {
if (DosQueryProcAddr(hmodRes, 0, "QueryResourceVersion", &ResVerProc)==0 &&
(ulVer = ResVerProc(ucLangStr,usLangStrLen),
(LOUCHAR(LOUSHORT(ulVer)) >= LASTINIVERMAJOROK &&
HIUCHAR(LOUSHORT(ulVer)) >= LASTINIVERMINOROK &&
LOUCHAR(HIUSHORT(ulVer)) >= LASTINIREVISIONOK))) {
*ucLang = HIUCHAR(HIUSHORT(ulVer));
strncpy(ucDllName,ucName,usNameLen);
}
DosFreeModule(hmodRes);
}
} else {
DosFindClose(hdir);
hdir = HDIR_CREATE;
return 0;
}
return 1;
}
HMODULE LoadResource(UCHAR ucLang, LSWDATA *plswData, BOOL bEngOk)
{ static UCHAR ucDllName[_MAX_PATH], ucLangStr[32], ucResLang, ucErr[32], ucFoundDllName[_MAX_PATH];
HMODULE hmodRes;
USHORT usFound = 0;
while (FindResDll(ucDllName, sizeof(ucDllName), &ucResLang, ucLangStr, sizeof(ucLangStr)))
if (ucResLang!=0) {
if (ucResLang==ucLang)
usFound = 1;
else if (bEngOk && ucResLang==ENGLISH && usFound==0)
usFound = 2;
else
continue;
strcpy(ucFoundDllName,ucDllName);
}
if (usFound && DosLoadModule(ucErr, sizeof(ucErr), ucFoundDllName, &hmodRes)==0) {
if ((plswData->haccAlt = WinLoadAccelTable(plswData->hab,hmodRes,ID_ALTACCELTABLE))==0 ||
(plswData->haccCtrl = WinLoadAccelTable(plswData->hab,hmodRes,ID_CTRLACCELTABLE))==0 ||
(plswData->haccNoAlt = WinLoadAccelTable(plswData->hab,hmodRes,ID_NOALTACCELTABLE))==0) {
DosFreeModule(hmodRes);
return 0;
} else {
plswData->Settings.ucLanguage = (usFound==1?ucLang:ENGLISH);
return hmodRes;
}
} else
return 0;
}
typedef struct _MSGSTRUCT {
HWND hwnd;
ULONG ulMsgid;
MPARAM mpParam1, mpParam2;
MRESULT mrRes;
HEV hev;
} MSGSTRUCT;
typedef MSGSTRUCT *pMSGSTRUCT;
VOID SendMsgThread(VOID *pParm)
{ LSWDATA *plswData=NULL;
HMQ hmq;
DosGetNamedSharedMem((PVOID*)&plswData,SHAREMEM_NAME,PAG_READ | PAG_WRITE);
hmq = WinCreateMsgQueue(plswData->hab, 0);
DosFreeMem(plswData);
((pMSGSTRUCT)pParm)->mrRes=
WinSendMsg(((pMSGSTRUCT)pParm)->hwnd,((pMSGSTRUCT)pParm)->ulMsgid,
((pMSGSTRUCT)pParm)->mpParam1,((pMSGSTRUCT)pParm)->mpParam2);
DosPostEventSem(((pMSGSTRUCT)pParm)->hev);
}
BOOL WinSendMsgAsync(HWND hwnd, ULONG ulMsgid, MPARAM mpParam1, MPARAM mpParam2, MRESULT *mrRes)
{ int tid;
MSGSTRUCT MsgStruct;
BOOL bRet;
MsgStruct.hwnd=hwnd;
MsgStruct.ulMsgid=ulMsgid;
MsgStruct.mpParam1=mpParam1;
MsgStruct.mpParam2=mpParam2;
DosCreateEventSem("\\SEM32\\SNDMSGSEM",&MsgStruct.hev,0,0);
tid=_beginthread(SendMsgThread,NULL,0x4000,&MsgStruct);
if (DosWaitEventSem(MsgStruct.hev,200)==640) { //timeout
DosBeep(1000,10);
DosKillThread(tid);
*mrRes=0;
bRet=FALSE;
} else {
*mrRes=MsgStruct.mrRes;
bRet=TRUE;
}
DosCloseEventSem(MsgStruct.hev);
return bRet;
}
/* this function is adapted from Roman Stangle's APM/2 package */
USHORT ProcessAPMOffRequest(USHORT usPowerState,USHORT usDevice)
{ APIRET rc=NO_ERROR;
ULONG ulPacketSize, ulDataSize, ulVersion[2],ulAction=0;
struct POWERRETURNCODE powerRC;
struct SENDPOWEREVENT sendpowereventAPM;
HFILE hfileAPM;
/* For /Shutdown "Request", we need Warp 4 otherwise at least a CHKDSK reliably occurs (if the request
does work at all) */
DosQuerySysInfo(QSV_VERSION_MAJOR, QSV_VERSION_MINOR, ulVersion, sizeof(ulVersion));
if(usPowerState==POWERSTATE_OFF) {
if((ulVersion[0]<0x14) || (ulVersion[1]<0x28))
return 1;
}
if (DosOpen("\\DEV\\APM$", &hfileAPM, &ulAction, 0, FILE_NORMAL, OPEN_ACTION_OPEN_IF_EXISTS,
OPEN_FLAGS_FAIL_ON_ERROR | OPEN_SHARE_DENYNONE | OPEN_ACCESS_READWRITE, NULL)!=NO_ERROR)
return 2;
memset(&sendpowereventAPM, 0, sizeof(sendpowereventAPM));
powerRC.usReturnCode=0;
/* Enable PWR MGMT function */
sendpowereventAPM.usSubID=SUBID_ENABLE_POWER_MANAGEMENT;
ulPacketSize=sizeof(sendpowereventAPM);
ulDataSize=sizeof(powerRC);
rc=DosDevIOCtl(hfileAPM, IOCTL_POWER, POWER_SENDPOWEREVENT, &sendpowereventAPM, ulPacketSize,
&ulPacketSize, &powerRC, ulDataSize, &ulDataSize);
if(rc!=NO_ERROR || powerRC.usReturnCode!=POWER_NOERROR) {
DosClose(hfileAPM);
return 3;
}
DosSleep(1000); /* need a delay before the set state call for some reason */
/* Invoke APM request */
memset(&sendpowereventAPM, 0, sizeof(sendpowereventAPM));
powerRC.usReturnCode=0;
sendpowereventAPM.usSubID=SUBID_SET_POWER_STATE;
sendpowereventAPM.usData1=usDevice;
sendpowereventAPM.usData2=usPowerState;
ulPacketSize=sizeof(sendpowereventAPM);
ulDataSize=sizeof(powerRC);
rc=DosDevIOCtl(hfileAPM, IOCTL_POWER, POWER_SENDPOWEREVENT,&sendpowereventAPM, ulPacketSize,
&ulPacketSize, &powerRC, ulDataSize, &ulDataSize);
DosClose(hfileAPM);
if(rc!=NO_ERROR || powerRC.usReturnCode!=POWER_NOERROR)
return 4;
else
return 0;
}
VOID FillRectGradient(HPS hps, RECTL *rcl, RECTL *rclClip, LONG RGBDark, LONG RGBLight, BOOL bReverse)
{ USHORT k,usBorderHgt,usRDark,usGDark,usBDark,usRLight,usGLight,usBLight,usYDiff;
float fRGrad,fGGrad,fBGrad;
POINTL ptl;
usRDark=(RGBDark&0xFF0000)>>16,
usGDark=(RGBDark&0xFF00)>>8,
usBDark=(RGBDark&0xFF);
usRLight=(RGBLight&0xFF0000)>>16,
usGLight=(RGBLight&0xFF00)>>8,
usBLight=(RGBLight&0xFF);
usYDiff=rcl->yTop-rcl->yBottom;
fRGrad=(float)(usRLight-usRDark)/(float)(usYDiff==0?1:usYDiff);
fGGrad=(float)(usGLight-usGDark)/(float)(usYDiff==0?1:usYDiff);
fBGrad=(float)(usBLight-usBDark)/(float)(usYDiff==0?1:usYDiff);
for (k=0;k<rcl->yTop-rcl->yBottom;k++) {
ptl.x=rcl->xLeft;
ptl.y=bReverse?rcl->yTop-k-1:rcl->yBottom+k;
if (rclClip!=NULL && (ptl.y<rclClip->yBottom || ptl.y>rclClip->yTop)) continue;
GpiMove(hps,&ptl);
ptl.x=rcl->xRight-1;
GpiSetColor(hps,(int)(usRDark+fRGrad*k)*65536+(int)(usGDark+fGGrad*k)*256+(int)(usBDark+fBGrad*k));
GpiLine(hps,&ptl);
}
}
LONG CalcBrightCol(LONG lColor,UCHAR ucBright)
{ UCHAR ucR,ucG,ucB,ucMax;
LONG lBrightCol;
ucB=lColor&0xFF; ucG=(lColor&0xFF00)>>8; ucR=(lColor&0xFF0000)>>16;
ucMax=max(ucR,max(ucG,ucB));
return (ucBright*ucR/ucMax*65536+ucBright*ucG/ucMax*256+ucBright*ucB/ucMax);
}
static MRESULT EXPENTRY PrtyDlgProc(HWND hwnd,ULONG msg,MPARAM mp1,MPARAM mp2)
{ static HWND hwndPrty;
static PID pidPrty;
switch (msg) {
case WM_INITDLG: {
USHORT usPrty;
SHORT sPrtyC, sPrtyD;
UCHAR ucBuf[128],ucTitle[NAMELEN];
HPS hps;
HWND hwndTBar;
RECTL rcl;
POINTL aptl[TXTBOX_COUNT];
LSWDATA *plswData;
SetControlsFont(hwnd,TRUE);
plswData = (LSWDATA*)PVOIDFROMMP(mp2);
hwndPrty = plswData->TaskArr[plswData->iMenuAtItem].hwnd;
pidPrty = plswData->TaskArr[plswData->iMenuAtItem].pid;
WinQueryDlgItemText(hwnd,FID_TITLEBAR,sizeof(ucBuf),ucBuf);
GetItemTitle(plswData->TaskArr[plswData->iMenuAtItem].hsw,ucTitle,sizeof(ucTitle),TRUE);
strncat(ucBuf,": ",sizeof(ucBuf)-strlen(ucTitle)-1);
strncat(ucBuf,ucTitle,sizeof(ucBuf)-strlen(ucTitle)-1);
hwndTBar=WinWindowFromID(hwnd,FID_TITLEBAR);
hps=WinGetPS(hwndTBar);
WinQueryWindowRect(hwndTBar,&rcl);
GpiQueryTextBox(hps,1,"W",TXTBOX_COUNT,aptl);
MakeFitStr(hps,ucBuf,sizeof(ucBuf), rcl.xRight-rcl.xLeft-aptl[TXTBOX_BOTTOMRIGHT].x-aptl[TXTBOX_BOTTOMLEFT].x);
WinReleasePS(hps);
WinSetDlgItemText(hwnd,FID_TITLEBAR,ucBuf);
DosGetPrty(PRTYS_PROCESS, &usPrty, pidPrty);
sPrtyC = (usPrty+PRTYD_MAXIMUM)>>8;
sPrtyD = usPrty-(sPrtyC<<8);
WinCheckButton(hwnd, sPrtyC==PRTYC_IDLETIME?RAD_IDLETIME:
sPrtyC==PRTYC_REGULAR?RAD_REGULAR:
sPrtyC==PRTYC_TIMECRITICAL?RAD_CRITICAL:RAD_FGNDSERVER,TRUE);
WinSendDlgItemMsg(hwnd,SPIN_DELTA,SPBM_SETLIMITS,MPFROMLONG(PRTYD_MAXIMUM),MPFROMLONG(PRTYD_MINIMUM));
WinSendDlgItemMsg(hwnd,SPIN_DELTA,SPBM_SETTEXTLIMIT,MPFROMSHORT(3),0);
WinSendDlgItemMsg(hwnd,SPIN_DELTA,SPBM_SETCURRENTVALUE,MPFROMLONG(sPrtyD),0);
break;
}
case WM_COMMAND:
if (SHORT1FROMMP(mp1)==DID_OK) {
SHORT sPrtyC, sPrtyD;
BOOL bDesc;
WinSendDlgItemMsg(hwnd,SPIN_DELTA,SPBM_QUERYVALUE,MPFROMP(&sPrtyD),MPFROM2SHORT(0,SPBQ_ALWAYSUPDATE));
if (WinQueryButtonCheckstate(hwnd,RAD_IDLETIME)) sPrtyC=PRTYC_IDLETIME;
else if (WinQueryButtonCheckstate(hwnd,RAD_REGULAR)) sPrtyC=PRTYC_REGULAR;
else if (WinQueryButtonCheckstate(hwnd,RAD_CRITICAL)) sPrtyC = PRTYC_TIMECRITICAL;
else sPrtyC = PRTYC_FOREGROUNDSERVER;
bDesc = (WinQueryButtonCheckstate(hwnd,CHK_DESCENDANTS));
WinPostMsg(hwndPrty,LSWM_SETPRIORITY,
MPFROM2SHORT(((sPrtyC<<8)+sPrtyD)|(bDesc?0x8000:0),PRTY_MAGIC),
MPFROMLONG(pidPrty));
}
default:
return WinDefDlgProc(hwnd, msg, mp1, mp2);
}
return 0;
}
static MRESULT EXPENTRY RunDlgProc(HWND hwnd,ULONG msg,MPARAM mp1,MPARAM mp2)
{ static HWND hwndList;
static UCHAR ucFName[_MAX_PATH];
switch (msg) {
case WM_INITDLG: {
UCHAR *ucBuf;
HFILE hFile;
ULONG ulAction,ulcbRead,k,pos;
APIRET rc;
SetControlsFont(hwnd,FALSE);
hwndList=WinWindowFromID(hwnd,CB_RUNCOMMAND);
WinSendMsg(hwndList,EM_SETTEXTLIMIT,MPFROMSHORT(_MAX_PATH),0);
GetStartupDir(ucFName,sizeof(ucFName));
strncat(ucFName,HSTFILENAME,sizeof(ucFName)-strlen(ucFName)-1);
rc=DosOpen(ucFName,&hFile,&ulAction,0,FILE_ARCHIVED|FILE_NORMAL,
OPEN_ACTION_OPEN_IF_EXISTS|OPEN_ACTION_FAIL_IF_NEW,
OPEN_FLAGS_FAIL_ON_ERROR|OPEN_SHARE_DENYWRITE|OPEN_ACCESS_READWRITE,0);
if (rc==0) {
if ((ucBuf=malloc((_MAX_PATH+2)*MAXRUNLISTHST))==NULL) {
DosClose(hFile);
break;
}
DosRead(hFile,ucBuf,(_MAX_PATH+2)*MAXRUNLISTHST,&ulcbRead);
DosClose(hFile);
for (k=0,pos=0;k<ulcbRead;k++)
if (ucBuf[k]=='\n') {
ucBuf[k]=ucBuf[k-1]='\0';
WinSendMsg(hwndList,LM_INSERTITEM,MPFROMSHORT(LIT_END),MPFROMP(&ucBuf[pos]));
pos=k+1;
}
free(ucBuf);
WinSendMsg(hwndList,LM_SELECTITEM,MPFROMSHORT(0),MPFROMSHORT(TRUE));
}
break;
}
case WM_COMMAND:
switch (SHORT1FROMMP(mp1)) {
case DID_OK: {
UCHAR ucCmd[_MAX_PATH+2],ucErrMsg[128],ucItemText[_MAX_PATH];
USHORT k,usItemCount;
SHORT sIndex;
ULONG ulcbWrite,ulAction;
APIRET rc;
HFILE hFile;
LSWDATA *plswData;
WinQueryWindowText(hwndList,sizeof(ucCmd), ucCmd);
strcpy(ucItemText,ucCmd); //RunCommand changes ucCmd
if (DosGetNamedSharedMem((PVOID*)&plswData,SHAREMEM_NAME,PAG_READ | PAG_WRITE)==0 &&
(rc=RunCommand(plswData,ucCmd,ucErrMsg,sizeof(ucErrMsg)))!=0) {
WinMessageBox(HWND_DESKTOP,HWND_DESKTOP,ucErrMsg,PGMNAME,0,MB_ERROR | MB_CANCEL);
DosFreeMem(plswData);
break;
}
sIndex=(SHORT)WinSendMsg(hwndList,LM_SEARCHSTRING,MPFROM2SHORT(0,LIT_FIRST),MPFROMP(ucItemText));
if (sIndex!=LIT_NONE)
WinSendMsg(hwndList,LM_DELETEITEM,MPFROMSHORT(sIndex),0);
WinSendMsg(hwndList,LM_INSERTITEM,MPFROMSHORT(0),MPFROMP(ucItemText));
rc=DosOpen(ucFName,&hFile,&ulAction,0,FILE_ARCHIVED|FILE_NORMAL,
OPEN_ACTION_REPLACE_IF_EXISTS|OPEN_ACTION_CREATE_IF_NEW,
OPEN_FLAGS_FAIL_ON_ERROR|OPEN_SHARE_DENYWRITE|OPEN_ACCESS_READWRITE,0);
if (rc==0) {
usItemCount=LONGFROMMR(WinSendMsg(hwndList,LM_QUERYITEMCOUNT,0,0));
for (k=0;k<usItemCount && k<MAXRUNLISTHST;k++) {
WinSendMsg(hwndList,LM_QUERYITEMTEXT,MPFROM2SHORT(k,sizeof(ucItemText)),MPFROMP(ucItemText));
sprintf(ucCmd,"%s\r\n",ucItemText);
DosWrite(hFile,ucCmd,strlen(ucCmd),&ulcbWrite);
}
DosClose(hFile);
}
return WinDefDlgProc(hwnd, msg, mp1, mp2);
}
case PB_BROWSE: {
static FILEDLG fild={0};
HWND hwndFDlg;
SHORT k;
fild.cbSize = sizeof(FILEDLG);
fild.fl = FDS_CENTER | FDS_OPEN_DIALOG ;
hwndFDlg = WinFileDlg(HWND_DESKTOP, hwnd, &fild);
if (hwndFDlg!=NULLHANDLE && (fild.lReturn == DID_OK))
WinSetWindowText(hwndList,(PCHAR)PVOIDFROMMP(fild.szFullFile));
for (k=strlen(fild.szFullFile);k>=0;k--)
if (fild.szFullFile[k]=='\\') {
fild.szFullFile[k+1]='\0';
strcat(fild.szFullFile,"*.EXE");
break;
}
break;
}
case DID_CANCEL:
WinSendDlgItemMsg(hwnd,CB_RUNCOMMAND,CBM_SHOWLIST,MPFROMSHORT(FALSE),0);
return WinDefDlgProc(hwnd, msg, mp1, mp2);
default:
return WinDefDlgProc(hwnd, msg, mp1, mp2);
}
break;
default:
return WinDefDlgProc(hwnd, msg, mp1, mp2);
}
return 0;
}
VOID ProcessCommand(USHORT cmd, USHORT src, LSWDATA *plswData, BOOL bTaskBar, BOOL bAll)
{
switch (cmd) {
case CMD_CANCELPOPUP:
case CMD_CANCELPOPUP1:
plswData->usCurrItem = MAXITEMS-1;
case CMD_SWITCHFROMPM:
if (plswData->bNowActive) {
WinSetWindowPos(plswData->hwndPopup,HWND_BOTTOM, plswData->usPopupWinHideX,
plswData->usPopupWinHideY, 0, 0, SWP_MOVE | SWP_SIZE | SWP_ZORDER);
ShowBubble(plswData,0,0,0,-1,NULL);
}
if (src==CMDSRC_MENU) plswData->usCurrItem = plswData->iMenuAtItem;
case CMD_SWITCHFROMFS:
/* turn the flag off only after the window has been repositioned or
our subclassed frame window function won't let do this */
plswData->bNowActive = FALSE;
if (cmd != CMD_CANCELPOPUP && cmd != CMD_CANCELPOPUP1) {
if (plswData->Settings.bDesktopMinimizes && IsDesktop(plswData->TaskArr[plswData->usCurrItem].hwnd)) {
MinimizeHideAll(plswData,FALSE,0);
break; //switching to desktop is done in MinimizeHideAll function
}
// for some weird reason WinSwitchToProgram does not always bring the window to top
// showing is needed for hidden windows and won't hurt in other cases
WinSetWindowPos(plswData->TaskArr[plswData->usCurrItem].hwnd,HWND_TOP,0,0,0,0,SWP_SHOW|SWP_ZORDER);
}
/* don't switch if the popup has been cancelled and current program
has been minimized or hidden or if a close window query has popped up and
changed the focus to itself (and the POPUP_CANCEL has been triggered by
the WM_TIMER) after the close command has been sent to a window */
if (cmd != CMD_CANCELPOPUP1) {
if (cmd != CMD_CANCELPOPUP ||
((plswData->TaskArr[plswData->usCurrItem].fl & (SWP_HIDE | SWP_MINIMIZE))==0) ||
((plswData->TaskArr[plswData->usCurrItem].ulType==PROG_FULLSCREEN ||
plswData->TaskArr[plswData->usCurrItem].ulType==PROG_VDM) &&
plswData->Settings.bPMPopupInFS))
// if we want to switch to the currently active window, which may be required if it's in
// another virtual desktop, activate desktop first, otherwise WinSwitchToProgram will not work
if (WinQueryActiveWindow(HWND_DESKTOP)==plswData->TaskArr[plswData->usCurrItem].hwnd)
WinSetActiveWindow(HWND_DESKTOP,plswData->TaskArr[plswData->usItems-1].hwnd);
if (plswData->TaskArr[plswData->usCurrItem].hsw != 0)
WinSwitchToProgram(plswData->TaskArr[plswData->usCurrItem].hsw);
else
WinSetWindowPos(plswData->TaskArr[plswData->usCurrItem].hwnd,
HWND_TOP,0,0,0,0,SWP_ACTIVATE | SWP_ZORDER);
/* this is needed to make a full screen session current */
if (plswData->TaskArr[plswData->usCurrItem].ulType==PROG_FULLSCREEN ||
plswData->TaskArr[plswData->usCurrItem].ulType==PROG_VDM)
WinSetWindowPos(plswData->TaskArr[plswData->usCurrItem].hwnd,HWND_TOP,
0,0,0,0,SWP_ZORDER | SWP_ACTIVATE);
}
break;
case CMD_SHOWSETTINGS:
if (!plswData->bNowActive) EditSettings(plswData);
break;
case CMD_PRIORITY:
if (src==CMDSRC_ACCELERATOR) {
if (!MenuNeedsItem(plswData,plswData->usCurrItem,CMD_PRIORITY,NULL,0,FALSE))
break;
plswData->iMenuAtItem = plswData->usCurrItem;
}
WinDlgBox(HWND_DESKTOP,HWND_DESKTOP,PrtyDlgProc,plswData->hmodRes,DLG_PRTY,plswData);
break;
case CMD_ADDFILTER: {
ENTRYNAME ucName;
if (src==CMDSRC_ACCELERATOR)
plswData->iMenuAtItem = plswData->usCurrItem;
GetItemTitle(plswData->TaskArr[plswData->iMenuAtItem].hsw,ucName,sizeof(ucName),FALSE);
if (AddFilter(&plswData->Settings,ucName,bTaskBar)) {
USHORT k;
ENTRYNAME ucName1;
for (k=0;k<plswData->usItems;k++) { //check for entries with the same name
GetItemTitle(plswData->TaskArr[k].hsw,ucName1,sizeof(ucName1),FALSE);
if (strcmp(ucName,ucName1)==0)
WinPostMsg(bTaskBar?plswData->hwndTaskBarClient:plswData->hwndPopClient,LSWM_SWITCHLISTCHANGED, MPFROMLONG(2), MPFROMLONG(plswData->TaskArr[k].hsw));
}
}
break;
}
case CMD_HIDE:
case CMD_SHOW:
case CMD_RESTORE:
case CMD_MINIMIZE:
case CMD_MAXIMIZE:
case CMD_MOVE:
case CMD_CLOSE:
case CMD_KILL:
case CMD_DEATH:
case CMD_CLOSEQUIT:
if (bAll && cmd>=CMD_HIDE && cmd<=CMD_CLOSE) {
SHORT k;
for (k=plswData->usItems-1;k>=0;k--)
if (plswData->TaskArr[k].pid==
plswData->TaskArr[src==CMDSRC_MENU?plswData->iMenuAtItem:plswData->usCurrItem].pid &&
!IsDesktop(plswData->TaskArr[k].hwnd) &&
(cmd!=CMD_CLOSE||(cmd==CMD_CLOSE && WndHasControl(plswData->hab,plswData->TaskArr[k].hwnd,SC_CLOSE))))
ChangeWindowPos(plswData, k,cmd);
} else
/* if this command comes from the keyboard use plswData->usCurrItem */
ChangeWindowPos(plswData, src==CMDSRC_MENU ? plswData->iMenuAtItem : plswData->usCurrItem,cmd);
break;
case CMD_RUN: {
static HWND hwndRunDlg=NULLHANDLE;
if (!WinIsWindow(plswData->hab,hwndRunDlg))
hwndRunDlg=WinLoadDlg(HWND_DESKTOP,NULLHANDLE,RunDlgProc,plswData->hmodRes,DLG_RUN,NULL);
if (hwndRunDlg != NULLHANDLE) {
WinSetWindowPos(hwndRunDlg,HWND_TOP,0,0,0,0,SWP_SHOW | SWP_ZORDER | SWP_ACTIVATE);
WinProcessDlg(hwndRunDlg);
WinDestroyWindow(hwndRunDlg);
}
break;
}
case CMD_QUIT:
WinPostMsg(plswData->hwndPopup, WM_QUIT, 0, 0);
break;
}
}