Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

3811 lines
104 KiB

/****************************** Module Header ******************************\
* Module Name: topdesk.c - TopDesk application
*
* Copyright (c) 1992 Sanford Staab
*
\***************************************************************************/
#define UNICODE
#define _UNICODE
#define NOGDICAPMASKS
#define NOATOM
#define NOCLIPBOARD
#define NOLOGERROR
#define NOMETAFILE
#define NOOEMRESOURCE
#define NOSCROLL
#define NOPROFILER
#define NODRIVERS
#define NOCOMM
#define NODBCS
#define NOSYSTEMPARAMSINFO
#define NOSCALABLEFONT
//#define DEBUG
#include "topdesk.h"
//#include <shell.h> // import stuff directly-------------------------
HINSTANCE RealShellExecuteA(
HWND hwndParent,
LPCSTR lpOperation,
LPCSTR lpFile,
LPCSTR lpParameters,
LPCSTR lpDirectory,
LPSTR lpResult,
LPCSTR lpTitle,
LPSTR lpReserved,
WORD nShow,
LPHANDLE lphProcess);
HINSTANCE RealShellExecuteW(
HWND hwndParent,
LPCWSTR lpOperation,
LPCWSTR lpFile,
LPCWSTR lpParameters,
LPCWSTR lpDirectory,
LPWSTR lpResult,
LPCWSTR lpTitle,
LPWSTR lpReserved,
WORD nShow,
LPHANDLE lphProcess);
#ifndef UNICODE
#define RealShellExecute RealShellExecuteA
#else
#define RealShellExecute RealShellExecuteW
#endif //UNICODE
//--------------------------------------------------------------------
#include "itsybits.h" // tiny caption module
#define CondDefWindowProc(h, m, w, l) (pro.fShowFrameCtrls ? DefWindowProc(h, m, w, l) : ibDefWindowProc(h, m, w, l))
#ifndef HLOCAL
#define HLOCAL HANDLE
#endif /* HLOCAL */
#ifndef MAX_PATH
#define MAX_PATH 128
#endif
/* --------------------- How the dang thing works -----------------------
magnification factor (0 = highest magnification)( mfx , mfy )
number of virtual desktops showing ( nxVDT , nyVDT )
Real Desktop size == screen size ( cxrDT , cyrDT )
client window size ( cxc , cyc )
Client coords Desktop size ( cxcDT , cycDT )
offset of home desktop from center VDT org ( oxrHDT , oyrHDT )
offset of current desktop from center VDT org ( oxrCDT , oyrCDT )
origin of center VDT in client coords ( oxcODT , oycODT )
relations: ? = x or y Dependent vars
To find out how many VDTs fit in the client:
n?VDT = mf? << 1 + 1 mf?
To find size of the desktop on the client:
c?cDT = (c?c + (n?VDT / 2)) / n?VDT mf?, c?c
To find the origin of the desktop on the client:
o?cODT = c?cDT * mf? mf?, c?cDT
o?rCDT is (0,0) when in relative viewing mode
o?rHDT is (0,0) when in absolute viewing mode
real -> client coord conversion:
?c = ((?r + o?rCDT) * (c?cDT / c?rDT) + o?cODT
client -> real coord conversion:
?r = ((?c - o?cODT) * (c?rDT / c?cDT) - o?rCDT
------------------------------------------------------------------------*/
// Globals
#ifdef DEBUG
FILE *hfDbgOut;
#define DPRINTF(x) fprintf##x;
#else
#define DPRINTF(x)
#endif // DEBUG
BOOL fStartingGhost = FALSE;
BOOL fBlockRefresh = FALSE;
BOOL fFrameToggleSize = FALSE;
BOOL fInvalidated = FALSE;
BOOL fStarted = FALSE;
BOOL fCairoShell = FALSE;
LPTSTR pszTopmost;
LPTSTR pszShowFrmCtrls;
LPTSTR pszData;
LPTSTR pszTopdeskHelpTitle;
LPTSTR pszHelpFileName;
LPTSTR pszWorking;
LPTSTR pszProfile;
LPTSTR pszStartupInfo;
LPTSTR pszTitle;
LPTSTR pszSubKey;
LPTSTR pszVersion;
TCHAR szWindowsDir[_MAX_PATH];
TCHAR szColorName[MAX_COLORNAME];
TCHAR szResString2[MAX_RESSTRING];
TCHAR szResString[MAX_RESSTRING];
LPTSTR pszSetTitle;
FARPROC fpRefreshEnumProc;
HANDLE hAccel;
HANDLE hInst;
HBITMAP hbmMem;
HBITMAP hbmOldMem;
HDC hdcDraw;
HDC hdcMem;
HFONT hMyFont;
HKEY hKeyTopDesk = NULL;
HWND hwndDT = 0;
HWND hwndFocus = 0;
HWND hwndTopdesk;
INT iStartGhost = -1;
INT cGhosts = 0;
INT cWindows = 0;
INT cxc;
INT cxcDT;
INT cxcDTmin;
INT cxFrame;
INT cxrDT;
INT cyc;
INT cycDT;
INT cycDTmin;
INT cyFrame;
INT cyrDT;
INT iRefresh;
INT ihwndJump = -1;
INT nxVDT;
INT nyVDT;
INT oxcODT;
INT oxrCDT = 0;
INT oxrHDT = 0;
INT oycODT;
INT oyrCDT = 0;
INT oyrHDT = 0;
INT PrevGhostState = SG_NONE;
INT idResetGhostTimer = 0;
UINT wmRefreshMsg;
MYSTARTUPINFO *pStartupInfo = NULL;
RECT rcrDT;
RECT rcrMS;
BOOL fStartingAnApp;
INT PopupGhostIndex;
INT PopupRealIndex;
POINT PopupPt;
HWND PopuphwndFocus;
HMENU hMenuTopdesk;
HMENU hMenuDesktop;
HMENU hMenuWindows;
HMENU hMenuHelp;
// This structure holds the topdesk profile information - the state of MD.
WINSTATE winstate[MAX_REMEMBER];
WINSTATE ghoststate[MAX_REMEMBER];
LPTSTR pszElementNames[MAX_ICOLOR] =
{
TEXT("") , // filler for no color
NULL , // SPACECOLOR
NULL , // WINDOWFILLCOLOR
NULL , // WINDOWFRAMECOLOR
TEXT("") , // DESKFILLCOLOR
NULL , // DESKFRAMECOLOR
NULL , // GRIDCOLOR
NULL , // GHOSTFRAMECOLOR
NULL , // WINDOWTEXT
NULL , // FIXEDFRAMECOLOR
NULL // GHOSTTEXTCOLOR
};
// This array controls colors. It allows us to keep track of your brushes.
HBR orgColors[MAX_ICOLOR] = {
{ 0, 0, 1 }, // filler for no color
{ 0, RGB( 0, 0, 0 ),0 }, // SPACECOLOR
{ 0, RGB( 0, 0xff, 0xff),0 }, // WINDOWFILLCOLOR
{ 0, RGB( 0, 0, 0xff),0 }, // WINDOWFRAMECOLOR
{ 0, 0, COLOR_BACKGROUND }, // DESKFILLCOLOR
{ 0, RGB( 0, 0xff, 0 ),0 }, // DESKFRAMECOLOR
{ 0, RGB( 0xff, 0, 0 ),0 }, // GRIDCOLOR
{ 0, RGB( 0xff, 0xff, 0xff),0 }, // GHOSTFRAMECOLOR
{ 0, RGB( 0, 0, 0 ),0 }, // WINDOWTEXT
{ 0, RGB( 0xff, 0xff, 0 ),0 }, // FIXEDFRAMECOLOR
{ 0, RGB( 0xff, 0xff, 0xff),0 }, // GHOSTTEXTCOLOR
};
PRO pro = {
{ // lf
-12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, TEXT("Arial")
},
{ 0 }, // ahbr is set up at init time.
{ // CustColors[]
RGB(0xff, 0xff, 0xff),
RGB(0xff, 0xff, 0xff),
RGB(0xff, 0xff, 0xff),
RGB(0xff, 0xff, 0xff),
RGB(0xff, 0xff, 0xff),
RGB(0xff, 0xff, 0xff),
RGB(0xff, 0xff, 0xff),
RGB(0xff, 0xff, 0xff),
RGB(0xff, 0xff, 0xff),
RGB(0xff, 0xff, 0xff),
RGB(0xff, 0xff, 0xff),
RGB(0xff, 0xff, 0xff),
RGB(0xff, 0xff, 0xff),
RGB(0xff, 0xff, 0xff),
RGB(0xff, 0xff, 0xff),
RGB(0xff, 0xff, 0xff)
},
FALSE, // fShift;
FALSE, // fAlt;
TRUE, // fControl;
' ', // vkey;
1, // mfx;
1, // mfy;
1, // mfxAlt;
1, // mfyAlt;
0, // x;
0, // y;
0, // cx;
0, // cy;
SG_NONE, // iShowGhosts;
FALSE, // fRelative;
TRUE, // fDistOnStart;
TRUE, // fShowFrameCtrls;
FALSE, // fAutoAdj;
FALSE, // fAlwaysOnTop;
FALSE, // fHideNoFocus;
};
/**************************************/
// Calculation functions
// Conversions
INT xr2xc(
INT xr)
{
return(INT)(((LONG)(xr + oxrCDT) * (LONG)cxcDT / (LONG)cxrDT) + oxcODT);
}
INT yr2yc(
INT yr)
{
return(INT)(((LONG)(yr + oyrCDT) * (LONG)cycDT / (LONG)cyrDT) + oycODT);
}
INT xc2xr(
INT xc)
{
return(INT)(((LONG)(xc - oxcODT) * (LONG)cxrDT / (LONG)cxcDT) - oxrCDT);
}
INT yc2yr(
INT yc)
{
return(INT)(((LONG)(yc - oycODT) * (LONG)cyrDT / (LONG)cycDT) - oyrCDT);
}
VOID rRect2cRect(
PRECT prcr)
{
prcr->left = xr2xc(prcr->left);
prcr->right = xr2xc(prcr->right);
prcr->top = yr2yc(prcr->top);
prcr->bottom = yr2yc(prcr->bottom);
}
VOID cRect2rRect(
PRECT prcc)
{
prcc->left = xc2xr(prcc->left);
prcc->right = xc2xr(prcc->right);
prcc->top = yc2yr(prcc->top);
prcc->bottom = yc2yr(prcc->bottom);
}
BOOL RectInRect(
PRECT prcInside,
PRECT prcOutside)
{
return(prcInside->left >= prcOutside->left &&
prcInside->right <= prcOutside->right &&
prcInside->top >= prcOutside->top &&
prcInside->bottom <= prcOutside->bottom);
}
//
// Calculates new n?VDT, c?cDT, and o?cODT
//
// This needs to be called whenever mf? or c?c change so conversions work.
//
VOID CalcConversionFactors(
BOOL fCheckShape)
{
INT cxcDTorg, cycDTorg;
INT oe = 0;
cxcDTorg = cxcDT;
cycDTorg = cycDT;
Recalc:
oe++; // causes alternating direction first checks
nxVDT = (pro.mfx << 1) + 1;
nyVDT = (pro.mfy << 1) + 1;
cxcDT = (cxc + pro.mfx) / nxVDT;
cycDT = (cyc + pro.mfy) / nyVDT;
if (fCheckShape && pro.fAutoAdj) {
if (cycDT > cxcDT * 2) {
// Too tall - fix it!
if (oe & 1) {
if (cycDTorg < cycDT) { // if its taller than it was...
if (cycDT > cycDTmin) {
pro.mfy++; // make it shorter
goto Recalc;
}
}
}
if (cxcDTorg > cxcDT) { // if its skinner than it was...
if (pro.mfx > 0) {
pro.mfx--; // make it fatter
goto Recalc;
}
}
if (!(oe & 1)) {
if (cycDTorg < cycDT) { // if its taller than it was...
if (cycDT > cycDTmin) {
pro.mfy++; // make it shorter
goto Recalc;
}
}
}
if (cycDT > cycDTmin) {
pro.mfy++; // make it shorter if we can
goto Recalc;
}
if (pro.mfx > 0) {
pro.mfx--; // make it fatter if we can
goto Recalc;
}
}
if (cxcDT > cycDT * 2) {
// Too fat - fix it!
if (oe & 1) {
if (cxcDTorg < cxcDT) { // if its fatter than it was...
if (cxcDT > cxcDTmin) {
pro.mfx++; // make it skinnier
goto Recalc;
}
}
}
if (cycDTorg > cycDT) { // if its shorter than it was...
if (pro.mfy > 0) {
pro.mfy--; // make it taller
goto Recalc;
}
}
if (!(oe & 1)) {
if (cxcDTorg < cxcDT) { // if its fatter than it was...
if (cxcDT > cxcDTmin) {
pro.mfx++; // make it skinnier
goto Recalc;
}
}
}
if (cxcDT > cxcDTmin) {
pro.mfx++; // make it skinnier
goto Recalc;
}
if (pro.mfy > 0) {
pro.mfy--; // make it taller
goto Recalc;
}
}
}
oxcODT = cxcDT * pro.mfx;
oycODT = cycDT * pro.mfy;
}
LPTSTR GetResString(
DWORD id)
{
LoadString(hInst, id, szResString, sizeof(szResString));
return(szResString);
}
VOID DrawIndentRect(
HDC hdc,
PRECT prc)
{
HANDLE hPenSave;
SetROP2(hdc, R2_COPYPEN);
hPenSave = SelectObject(hdc, GetStockObject(BLACK_PEN));
MMoveTo(hdc, prc->left, prc->bottom - 1);
LineTo(hdc, prc->left, prc->top);
LineTo(hdc, prc->right - 1, prc->top);
SelectObject(hdc, GetStockObject(WHITE_PEN));
MMoveTo(hdc, prc->right, prc->top + 1);
LineTo(hdc, prc->right, prc->bottom);
LineTo(hdc, prc->left + 1, prc->bottom);
SelectObject(hdc, hPenSave);
}
VOID DrawExdentRect(
HDC hdc,
PRECT prc)
{
HANDLE hPenSave;
SetROP2(hdc, R2_COPYPEN);
hPenSave = SelectObject(hdc, GetStockObject(WHITE_PEN));
MMoveTo(hdc, prc->left, prc->bottom - 1);
LineTo(hdc, prc->left, prc->top);
LineTo(hdc, prc->right - 1, prc->top);
SelectObject(hdc, GetStockObject(BLACK_PEN));
MMoveTo(hdc, prc->right, prc->top + 1);
LineTo(hdc, prc->right, prc->bottom);
LineTo(hdc, prc->left + 1, prc->bottom);
SelectObject(hdc, hPenSave);
}
VOID Working(
RECT *prc)
{
HDC hdc;
HFONT hfSave;
RECT rcClient;
hdc = GetDC(hwndTopdesk);
hfSave = SelectObject(hdc, hMyFont);
GetClientRect(hwndTopdesk, &rcClient);
*prc = rcClient;
DrawText(hdc, pszWorking, -1, prc, DT_CALCRECT);
OffsetRect(prc, (rcClient.right - prc->right) / 2,
(rcClient.bottom - prc->bottom) / 2);
InflateRect(prc, 4, 4);
FillRect(hdc, prc, GetStockObject(GRAY_BRUSH));
DrawExdentRect(hdc, prc);
InflateRect(prc, -3, -3);
DrawIndentRect(hdc, prc);
InflateRect(prc, -1, -1);
SetBkMode(hdc, TRANSPARENT);
DrawText(hdc, pszWorking, -1, prc, 0);
InflateRect(prc, 4, 4);
SelectObject(hdc, hfSave);
ReleaseDC(hwndTopdesk, hdc);
InflateRect(prc, 1, 1);
}
//
// File IO - make that registry IO!
//
BOOL MyQueryProfileSize(
LPTSTR szFname,
INT *pSize)
{
DWORD type;
*pSize = 0;
if (hKeyTopDesk == NULL) {
return(FALSE);
}
return(RegQueryValueEx(hKeyTopDesk, szFname, 0, &type, NULL, (LPDWORD)pSize)
== ERROR_SUCCESS);
}
BOOL MyQueryProfileData(
LPTSTR szFname,
VOID *lpBuf,
INT Size)
{
DWORD type = REG_BINARY;
if (hKeyTopDesk == NULL) {
return(FALSE);
}
return(RegQueryValueEx(hKeyTopDesk, szFname, NULL, &type, lpBuf, (LPDWORD)&Size)
== ERROR_SUCCESS);
}
UINT MyWriteProfileData(
LPTSTR szFname,
VOID *lpBuf,
UINT cb)
{
if (hKeyTopDesk == NULL) {
return(FALSE);
}
return(RegSetValueEx(hKeyTopDesk, szFname, 0, REG_BINARY, lpBuf, (DWORD)cb)
== ERROR_SUCCESS);
}
MYSTARTUPINFO *CreateStartupInfo(
LPTSTR pszTitle,
LPTSTR pszStartup,
LPTSTR pszWorkDir,
BOOL fSetTitle)
{
MYSTARTUPINFO *psi;
psi = (MYSTARTUPINFO *)LocalAlloc(LPTR, sizeof(MYSTARTUPINFO));
psi->pszTitle = (LPTSTR)LocalAlloc(LPTR, (_tcslen(pszTitle) + 1) * sizeof(TCHAR));
_tcscpy(psi->pszTitle, pszTitle);
psi->pszStartup = (LPTSTR)LocalAlloc(LPTR, (_tcslen(pszStartup) + 1) * sizeof(TCHAR));
_tcscpy(psi->pszStartup, pszStartup);
psi->pszWorkDir = (LPTSTR)LocalAlloc(LPTR, (_tcslen(pszWorkDir) + 1) * sizeof(TCHAR));
_tcscpy(psi->pszWorkDir, pszWorkDir);
psi->fSetTitle = fSetTitle;
psi->next = pStartupInfo;
pStartupInfo = psi;
return(psi);
}
VOID LoadGhostState()
{
DWORD cbData, dwType;
LPTSTR pszBuf, psz, pszT;
if (RegQueryValueEx(hKeyTopDesk, pszData, NULL, &dwType, NULL, &cbData) != ERROR_SUCCESS) {
return;
}
if (dwType != REG_MULTI_SZ) {
RegDeleteValue(hKeyTopDesk, pszData);
return;
}
pszBuf = LocalAlloc(LPTR, cbData);
if (pszBuf == NULL) {
return;
}
if (RegQueryValueEx(hKeyTopDesk, pszData, NULL, &dwType,
(LPBYTE)pszBuf, &cbData) != ERROR_SUCCESS) {
LocalFree(pszBuf);
return;
}
psz = pszBuf;
while (*psz != TEXT('\0')) {
if (_stscanf(psz, TEXT("(%08d,%08d,%08d,%08d),%08x"),
&ghoststate[cGhosts].rc.left,
&ghoststate[cGhosts].rc.right,
&ghoststate[cGhosts].rc.top,
&ghoststate[cGhosts].rc.bottom,
&ghoststate[cGhosts].style) == 5) {
pszT = _tcschr(psz, TEXT('['));
if (pszT != NULL && *pszT == TEXT('[')) {
_tcscpy(ghoststate[cGhosts].szTitle, pszT + 1);
pszT = _tcsrchr(ghoststate[cGhosts].szTitle, TEXT(']'));
if (pszT != NULL) {
*pszT = TEXT('\0');
}
ghoststate[cGhosts].hwnd = 0;
cGhosts++;
psz += _tcslen(psz) + 1;
}
}
}
LocalFree(pszBuf);
}
VOID SaveGhostState()
{
TCHAR psz[200];
LPTSTR pszBuf;
DWORD cchTotal, cchPrev;
int i;
if (cGhosts == 0) {
RegDeleteValue(hKeyTopDesk, pszData);
return;
}
MoveGhosts(oxrCDT - oxrHDT, oyrCDT - oyrHDT);
cchTotal = 0;
for (i = 0; i < cGhosts; i++) {
cchPrev = cchTotal;
wsprintf(psz, TEXT("(%08d,%08d,%08d,%08d),%08x,[%s]"),
ghoststate[i].rc.left,
ghoststate[i].rc.right,
ghoststate[i].rc.top,
ghoststate[i].rc.bottom,
ghoststate[i].style,
ghoststate[i].szTitle);
cchTotal += _tcslen(psz) + 1;
if (i == 0) {
pszBuf = LocalAlloc(LPTR, (cchTotal + 1) * sizeof(TCHAR));
} else {
pszBuf = LocalReAlloc(pszBuf, (cchTotal + 1) * sizeof(TCHAR),
LMEM_MOVEABLE);
}
if (pszBuf == NULL) {
return; // FAILED
}
_tcscpy(&pszBuf[cchPrev], psz);
}
pszBuf[cchTotal] = TEXT('\0');
RegSetValueEx(hKeyTopDesk, pszData, 0, REG_MULTI_SZ,
(LPBYTE)pszBuf, (cchTotal + 1) * sizeof(TCHAR));
LocalFree(pszBuf);
MoveGhosts(oxrHDT - oxrCDT, oyrHDT - oyrCDT);
}
/*
* Returns FALSE if the profile portion was not read in ok.
* GhostState and StartupInfo input do not effect the return value.
* This is so topdesk can use the desktop size to determine the default
* placement of topdesk.
*/
BOOL GetProfile()
{
INT c;
BOOL fRet = FALSE;
//
// startup info
//
MyQueryProfileSize(pszStartupInfo, &c);
if (c) {
LPTSTR pBuf, pszT, pszTitle, pszStartup, pszWorkDir;
BOOL fSetTitle;
pBuf = (LPTSTR)LocalAlloc(LPTR, c);
if (pBuf != NULL) {
MyQueryProfileData(pszStartupInfo, pBuf, c);
pszTitle = pBuf;
while (*pszTitle) {
fSetTitle = FALSE;
if (pszTitle[0] == TEXT('*')) {
fSetTitle = TRUE;
pszTitle++;
} else if (pszTitle[0] == TEXT(' ')) {
pszTitle++;
}
pszStartup = _tcschr(pszTitle, TEXT('='));
if (pszStartup == NULL) {
break;
}
*pszStartup++ = TEXT('\0');
pszWorkDir = _tcschr(pszStartup, TEXT('@'));
if (pszWorkDir == NULL) {
break;
}
*pszWorkDir++ = TEXT('\0');
pszT = pszWorkDir;
while (*pszT++) {
;
}
CreateStartupInfo(pszTitle, pszStartup, pszWorkDir, fSetTitle);
pszTitle = pszT;
}
LocalFree((HLOCAL)pBuf);
}
}
//
// profile data
//
MyQueryProfileSize(pszProfile, &c);
if (c == sizeof(pro)) {
MyQueryProfileData(pszProfile, (LPTSTR)&pro, sizeof(pro));
fRet = TRUE;
}
LoadGhostState();
return(fRet);
}
VOID SaveProfile()
{
RECT rc;
MYSTARTUPINFO *psi;
LPTSTR pszBuf, psz;
DWORD cb = 0;
if (hKeyTopDesk == NULL) {
return;
}
if (IsIconic(hwndTopdesk)) {
ShowWindow(hwndTopdesk, SW_RESTORE);
}
GetWindowRect(hwndTopdesk, &rc); // screen coords
pro.x = (INT)rc.left;
pro.y = (INT)rc.top;
pro.cx = (INT)rc.right - (INT)rc.left;
pro.cy = (INT)rc.bottom - (INT)rc.top;
MyWriteProfileData(pszProfile, (LPTSTR)&pro, sizeof(pro));
psz = pszBuf = LocalAlloc(LPTR, 4 * 1024 * sizeof(TCHAR));
if (pszBuf != NULL) {
*pszBuf = TEXT('\0'); // zero terminate
psi = pStartupInfo;
while (psi != NULL) {
_tcscat(pszBuf, psi->fSetTitle ? TEXT("*") : TEXT(" "));
_tcscat(pszBuf, psi->pszTitle);
_tcscat(pszBuf, TEXT("="));
_tcscat(pszBuf, psi->pszStartup);
_tcscat(pszBuf, TEXT("@"));
_tcscat(pszBuf, psi->pszWorkDir);
cb += (_tcslen(pszBuf) + 1) * sizeof(TCHAR);
pszBuf = _tcschr(pszBuf, TEXT('\0'));
pszBuf++;
*pszBuf = TEXT('\0');
psi = psi->next;
}
}
cb += sizeof(TCHAR);
RegSetValueEx(hKeyTopDesk, pszStartupInfo, 0, REG_MULTI_SZ, (BYTE *)psz, cb);
LocalFree(psz);
}
VOID FreeStartupInfo()
{
MYSTARTUPINFO *psi;
psi = pStartupInfo;
while (psi != NULL) {
LocalFree((HLOCAL)psi->pszTitle);
LocalFree((HLOCAL)psi->pszStartup);
LocalFree((HLOCAL)psi->pszWorkDir);
psi = pStartupInfo->next;
LocalFree((HLOCAL)pStartupInfo);
pStartupInfo = psi;
}
}
VOID CreateBrushes()
{
INT i;
for (i = 1; i < MAX_ICOLOR; i++) {
if (pro.ahbr[i].syscolor) {
pro.ahbr[i].color = GetSysColor((INT)(pro.ahbr[i].syscolor));
}
pro.ahbr[i].hbr = CreateSolidBrush(pro.ahbr[i].color);
}
}
VOID DeleteBrushes()
{
INT i;
for (i = 1; i < MAX_ICOLOR; i++) {
DeleteObject(pro.ahbr[i].hbr);
}
}
//
// Window and ghost manipulation
//
VOID MoveGhosts(
INT dx,
INT dy)
{
INT i;
for (i = 0; i < cGhosts; i++) {
if (!(ghoststate[i].style & WISF_FIXED)) {
OffsetRect(&ghoststate[i].rc, dx, dy);
}
}
OffsetRect(&rcrMS, dx, dy);
}
INT FindIndexFromHwnd(
HWND hwnd)
{
INT iReal;
for (iReal = 0; iReal < cWindows; iReal++) {
if (winstate[iReal].hwnd == hwnd) {
return(iReal);
}
}
return(-1);
}
VOID MyMoveWindow(
HWND hwnd,
INT iLeft,
INT iTop,
INT cx,
INT cy)
{
int iReal;
RECT rc;
if (!(GetWindowLong(hwnd, GWL_STYLE) & WS_MINIMIZE)) {
Working(&rc);
for (iReal = 0; iReal < cWindows; iReal++) {
if (winstate[iReal].hwnd == hwnd) {
SetRect(&winstate[iReal].rc, iLeft, iTop, iLeft + cx, iTop + cy);
MoveWindow(hwnd, iLeft, iTop, cx, cy, TRUE);
break;
}
}
InvalidateRect(hwndTopdesk, &rc, FALSE);
}
}
VOID MoveChildren(
INT cx,
INT cy)
{
HDWP hdwp;
INT i;
RECT rc;
if (cx == 0 && cy == 0) {
return;
}
hdwp = BeginDeferWindowPos(MAX_CHILDREN);
if (hdwp == NULL) {
return;
}
Working(&rc);
for (i = 0; i < cWindows; i++) {
if (!(winstate[i].style & (WISF_FIXED | WS_MINIMIZE)) &&
winstate[i].hwnd != hwndTopdesk &&
IsWindow(winstate[i].hwnd)) {
OffsetRect(&winstate[i].rc, cx, cy);
hdwp = DeferWindowPos(hdwp, winstate[i].hwnd, (HWND)0,
winstate[i].rc.left, winstate[i].rc.top, 0, 0,
SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER);
InvalidateRect(hwndTopdesk, &rc, FALSE);
}
}
EndDeferWindowPos(hdwp);
MoveGhosts(cx, cy);
if (pro.fRelative) {
oxrHDT += cx; // relative keeps CDT in center
oyrHDT += cy;
} else {
oxrCDT -= cx; // absolute keeps HDT in center
oyrCDT -= cy;
}
InvalidateRect(hwndTopdesk, NULL, TRUE);
}
VOID GatherWindow(
INT iReal)
{
RECT rc;
if (winstate[iReal].hwnd != hwndTopdesk) {
if (RectInRect(&winstate[iReal].rc, &rcrDT)) {
return;
}
/*
* bring top-center of window onto desktop.
*/
while (((winstate[iReal].rc.left +
winstate[iReal].rc.right) / 2) > cxrDT) {
winstate[iReal].rc.left -= cxrDT;
winstate[iReal].rc.right -= cxrDT;
}
while (((winstate[iReal].rc.left +
winstate[iReal].rc.right) / 2) < 0) {
winstate[iReal].rc.left += cxrDT;
winstate[iReal].rc.right += cxrDT;
}
while (winstate[iReal].rc.top + 8 > cyrDT) {
winstate[iReal].rc.top -= cyrDT;
winstate[iReal].rc.bottom -= cyrDT;
}
while (winstate[iReal].rc.top + 8 < 0) {
winstate[iReal].rc.top += cyrDT;
winstate[iReal].rc.bottom += cyrDT;
}
Working(&rc);
MoveWindow(winstate[iReal].hwnd,
winstate[iReal].rc.left, winstate[iReal].rc.top,
winstate[iReal].rc.right - winstate[iReal].rc.left,
winstate[iReal].rc.bottom - winstate[iReal].rc.top,
TRUE);
InvalidateRect(hwndTopdesk, &rc, FALSE);
}
}
VOID GatherWindows()
{
INT i;
for (i = 0; i < cWindows; i++) {
GatherWindow(i);
}
}
VOID DeleteGhostWindow(
INT iGhost)
{
INT j;
if (pro.iShowGhosts) {
InvalidateRect(hwndTopdesk, NULL, TRUE);
}
if (ghoststate[iGhost].style & WISF_LINKED) {
for (j = 0; j < cWindows; j++) {
if (ghoststate[iGhost].hwnd == winstate[j].hwnd) {
winstate[j].style &= ~WISF_LINKED;
}
}
}
cGhosts--;
if (iGhost < cGhosts) {
memmove(&ghoststate[iGhost], &ghoststate[iGhost + 1],
sizeof(WINSTATE) * (cGhosts - iGhost));
}
SaveGhostState();
}
VOID ModifyTitle(
LPTSTR pstr)
{
LPTSTR pch;
INT cch;
//
// first strip off anything with and including TEXT(" - "), TEXT("["), or TEXT("(")
//
pch = _tcsstr(pstr, TEXT(" - "));
if (pch != NULL) {
*pch = TEXT('\0');
}
pch = _tcschr(pstr, TEXT('['));
if (pch != NULL) {
*pch = TEXT('\0');
}
pch = _tcschr(pstr, TEXT('('));
if (pch != NULL) {
*pch = TEXT('\0');
}
//
// remove trailing spaces
//
pch = pstr + _tcslen(pstr);
while (*(--pch) == TEXT(' ') && pch >= pstr) {
*pch = TEXT('\0');
}
//
// strip out any file extension or path name
//
cch = _tcslen(pstr);
pch = pstr + cch;
while (cch-- > 0) {
switch(*pch) {
case TEXT('.'):
/* get rid of extension */
*pch = TEXT('\0');
break;
case TEXT('\\'):
case TEXT('/':)
case TEXT(':':)
/* found end of path or drive name, move root portion
to start of scScratch */
_tcscpy(pstr,pch + 1);
/* and get out of here */
cch = 0;
}
pch--;
}
}
VOID GetModifiedWindowTitle(
HWND hwnd,
LPTSTR pstr) // ASSUME size == MAX_SZTITLE!
{
if (!GetWindowText(hwnd, pstr, MAX_SZTITLE)) {
*pstr = TEXT('\0');
return;
}
pstr[MAX_SZTITLE - 1] = TEXT('\0');
ModifyTitle(pstr);
return;
}
DWORD UpdateState(
WINSTATE *pws,
HWND hwnd)
{
TCHAR szTitle[MAX_SZTITLE];
RECT rc;
DWORD fChanged = 0;
DWORD style;
if (!IsWindow(hwnd)) {
return(FALSE);
}
//
// update database info - preserving any custom style flags.
//
if (pws->hwnd != hwnd) {
fChanged |= 1;
pws->hwnd = hwnd;
}
GetWindowRect(hwnd, &rc);
if (!EqualRect(&rc, &pws->rc)) {
fChanged |= 1;
pws->rc = rc;
}
style = (GetWindowLong(hwnd, GWL_STYLE) & WS_TRACKEDSTYLES) |
(pws->style & WISF_CUSTOMSTYLES);
if (style != pws->style) {
fChanged |= 1;
pws->style = style;
}
GetModifiedWindowTitle(hwnd, szTitle);
szTitle[MAX_SZTITLE - 1] = TEXT('\0');
if (_tcscmp(pws->szTitle, szTitle)) {
fChanged |= 2;
_tcscpy(pws->szTitle, szTitle);
}
return(fChanged);
}
INT FindLinkableGhost(
INT iReal)
{
INT iGhost;
if (!IsWindow(winstate[iReal].hwnd)) {
return(-1);
}
//
// Try iStartGhost first - this way multiple ghosts with the same
// name don't fool us.
//
if (iStartGhost != -1 && ghoststate[iStartGhost].hwnd == 0) {
DPRINTF((hfDbgOut, "IsLinkableStartGhost(%ls, %ls) ",
ghoststate[iStartGhost].szTitle, winstate[iReal].szTitle));
if (!_tcsicmp(ghoststate[iStartGhost].szTitle, winstate[iReal].szTitle)) {
DPRINTF((hfDbgOut, "matched.\n"));
iGhost = iStartGhost;
iStartGhost = -1;
return(iGhost);
} else {
DPRINTF((hfDbgOut, "did not match.\n"));
}
}
for (iGhost = 0; iGhost < cGhosts; iGhost++) {
if (ghoststate[iGhost].hwnd == 0) {
DPRINTF((hfDbgOut, "IsLinkableGhost(%ls, %ls) ",
ghoststate[iGhost].szTitle, winstate[iReal].szTitle));
if (!_tcsicmp(ghoststate[iGhost].szTitle, winstate[iReal].szTitle)) {
DPRINTF((hfDbgOut, "matched.\n"));
return(iGhost);
} else {
DPRINTF((hfDbgOut, "did not match.\n"));
}
}
}
return(-1);
}
INT FindLinkedGhost(
INT iReal)
{
INT iGhost;
if (!IsWindow(winstate[iReal].hwnd)) {
return(-1);
}
for (iGhost = 0; iGhost < cGhosts; iGhost++) {
if (ghoststate[iGhost].hwnd == winstate[iReal].hwnd) {
return(iGhost);
}
}
return(-1);
}
VOID Unlink(
INT iReal,
INT iGhost)
{
winstate[iReal].style &= ~WISF_LINKED;
ghoststate[iGhost].style &= ~WISF_LINKED;
ghoststate[iGhost].hwnd = 0;
}
INT FindLinkedReal(
INT iGhost)
{
INT iReal;
for (iReal = 0; iReal < cWindows; iReal++) {
if (ghoststate[iGhost].hwnd == winstate[iReal].hwnd) {
if (IsWindow(winstate[iReal].hwnd)) {
return(iReal);
} else {
Unlink(iReal, iGhost);
return(-1);
}
}
}
return(-1);
}
VOID LinkWindows(
INT iReal,
INT iGhost,
BOOL fSnapGhost)
{
winstate[iReal].style |= WISF_LINKED;
ghoststate[iGhost].style |= WISF_LINKED;
ghoststate[iGhost].hwnd = winstate[iReal].hwnd;
_tcscpy(ghoststate[iGhost].szTitle, winstate[iReal].szTitle);
if (fSnapGhost) {
ghoststate[iGhost] = winstate[iReal];
}
}
INT DistributeWindow(
INT iReal,
INT iGhost)
{
RECT rc;
if (iReal == -1) {
iReal = FindLinkedReal(iGhost);
}
if (iGhost == -1) {
iGhost = FindLinkedGhost(iReal);
}
if (iGhost == -1) {
return(iReal);
}
//
// If there is a difference between the linked ghost state and
// the window state, make them match.
//
if ((winstate[iReal].style ^ ghoststate[iGhost].style) &
(WS_MINIMIZE | WS_MAXIMIZE)) {
if (winstate[iReal].style & WS_MINIMIZE) {
// this is so DOS windows do the right thing
SendMessage(winstate[iReal].hwnd, WM_LBUTTONDBLCLK, 0, 0);
}
if (ghoststate[iGhost].style & WS_MINIMIZE) {
SendMessage(winstate[iReal].hwnd, WM_SYSCOMMAND, SC_MINIMIZE, 0);
} else if (ghoststate[iGhost].style & WS_MAXIMIZE) {
SendMessage(winstate[iReal].hwnd, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
} else {
SendMessage(winstate[iReal].hwnd, WM_SYSCOMMAND, SC_RESTORE, 0);
}
}
winstate[iReal].style = ghoststate[iGhost].style;
//
// move the real window to where the ghost is.
//
Working(&rc);
MyMoveWindow(winstate[iReal].hwnd, ghoststate[iGhost].rc.left,
ghoststate[iGhost].rc.top,
ghoststate[iGhost].rc.right - ghoststate[iGhost].rc.left,
ghoststate[iGhost].rc.bottom - ghoststate[iGhost].rc.top);
InvalidateRect(hwndTopdesk, &rc, FALSE);
return(iReal);
}
INT FindRealLink(
INT iGhost)
{
INT iReal;
if (!ghoststate[iGhost].hwnd) {
return(-1);
}
for (iReal = 0; iReal < cWindows; iReal++) {
if (winstate[iReal].hwnd == ghoststate[iGhost].hwnd) {
return(iReal);
}
}
return(-1);
}
VOID GetBestGuessRect(
PRECT prcOut,
WINSTATE *pws)
{
GetWindowRect(pws->hwnd, &pws->rc);
*prcOut = pws->rc;
}
/*
* The critical point of a rectangle is that point which TopDesk uses
* to determine what desktop the window is on.
*/
VOID GetCriticalPoint(
PRECT prc,
int *px,
int *py)
{
*px = (prc->left + prc->right) / 2;
if (prc->bottom - prc->top > cyrDT) {
*py = (prc->top + prc->bottom) / 2;
} else {
*py = prc->top + GetSystemMetrics(SM_CYCAPTION) / 2;
}
}
BOOL IsCriticalPointOnDesktop(
PRECT prc)
{
POINT pt;
GetCriticalPoint(prc, &pt.x, &pt.y);
return(PtInRect(&rcrDT, pt));
}
BOOL APIENTRY RefreshEnumProc(
HWND hwnd,
LONG l)
{
INT j;
BOOL fNew = FALSE;
RECT rc;
WINSTATE winstateT;
DWORD StateChanges;
TCHAR szClass[30];
l;
if (iRefresh >= MAX_REMEMBER - 1) {
iRefresh++;
return(FALSE); // overflow
}
if (!IsWindow(hwnd)) {
return(TRUE);
}
if (!IsWindowVisible(hwnd)) {
return(TRUE); // don't remember invisible windows
}
GetWindowRect(hwnd, &rc);
if (IsRectEmpty(&rc)) {
return(TRUE); // don't remember 0 sized windows
}
if (GetWindowTextLength(hwnd) == 0) { // skip empty title windows too.
return(TRUE);
}
/*
* Skip the vslick owner window - its real trouble.
*/
GetClassName(hwnd, szClass, sizeof(szClass) / sizeof(szClass[0]));
if (!_tcscmp(szClass, TEXT("Visual SlickEdit"))) {
return(TRUE);
}
/*
* If we are runing with the cairo shell, don't show the full screen
* sized program manager window. (which draws the icons for the new
* shell and handles DDE.) We will still accept progman windows that
* aren't the size of the desktop because the person could be runing
* progman at the same time. (like me)
*/
if (fCairoShell) {
static TCHAR szProgman[] = TEXT("Program Manager");
TCHAR szBuf[25];
RECT rc;
GetClientRect(hwnd, &rc);
if (GetWindowText(hwnd, szBuf, sizeof(szBuf) / sizeof(TCHAR)) &&
!_tcscmp(szBuf, szProgman) &&
EqualRect(&rc, &rcrDT)) {
return(TRUE);
}
}
if ((iRefresh >= cWindows || winstate[iRefresh].hwnd != hwnd)) {
//
// Something has changed or been added.
//
fInvalidated = TRUE;
fNew = TRUE;
for (j = iRefresh + 1; j < cWindows; j++) {
if (j < MAX_REMEMBER) {
//
// see if it was a Z-order change
//
if (winstate[j].hwnd == hwnd) {
//
// yes it was... its not new, just swap.
//
fNew = FALSE;
winstateT = winstate[j];
winstate[j] = winstate[iRefresh];
winstate[iRefresh] = winstateT;
break;
}
}
}
if (fNew) {
if (iRefresh < (cWindows - 1)) {
/*
* new window - make room
*/
memmove(&winstate[iRefresh + 1], &winstate[iRefresh],
sizeof(WINSTATE) * (cWindows - iRefresh));
}
if (cWindows < MAX_REMEMBER) {
cWindows++;
}
winstate[iRefresh].style = 0; // clear custom flags.
if (pszSetTitle != NULL) {
SetWindowText(hwnd, pszSetTitle);
pszSetTitle = NULL;
}
}
}
StateChanges = UpdateState(&winstate[iRefresh], hwnd);
if (StateChanges) {
/*
* If there is no ghost associated with this window then set
* fNew so we can link it to a ghost if its name changed
* during startup. (ex. WinHelp alters its name on startup
* and will not link to a ghost under certain timing conditions.
*/
if ((StateChanges & 2) && FindLinkedGhost(iRefresh) == -1) {
fNew = TRUE;
}
fInvalidated = TRUE;
}
if (fNew) {
/*
* 2 hacks:
* 1) Make topdesk's help window automatically locked.
* 2) vslick uses an off-screen owner window that will move
* with its ownee. If we move the ownee, the owner
* will move and then when we move the owner, the ownee
* will move again, so we always lock the ownee.
*/
if (!_tcscmp(winstate[iRefresh].szTitle, pszTopdeskHelpTitle)
// || !_tcscmp(TEXT("vs_mdiframe"), szClass)
)
{
winstate[iRefresh].style |= WISF_FIXED;
}
}
//
// See if we can associate an unlinked ghost window with this.
// If so, make the real window adapt to match the ghost. (auto place)
// if pro.fDistOnStart is set.
//
if (fNew && hwnd != hwndTopdesk) {
j = FindLinkableGhost(iRefresh);
if (j > -1) {
LinkWindows(iRefresh, j, FALSE);
if (pro.fDistOnStart) {
if (ihwndJump == -1) {
ihwndJump = DistributeWindow(iRefresh, j);
} else if (ihwndJump == -2) {
//
// this is so at startup the windows get distributed but
// the desktop doesn't jump around.
//
DistributeWindow(iRefresh, j);
}
}
}
}
/*
* See if the top window is on the screen. If not, we need to jump.
* This is a hack so that CMD windows, which cannot be hooked, will
* be jumped to when focus changes.
*/
if (iRefresh == 0 && ihwndJump == -1) {
int i;
HWND hwndForeground = GetForegroundWindow();
/*
* because of WM_TOPMOST, the top window may not have the focus
* so make sure we have the right one.
*/
if (hwndForeground) {
for (i = 0; i < MAX_REMEMBER; i++) {
if (winstate[i].hwnd && IsChild(winstate[i].hwnd, hwndForeground)) {
GetBestGuessRect(&rc, &winstate[i]);
if (!IsCriticalPointOnDesktop(&rc)) {
ihwndJump = i;
}
}
}
}
}
iRefresh++;
return(TRUE);
}
VOID JerkDesktop(
INT xr,
INT yr,
HWND hwndFocus,
INT iReal)
{
VOID RefreshWinState(VOID);
RECT rc;
Working(&rc);
if (hwndFocus) {
#ifdef WIN16
SetActiveWindow(hwndFocus);
#else // WIN32
SetForegroundWindow(hwndFocus);
#endif // WIN16
GetWindowRect(hwndFocus, &rc);
GetCriticalPoint(&rc, &xr, &yr);
}
xr -= (xr + cxrDT * nxVDT) % cxrDT;
yr -= (yr + cyrDT * nyVDT) % cyrDT;
if (xr || yr) {
MoveChildren(-xr, -yr);
} else {
InvalidateRect(hwndTopdesk, &rc, FALSE);
}
}
VOID RefreshWinState()
{
INT i, j;
RECT rc;
if (fBlockRefresh) {
return;
}
fInvalidated = FALSE;
if (cWindows == 0) {
ihwndJump = -2;
} else {
ihwndJump = -1; // RefreshEnumProc will set this if a new one is found.
}
iRefresh = 0;
EnumWindows((WNDENUMPROC)fpRefreshEnumProc, 0);
if (iRefresh != cWindows && iRefresh < MAX_REMEMBER) {
fInvalidated = TRUE;
cWindows = iRefresh;
}
//
// Remove any ghost links where the real window died.
//
for (i = 0; i < cGhosts; i++) {
j = FindRealLink(i);
if (j == -1) {
ghoststate[i].hwnd = 0;
ghoststate[i].style &= ~WISF_LINKED;
}
}
//
// If any new windows were discovered and were linked, jump to the first one found.
//
if (ihwndJump > -1) {
int x, y;
//
// Jerk the desktop to the new window.
//
GetBestGuessRect(&rc, &winstate[ihwndJump]);
GetCriticalPoint(&rc, &x, &y);
JerkDesktop(x, y, 0, -1);
fInvalidated = TRUE;
}
if (fInvalidated) {
InvalidateRect(hwndTopdesk, NULL, TRUE);
}
}
VOID ToggleFrameCtrls()
{
DWORD dwStyle;
INT mfT ;
mfT = pro.mfx; // swap these so that when frame controls
pro.mfx = pro.mfxAlt; // are changed we revert back to what we
pro.mfxAlt = mfT; // last had before recalcing.
mfT = pro.mfy;
pro.mfy = pro.mfyAlt;
pro.mfyAlt = mfT;
fFrameToggleSize = TRUE; // so WM_SIZE recalc is bypassed.
dwStyle = GetWindowLong(hwndTopdesk, GWL_STYLE);
pro.fShowFrameCtrls = !pro.fShowFrameCtrls;
if (pro.fShowFrameCtrls) {
SetWindowLong(hwndTopdesk, GWL_STYLE, dwStyle | WS_THICKFRAME | WS_DLGFRAME);
SetMenu(hwndTopdesk, hMenuTopdesk);
} else {
SetWindowLong(hwndTopdesk, GWL_STYLE, dwStyle & ~(WS_THICKFRAME | WS_DLGFRAME));
hMenuTopdesk = GetMenu(hwndTopdesk);
SetMenu(hwndTopdesk, NULL);
}
}
HWND GetTopAppHwnd()
{
int i;
POINT pt;
RECT rc;
//
// return the topmost window who's centerpoint lies within the current
// desktop. (skip topdesk itself)
//
for (i = 0; i < cWindows; i++) {
if (winstate[i].hwnd == hwndTopdesk)
continue;
GetBestGuessRect(&rc, &winstate[i]);
pt.x = (rc.left + rc.right) / 2;
pt.y = (rc.top + rc.bottom) / 2;
if (PtInRect(&rcrDT, pt)) {
return(winstate[i].hwnd);
}
}
return(0);
}
VOID AlignWindow(
HWND hwnd,
BOOL fLeft,
BOOL fRight,
BOOL fTop,
BOOL fBottom)
{
RECT rc;
RECT rcClient;
int x, y;
LONG lStyle;
if (hwnd == 0) {
return;
}
GetWindowRect(hwnd, &rc);
GetClientRect(hwnd, &rcClient);
x = rc.left;
if (fLeft) {
x = 0;
} else if (fRight) {
x = cxrDT - (rc.right - rc.left);
}
y = rc.top;
if (fTop) {
y = 0;
} else if (fBottom) {
y = cyrDT - (rc.bottom - rc.top);
}
lStyle = GetWindowLong(hwnd, GWL_STYLE);
if (lStyle & WS_MAXIMIZE) {
if (lStyle & WS_THICKFRAME) {
if (cxrDT <= (rcClient.right - rcClient.left)) {
if (fLeft) {
x -= cxFrame;
} else if (fRight) {
x += cxFrame;
}
}
if (cyrDT <= (rcClient.bottom - rcClient.top)) {
if (fTop) {
y -= cyFrame;
} else if (fBottom) {
y += cyFrame;
}
}
}
}
MyMoveWindow(hwnd, x, y, rc.right - rc.left, rc.bottom - rc.top);
InvalidateRect(hwndTopdesk, NULL, TRUE);
}
VOID NewGhostWindow(
LPTSTR pszTitle)
{
MYSTARTUPINFO *psi;
if (cGhosts < MAX_REMEMBER) {
cGhosts++;
for (psi = pStartupInfo; psi != NULL; psi = psi->next) {
if (!_tcsicmp(psi->pszTitle, pszTitle)) {
break;
}
}
if (psi == NULL) {
CreateStartupInfo(pszTitle, TEXT(""), TEXT(""), FALSE);
}
}
}
VOID CALLBACK ResetGhostState(
HWND hwnd,
UINT msg,
UINT id,
DWORD time)
{
if (idResetGhostTimer) {
KillTimer(hwnd, idResetGhostTimer);
idResetGhostTimer = 0;
}
pro.iShowGhosts = PrevGhostState;
SaveGhostState();
InvalidateRect(hwndTopdesk, NULL, TRUE);
}
VOID SnapGhost(
INT i)
{
INT j;
if (winstate[i].hwnd == hwndTopdesk ||
winstate[i].style & WS_MINIMIZE) {
return;
}
//
// see if there exists a ghost we can link the window to.
//
if (!(winstate[i].style & WISF_LINKED)) {
for (j = 0; j < cGhosts; j++) {
if (ghoststate[j].hwnd == 0 &&
!_tcsicmp(ghoststate[j].szTitle, winstate[iRefresh].szTitle)
) {
//
// Link the ghost window with the real window and make the
// real window jump to the ghost's location and state.
//
winstate[iRefresh].style |= WISF_LINKED;
ghoststate[j].style |= WISF_LINKED;
ghoststate[j].hwnd = winstate[iRefresh].hwnd;
_tcscpy(ghoststate[j].szTitle, winstate[iRefresh].szTitle);
}
}
}
if (winstate[i].style & WISF_LINKED) {
//
// update ghost
//
for (j = 0; j < cGhosts; j++) {
if (ghoststate[j].hwnd == winstate[i].hwnd) {
ghoststate[j] = winstate[i];
ghoststate[j].rc = winstate[i].rc;
break;
}
}
} else {
//
// make a new ghost - don't snap minimized ghosts because we
// can't move them anyway.
//
if (winstate[i].hwnd != hwndTopdesk) {
NewGhostWindow(winstate[i].szTitle);
winstate[i].style |= WISF_LINKED;
ghoststate[cGhosts - 1] = winstate[i];
ghoststate[cGhosts - 1].rc = winstate[i].rc;
}
}
SaveGhostState();
PrevGhostState = pro.iShowGhosts;
pro.iShowGhosts = SG_ALL;
InvalidateRect(hwndTopdesk, NULL, TRUE);
if (!idResetGhostTimer) {
idResetGhostTimer = SetTimer(NULL, 0, 1000, ResetGhostState);
}
}
VOID SnapGhosts()
{
INT i;
INT OrgGhostState;
OrgGhostState = pro.iShowGhosts;
for (i = 0; i < cWindows; i++) {
SnapGhost(i);
}
PrevGhostState = OrgGhostState;
}
MYSTARTUPINFO *FindStartupInfo(
INT iGhost)
{
MYSTARTUPINFO *psi;
//
// Locate matching startup info.
//
psi = pStartupInfo;
while (psi != NULL &&
_tcsicmp(ghoststate[iGhost].szTitle, psi->pszTitle)) {
psi = psi->next;
}
if (psi == NULL) {
psi = CreateStartupInfo(ghoststate[iGhost].szTitle, TEXT(""), TEXT(""), FALSE);
}
return(psi);
}
BOOL CommandMsg(WORD cmd)
{
INT i;
INT iReal, iGhost;
FARPROC lpfp;
INT dx = 0, dy = 0;
switch (cmd) {
case CMD_ABSOLUTE_VIEW:
if (pro.fRelative) {
// Rel-> Abs - puts HDT into center
oxrCDT -= oxrHDT;
oyrCDT -= oyrHDT;
oxrHDT = 0;
oyrHDT = 0;
pro.fRelative = !pro.fRelative;
goto repaint;
}
break;
case CMD_RELATIVE_VIEW:
if (!pro.fRelative) {
// Abs -> Rel - puts CDT into center
oxrHDT -= oxrCDT;
oyrHDT -= oyrCDT;
oxrCDT = 0;
oyrCDT = 0;
pro.fRelative = !pro.fRelative;
goto repaint;
}
break;
case CMD_TOGGLE_FRM_CTRLS:
ToggleFrameCtrls();
goto repaint;
case CMD_TOGGLE_GHOSTS:
switch (pro.iShowGhosts) {
case SG_NONE:
pro.iShowGhosts = SG_ALL;
break;
case SG_ALL:
pro.iShowGhosts = SG_PARTIAL;
break;
case SG_PARTIAL:
pro.iShowGhosts = SG_NONE;
break;
}
goto repaint;
case CMD_HIDE_GHOSTS:
pro.iShowGhosts = SG_NONE;
goto repaint;
case CMD_SHOW_GHOSTS:
pro.iShowGhosts = SG_ALL;
goto repaint;
case CMD_PARTIAL_GHOSTS:
pro.iShowGhosts = SG_PARTIAL;
goto repaint;
case CMD_STARTUPINFO:
fStartingAnApp = FALSE;
StartStartupInfo(pStartupInfo, 0, FALSE);
break;
case CMD_MAGNIFY:
if (pro.mfx > 0) {
pro.mfx--;
}
if (pro.mfy > 0) {
pro.mfy--;
}
CalcConversionFactors(TRUE);
goto repaint;
case CMD_MAGNIFY_VERT:
if (pro.mfy > 0) {
pro.mfy--;
}
goto repaint;
case CMD_MAGNIFY_HORZ:
if (pro.mfx > 0) {
pro.mfx--;
}
goto repaint;
case CMD_REDUCE:
if (cycDT > cycDTmin) {
pro.mfy++;
}
if (cxcDT > cxcDTmin) {
pro.mfx++;
}
CalcConversionFactors(TRUE);
goto repaint;
case CMD_REDUCE_VERT:
if (cycDT > cycDTmin) {
pro.mfy++;
}
goto repaint;
case CMD_REDUCE_HORZ:
if (cxcDT > cxcDTmin) {
pro.mfx++;
}
goto repaint;
case CMD_SNAPSHOT:
SnapGhosts();
goto repaint;
case CMD_ERASEGHOSTS:
if (cGhosts == 0) {
break;
}
cGhosts = 0;
for (i = 0; i < cWindows; i++) {
winstate[i].style &= ~WISF_LINKED;
}
SaveGhostState();
goto repaint;
case CMD_GATHER:
CommandMsg(CMD_GOHOME);
GatherWindows();
break;
case CMDP_SETHOME: // we use a seperate constant to avoid
// WM_INITMENU processing for the popup one.
JerkDesktop(PopupPt.x, PopupPt.y, (HWND)0, -1);
case CMD_SETHOME:
oxrHDT = oxrCDT = 0;
oyrHDT = oyrCDT = 0;
goto repaint;
case CMD_LL_OF_HOME:
if (pro.mfx == 0 && pro.mfy != 0) { // VERT
dy = -cyrDT * 4;
} else if (pro.mfx != 0 && pro.mfy == 0) { // HORZ
dx = -cxrDT * 4;
} else {
dx = -cxrDT;
dy = cyrDT;
}
goto move_to_home;
case CMD_LC_OF_HOME:
if (pro.mfx == 0 && pro.mfy != 0) { // VERT
dy = -cyrDT * 3;
} else if (pro.mfx != 0 && pro.mfy == 0) { // HORZ
dx = -cxrDT * 3;
} else {
dy = cyrDT;
}
goto move_to_home;
case CMD_LR_OF_HOME:
if (pro.mfx == 0 && pro.mfy != 0) { // VERT
dy = -cyrDT * 2;
} else if (pro.mfx != 0 && pro.mfy == 0) { // HORZ
dx = -cxrDT * 2;
} else {
dx = cxrDT;
dy = cyrDT;
}
goto move_to_home;
case CMD_CL_OF_HOME:
if (pro.mfx == 0 && pro.mfy != 0) { // VERT
dy = -cyrDT;
} else if (pro.mfx != 0 && pro.mfy == 0) { // HORZ
dx = -cxrDT;
} else {
dx = -cxrDT;
}
goto move_to_home;
case CMD_CR_OF_HOME:
if (pro.mfx == 0 && pro.mfy != 0) { // VERT
dy = cyrDT;
} else if (pro.mfx != 0 && pro.mfy == 0) { // HORZ
dx = cxrDT;
} else {
dx = cxrDT;
}
goto move_to_home;
case CMD_UL_OF_HOME:
if (pro.mfx == 0 && pro.mfy != 0) { // VERT
dy = cyrDT * 2;
} else if (pro.mfx != 0 && pro.mfy == 0) { // HORZ
dx = cxrDT * 2;
} else {
dx = -cxrDT;
dy = -cyrDT;
}
goto move_to_home;
case CMD_UC_OF_HOME:
if (pro.mfx == 0 && pro.mfy != 0) { // VERT
dy = cyrDT * 3;
} else if (pro.mfx != 0 && pro.mfy == 0) { // HORZ
dx = cxrDT * 3;
} else {
dy = -cyrDT;
}
goto move_to_home;
case CMD_UR_OF_HOME:
if (pro.mfx == 0 && pro.mfy != 0) { // VERT
dy = cyrDT * 4;
} else if (pro.mfx != 0 && pro.mfy == 0) { // HORZ
dx = cxrDT * 4;
} else {
dx = cxrDT;
dy = -cyrDT;
}
goto move_to_home;
case CMD_DISTRIBUTE:
for (iReal = 0; iReal < cWindows; iReal++) {
if (winstate[iReal].style & WISF_LINKED) {
iGhost = FindLinkedGhost(iReal);
if (iGhost > -1) {
DistributeWindow(iReal, iGhost);
} else {
winstate[iReal].style &= ~WISF_LINKED;
}
} else {
iGhost = FindLinkableGhost(iReal);
if (iGhost > -1) {
LinkWindows(iReal, iGhost, FALSE);
DistributeWindow(iReal, iGhost);
}
}
}
// fall through to go home
case CMD_GOHOME:
dx = 0;
dy = 0;
move_to_home:
if (pro.fRelative) {
MoveChildren(-oxrHDT - dx, -oyrHDT - dy);
} else {
MoveChildren(oxrCDT - dx, oyrCDT - dy);
}
repaint:
InvalidateRect(hwndTopdesk, NULL, TRUE);
break;
case CMD_HELP:
WinHelp(hwndTopdesk, pszHelpFileName, HELP_INDEX, 0L);
break;
case CMD_COMMANDS:
WinHelp(hwndTopdesk, pszHelpFileName, HELP_INDEX, 3L);
break;
case CMD_EXIT:
WinHelp(hwndTopdesk, pszHelpFileName, HELP_QUIT, 0);
PostMessage(hwndTopdesk, WM_CLOSE, 0, 0L);
break;
case CMD_DTLEFT:
MoveChildren(cxrDT, 0);
break;
case CMD_DTRIGHT:
MoveChildren(-cxrDT, 0);
break;
case CMD_DTUP:
MoveChildren(0, cyrDT);
break;
case CMD_DTDOWN:
MoveChildren(0, -cyrDT);
break;
case CMD_MDLEFT:
AlignWindow(hwndTopdesk, 1, 0, 0, 0);
break;
case CMD_MDRIGHT:
AlignWindow(hwndTopdesk, 0, 1, 0, 0);
break;
case CMD_MDUP:
AlignWindow(hwndTopdesk, 0, 0, 1, 0);
break;
case CMD_MDDOWN:
AlignWindow(hwndTopdesk, 0, 0, 0, 1);
break;
case CMD_ALIGNLEFT:
AlignWindow(GetTopAppHwnd(), 1, 0, 0, 0);
break;
case CMD_ALIGNRIGHT:
AlignWindow(GetTopAppHwnd(), 0, 1, 0, 0);
break;
case CMD_ALIGNUP:
AlignWindow(GetTopAppHwnd(), 0, 0, 1, 0);
break;
case CMD_ALIGNDOWN:
AlignWindow(GetTopAppHwnd(), 0, 0, 0, 1);
break;
case CMD_ABOUT:
fBlockRefresh++;
lpfp = MakeProcInstance((FARPROC)AboutDlgProc, hInst);
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUT), hwndTopdesk, (DLGPROC)lpfp);
FreeProcInstance(lpfp);
fBlockRefresh--;
break;
case CMD_CONFIG:
fBlockRefresh++;
lpfp = MakeProcInstance((FARPROC)ConfigDlgProc, hInst);
DialogBox(hInst, MAKEINTRESOURCE(IDD_CONFIG), hwndTopdesk, (DLGPROC)lpfp);
FreeProcInstance(lpfp);
fBlockRefresh--;
break;
case CMDP_STARTUPINFO:
StartStartupInfo(FindStartupInfo(PopupGhostIndex), PopupGhostIndex, FALSE);
break;
case CMDP_DISTRIBUTE_GHOST:
DistributeWindow(-1, PopupGhostIndex);
InvalidateRect(hwndTopdesk, NULL, FALSE);
break;
case CMDP_DISTRIBUTE_REAL:
DistributeWindow(PopupRealIndex, -1);
InvalidateRect(hwndTopdesk, NULL, FALSE);
break;
case CMDP_START_GHOST:
StartGhostWindow(PopupGhostIndex);
break;
case CMDP_DESTROY_GHOST:
DeleteGhostWindow(PopupGhostIndex);
break;
case CMDP_UNLOCK_GHOST:
ghoststate[PopupGhostIndex].style &= ~WISF_FIXED;
SaveGhostState();
InvalidateRect(hwndTopdesk, NULL, FALSE);
break;
case CMDP_LOCK_GHOST:
ghoststate[PopupGhostIndex].style |= WISF_FIXED;
SaveGhostState();
InvalidateRect(hwndTopdesk, NULL, FALSE);
break;
case CMDP_JUMP_REAL:
JerkDesktop(PopupPt.x, PopupPt.y, PopuphwndFocus, PopupRealIndex);
break;
case CMDP_DESTROY_REAL:
SendMessage(winstate[PopupRealIndex].hwnd, WM_CLOSE, 0, 0);
break;
case CMDP_UNLOCK_REAL:
winstate[PopupRealIndex].style &= ~WISF_FIXED;
InvalidateRect(hwndTopdesk, NULL, FALSE);
break;
case CMDP_LOCK_REAL:
winstate[PopupRealIndex].style |= WISF_FIXED;
InvalidateRect(hwndTopdesk, NULL, FALSE);
break;
case CMDP_SNAPSHOT_REAL:
SnapGhost(PopupRealIndex);
break;
case CMDP_SNAPSHOT_GHOST:
SnapGhost(FindLinkedGhost(PopupGhostIndex));
break;
case CMDP_JUMP_DESKTOP:
JerkDesktop(PopupPt.x, PopupPt.y, (HWND)0, -1);
break;
case CMD_TOPMOST:
pro.fAlwaysOnTop = !pro.fAlwaysOnTop;
SetWindowPos(hwndTopdesk,
pro.fAlwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0,
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
break;
#ifdef DEBUG
case CMD_DUMP_ALL:
{
_ftprintf(hfDbgOut, TEXT("Globals:\n"));
_ftprintf(hfDbgOut, TEXT("\tfBlockRefresh = %d\n"), fBlockRefresh);
_ftprintf(hfDbgOut, TEXT("\tfFrameToggleSize = %d\n"), fFrameToggleSize);
_ftprintf(hfDbgOut, TEXT("\tfInvalidated = %d\n"), fInvalidated);
_ftprintf(hfDbgOut, TEXT("\tfStarted = %d\n"), fStarted);
_ftprintf(hfDbgOut, TEXT("\thwndFocus = %lx\n"), hwndFocus);
_ftprintf(hfDbgOut, TEXT("\tiStartGhost = %d\n"), iStartGhost);
_ftprintf(hfDbgOut, TEXT("\tcGhosts = %d\n"), cGhosts);
_ftprintf(hfDbgOut, TEXT("\tcWindows = %d\n"), cWindows);
_ftprintf(hfDbgOut, TEXT("\tcxc = %d\n"), cxc);
_ftprintf(hfDbgOut, TEXT("\tcxcDT = %d\n"), cxcDT);
_ftprintf(hfDbgOut, TEXT("\tcxcDTmin = %d\n"), cxcDTmin);
_ftprintf(hfDbgOut, TEXT("\tcxFrame = %d\n"), cxFrame);
_ftprintf(hfDbgOut, TEXT("\tcxrDT = %d\n"), cxrDT);
_ftprintf(hfDbgOut, TEXT("\tcyc = %d\n"), cyc);
_ftprintf(hfDbgOut, TEXT("\tcycDT = %d\n"), cycDT);
_ftprintf(hfDbgOut, TEXT("\tcycDTmin = %d\n"), cycDTmin);
_ftprintf(hfDbgOut, TEXT("\tcyFrame = %d\n"), cyFrame);
_ftprintf(hfDbgOut, TEXT("\tcyrDT = %d\n"), cyrDT);
_ftprintf(hfDbgOut, TEXT("\tiRefresh = %d\n"), iRefresh);
_ftprintf(hfDbgOut, TEXT("\tihwndJump = %d\n"), ihwndJump);
_ftprintf(hfDbgOut, TEXT("\tnxVDT = %d\n"), nxVDT);
_ftprintf(hfDbgOut, TEXT("\tnyVDT = %d\n"), nyVDT);
_ftprintf(hfDbgOut, TEXT("\toxcODT = %d\n"), oxcODT);
_ftprintf(hfDbgOut, TEXT("\toxrCDT = %d\n"), oxrCDT);
_ftprintf(hfDbgOut, TEXT("\toxrHDT = %d\n"), oxrHDT);
_ftprintf(hfDbgOut, TEXT("\toycODT = %d\n"), oycODT);
_ftprintf(hfDbgOut, TEXT("\toyrCDT = %d\n"), oyrCDT);
_ftprintf(hfDbgOut, TEXT("\toyrHDT = %d\n"), oyrHDT);
_ftprintf(hfDbgOut, TEXT("\trcrDT = %d\n"), rcrDT);
_ftprintf(hfDbgOut, TEXT("\trcrMS = %d\n"), rcrMS);
_ftprintf(hfDbgOut, TEXT("\tpro.fShift = %d\n"), pro.fShift);
_ftprintf(hfDbgOut, TEXT("\tpro.fAlt = %d\n"), pro.fAlt);
_ftprintf(hfDbgOut, TEXT("\tpro.fControl = %d\n"), pro.fControl);
_ftprintf(hfDbgOut, TEXT("\tpro.vkey = %d\n"), pro.vkey);
_ftprintf(hfDbgOut, TEXT("\tpro.mfx = %d\n"), pro.mfx);
_ftprintf(hfDbgOut, TEXT("\tpro.mfy = %d\n"), pro.mfy);
_ftprintf(hfDbgOut, TEXT("\tpro.mfxAlt = %d\n"), pro.mfxAlt);
_ftprintf(hfDbgOut, TEXT("\tpro.mfyAlt = %d\n"), pro.mfyAlt);
_ftprintf(hfDbgOut, TEXT("\tpro.x = %d\n"), pro.x);
_ftprintf(hfDbgOut, TEXT("\tpro.y = %d\n"), pro.y);
_ftprintf(hfDbgOut, TEXT("\tpro.cx = %d\n"), pro.cx);
_ftprintf(hfDbgOut, TEXT("\tpro.cy = %d\n"), pro.cy);
_ftprintf(hfDbgOut, TEXT("\tpro.iShowGhosts = %d\n"), pro.iShowGhosts);
_ftprintf(hfDbgOut, TEXT("\tpro.fRelative = %d\n"), pro.fRelative);
_ftprintf(hfDbgOut, TEXT("\tpro.fDistOnStart = %d\n"), pro.fDistOnStart);
_ftprintf(hfDbgOut, TEXT("\tpro.fShowFrameCtrls = %d\n"), pro.fShowFrameCtrls);
_ftprintf(hfDbgOut, TEXT("\tpro.fAutoAdj = %d\n"), pro.fAutoAdj);
_ftprintf(hfDbgOut, TEXT("\tpro.fAlwaysOnTop = %d\n"), pro.fAlwaysOnTop);
_ftprintf(hfDbgOut, TEXT("winstate:\n"));
for (i = 0; i < cWindows; i++) {
_ftprintf(hfDbgOut, TEXT(" (%d)\n"), i);
_ftprintf(hfDbgOut, TEXT(" rc = (%d - %d, %d - %d)\n"),
winstate[i].rc.left,
winstate[i].rc.right,
winstate[i].rc.top,
winstate[i].rc.bottom
);
_ftprintf(hfDbgOut, TEXT(" style = %lx\n"), winstate[i].style);
_ftprintf(hfDbgOut, TEXT(" hwnd = %lx\n"), winstate[i].hwnd);
_ftprintf(hfDbgOut, TEXT(" title = %s\n"), winstate[i].szTitle);
}
_ftprintf(hfDbgOut, TEXT("ghoststate:\n"));
for (i = 0; i < cGhosts; i++) {
_ftprintf(hfDbgOut, TEXT(" (%d)\n"), i);
_ftprintf(hfDbgOut, TEXT(" rc = (%d - %d, %d - %d)\n"),
ghoststate[i].rc.left,
ghoststate[i].rc.right,
ghoststate[i].rc.top,
ghoststate[i].rc.bottom
);
_ftprintf(hfDbgOut, TEXT(" style = %lx\n"), ghoststate[i].style);
_ftprintf(hfDbgOut, TEXT(" hwnd = %lx\n"), ghoststate[i].hwnd);
_ftprintf(hfDbgOut, TEXT(" title = %s\n"), ghoststate[i].szTitle);
}
}
break;
#endif // DEBUG
default:
return(FALSE);
break;
}
RefreshWinState();
return(TRUE);
}
VOID MyDrawText(
HDC hdc,
LPTSTR psz,
LPRECT prc,
LONG clrFgnd,
LONG clrBkgnd,
WORD flCmd)
{
SetTextColor(hdc, pro.ahbr[clrFgnd].color);
SetBkColor(hdc, pro.ahbr[clrBkgnd].color);
DrawText(hdc, psz, -1, prc, flCmd);
}
/*
* maps a normal window rect (in desktop coordinates) to the proper size
* for the topdesk client and draws it.
*/
VOID DrawWindowRect(
HWND hwnd,
PRECT prc,
DWORD FillColor,
DWORD FrameColor,
BOOL fMaximized)
{
TCHAR sz[MAX_SZTITLE];
rRect2cRect(prc);
if (FillColor)
FillRect(hdcDraw, prc, pro.ahbr[FillColor].hbr);
GetModifiedWindowTitle(hwnd, sz);
InflateRect(prc, -2, -2);
MyDrawText(hdcDraw, sz, prc, WINDOWTEXT, FillColor,
DT_LEFT | DT_TOP | DT_WORDBREAK);
if (fMaximized) {
MyDrawText(hdcDraw, GetResString(IDS_MAX), prc, WINDOWTEXT, FillColor,
DT_LEFT | DT_BOTTOM | DT_SINGLELINE);
}
InflateRect(prc, 2, 2);
FrameRect(hdcDraw, prc, pro.ahbr[FrameColor].hbr);
}
VOID DottedLine(
HDC hdc,
INT x1,
INT y1,
INT x2,
INT y2,
DWORD color)
{
HPEN hPenSave, hPen;
hPen = CreatePen(PS_DOT, 1, pro.ahbr[color].color);
hPenSave = SelectObject(hdc, hPen);
MoveToEx(hdc, x1, y1, NULL);
LineTo(hdc, x2, y2);
DeleteObject(SelectObject(hdc, hPenSave));
}
VOID TopDeskPaint(
HDC hdc,
RECT rc)
{
RECT rcChild;
INT x, y;
INT i;
HFONT hfOld;
hdcDraw = hdc;
hfOld = SelectObject(hdc, hMyFont);
SetBkMode(hdc, TRANSPARENT);
cxc = rc.right;
cyc = rc.bottom;
CalcConversionFactors(FALSE);
FillRect(hdc, &rc, pro.ahbr[SPACECOLOR].hbr);
if (pro.mfx > 0) {
for (x = oxcODT; x < cxc; x += cxcDT) {
DottedLine(hdc, x, 0, x, cyc, GRIDCOLOR);
}
for (x = oxcODT - cxcDT; x > 0; x -= cxcDT) {
DottedLine(hdc, x, 0, x, cyc, GRIDCOLOR);
}
}
if (pro.mfy > 0) {
for (y = oycODT; y < cyc; y += cycDT) {
DottedLine(hdc, 0, y, cxc, y, GRIDCOLOR);
}
for (y = oycODT - cycDT ; y > 0; y -= cycDT) {
DottedLine(hdc, 0, y, cxc, y, GRIDCOLOR);
}
}
rcChild = rcrDT;
DrawWindowRect(hwndDT, &rcChild, DESKFILLCOLOR, DESKFILLCOLOR, FALSE);
rcChild = rcrDT;
if (pro.fRelative) {
OffsetRect(&rcChild, oxrHDT, oyrHDT);
} else {
OffsetRect(&rcChild, -oxrCDT, -oyrCDT);
}
DrawWindowRect(hwndDT, &rcChild, 0L, DESKFRAMECOLOR, FALSE);
InflateRect(&rcChild, -1, -1);
FrameRect(hdcDraw, &rcChild, pro.ahbr[DESKFRAMECOLOR].hbr);
InflateRect(&rcChild, -1, -1);
MyDrawText(hdcDraw, TEXT("5"), &rcChild, GRIDCOLOR, SPACECOLOR, DT_RIGHT | DT_BOTTOM | DT_SINGLELINE);
if (pro.mfx == 0 && pro.mfy != 0) { // Vert
OffsetRect(&rcChild, 0, -cycDT);
} else if (pro.mfx != 0 && pro.mfy == 0) { // Horz
OffsetRect(&rcChild, -cxcDT, 0);
} else {
OffsetRect(&rcChild, -cxcDT, 0);
}
MyDrawText(hdcDraw, TEXT("4"), &rcChild, GRIDCOLOR, SPACECOLOR, DT_RIGHT | DT_BOTTOM | DT_SINGLELINE);
if (pro.mfx == 0 && pro.mfy != 0) { // Vert
OffsetRect(&rcChild, 0, cycDT * 3);
} else if (pro.mfx != 0 && pro.mfy == 0) { // Horz
OffsetRect(&rcChild, cxcDT * 3, 0);
} else {
OffsetRect(&rcChild, 0, -cycDT);
}
MyDrawText(hdcDraw, TEXT("7"), &rcChild, GRIDCOLOR, SPACECOLOR, DT_RIGHT | DT_BOTTOM | DT_SINGLELINE);
if (pro.mfx == 0 && pro.mfy != 0) { // Vert
OffsetRect(&rcChild, 0, cycDT);
} else if (pro.mfx != 0 && pro.mfy == 0) { // Horz
OffsetRect(&rcChild, cxcDT, 0);
} else {
OffsetRect(&rcChild, cxcDT, 0);
}
MyDrawText(hdcDraw, TEXT("8"), &rcChild, GRIDCOLOR, SPACECOLOR, DT_RIGHT | DT_BOTTOM | DT_SINGLELINE);
if (pro.mfx == 0 && pro.mfy != 0) { // Vert
OffsetRect(&rcChild, 0, cycDT);
} else if (pro.mfx != 0 && pro.mfy == 0) { // Horz
OffsetRect(&rcChild, cxcDT, 0);
} else {
OffsetRect(&rcChild, cxcDT, 0);
}
MyDrawText(hdcDraw, TEXT("9"), &rcChild, GRIDCOLOR, SPACECOLOR, DT_RIGHT | DT_BOTTOM | DT_SINGLELINE);
if (pro.mfx == 0 && pro.mfy != 0) { // Vert
OffsetRect(&rcChild, 0, -cycDT * 3);
} else if (pro.mfx != 0 && pro.mfy == 0) { // Horz
OffsetRect(&rcChild, -cxcDT * 3, 0);
} else {
OffsetRect(&rcChild, 0, cycDT);
}
MyDrawText(hdcDraw, TEXT("6"), &rcChild, GRIDCOLOR, SPACECOLOR, DT_RIGHT | DT_BOTTOM | DT_SINGLELINE);
if (pro.mfx == 0 && pro.mfy != 0) { // Vert
OffsetRect(&rcChild, 0, -cycDT * 3);
} else if (pro.mfx != 0 && pro.mfy == 0) { // Horz
OffsetRect(&rcChild, -cxcDT * 3, 0);
} else {
OffsetRect(&rcChild, 0, cycDT);
}
MyDrawText(hdcDraw, TEXT("3"), &rcChild, GRIDCOLOR, SPACECOLOR, DT_RIGHT | DT_BOTTOM | DT_SINGLELINE);
if (pro.mfx == 0 && pro.mfy != 0) { // Vert
OffsetRect(&rcChild, 0, -cycDT);
} else if (pro.mfx != 0 && pro.mfy == 0) { // Horz
OffsetRect(&rcChild, -cxcDT, 0);
} else {
OffsetRect(&rcChild, -cxcDT, 0);
}
MyDrawText(hdcDraw, TEXT("2"), &rcChild, GRIDCOLOR, SPACECOLOR, DT_RIGHT | DT_BOTTOM | DT_SINGLELINE);
if (pro.mfx == 0 && pro.mfy != 0) { // Vert
OffsetRect(&rcChild, 0, -cycDT);
} else if (pro.mfx != 0 && pro.mfy == 0) { // Horz
OffsetRect(&rcChild, -cxcDT, 0);
} else {
OffsetRect(&rcChild, -cxcDT, 0);
}
MyDrawText(hdcDraw, TEXT("1"), &rcChild, GRIDCOLOR, SPACECOLOR, DT_RIGHT | DT_BOTTOM | DT_SINGLELINE);
if (cWindows) {
for (i = cWindows - 1; i >= 0; i--) {
if (winstate[i].hwnd == hwndTopdesk) {
continue;
}
// Draw existing window
GetBestGuessRect(&rcChild, &winstate[i]);
DrawWindowRect(winstate[i].hwnd, &rcChild,
WINDOWFILLCOLOR,
(winstate[i].style & (WISF_FIXED | WS_MINIMIZE) ? FIXEDFRAMECOLOR : WINDOWFRAMECOLOR),
winstate[i].style & WS_MAXIMIZE);
}
}
if ((pro.iShowGhosts != SG_NONE) && cGhosts) {
for (i = cGhosts - 1; i >= 0; i--) {
if ((pro.iShowGhosts == SG_ALL) || !(ghoststate[i].style & WISF_LINKED)) {
/*
* Draw ghost window
*/
rcChild = ghoststate[i].rc;
rRect2cRect(&rcChild);
InflateRect(&rcChild, -2, -2);
MyDrawText(hdc, ghoststate[i].szTitle,
&rcChild, GHOSTTEXTCOLOR, SPACECOLOR,
DT_LEFT | DT_TOP | DT_WORDBREAK);
if (ghoststate[i].style & WS_MAXIMIZE) {
MyDrawText(hdcDraw, GetResString(IDS_MAX), &rcChild,
GHOSTTEXTCOLOR, SPACECOLOR,
DT_LEFT | DT_BOTTOM | DT_SINGLELINE);
}
InflateRect(&rcChild, 2, 2);
FrameRect(hdc, &rcChild, pro.ahbr[ghoststate[i].style & WISF_FIXED ?
FIXEDFRAMECOLOR : GHOSTFRAMECOLOR].hbr);
}
}
}
SelectObject(hdc, hfOld);
}
/*
* This routine returns the hwnd of the window associated with the given point.
* If the window isn't real, 0 is returned.
*
* *pwType is filled with an apropriate HTY_ value to indicat what was hit.
* *pi is the index into the winstate (hwnd returnd) or ghoststate (hwnd is 0)
* array.
* *prc is filled with the rectangle of the window hit.
*/
HWND MyWindowFromPt(
LPPOINT pptr, // Real Desktop coordinates
UINT *pwType,
PRECT prc,
INT *pi,
BOOL fSkipGhosts) // set if we don't want to hit a ghost.
{
INT i;
RECT rc;
/*
* If ghosts are showing check the ghoststate array for a hit first
* since ghosts are always on top.
*/
if ((pro.iShowGhosts != SG_NONE) && cGhosts && !fSkipGhosts) {
for (i = 0; i < cGhosts; i++) {
if ((pro.iShowGhosts == SG_PARTIAL) && ghoststate[i].style & WISF_LINKED) {
continue;
}
if (PtInRect(&ghoststate[i].rc, *pptr)) {
*pwType = HTY_GHOST;
*prc = ghoststate[i].rc;
if (pi != NULL) {
*pi = i;
}
return(ghoststate[i].hwnd);
}
}
}
/*
* scan the winstate array for a hit
*/
for (i = 0; i < cWindows; i++) {
GetBestGuessRect(&rc, &winstate[i]);
if (PtInRect(&rc, *pptr)) {
if (winstate[i].hwnd == hwndTopdesk) {
continue;
}
*pwType = HTY_REAL;
*prc = rc;
if (pi != NULL) {
*pi = i;
}
return(winstate[i].hwnd);
}
}
/*
* Check the current desktop
*/
if (pro.fRelative) {
SetRect(prc, oxrCDT, oyrCDT, oxrCDT + cxrDT, oyrCDT + cyrDT);
} else {
SetRect(prc, -oxrHDT, -oyrHDT, -oxrHDT + cxrDT, -oyrHDT + cyrDT);
}
if (PtInRect(prc, *pptr)) {
*pwType = HTY_DESKTOP;
return(hwndDT);
}
/*
* Check for the home desktop
*/
if (pro.fRelative) {
SetRect(prc, oxrHDT, oyrHDT, oxrHDT + cxrDT, oyrHDT + cyrDT);
} else {
SetRect(prc, -oxrCDT, -oyrCDT, -oxrCDT + cxrDT, -oyrCDT + cyrDT);
}
if (PtInRect(prc, *pptr)) {
*pwType = HTY_HOME;
return(0);
}
*pwType = HTY_NONE;
return(0);
}
VOID TrackWindow(
INT xc,
INT yc)
{
POINT pt;
INT xCrit, yCrit;
UINT wType;
RECT rc, rcClient;
TRACKINFO ti;
INT width, height, i, xOrg, yOrg;
HWND hwnd;
BOOL fDesktopGrid, fLocked;
ti.ptOrg.x = xc;
ti.ptOrg.y = yc;
pt.x = xc2xr(xc);
pt.y = yc2yr(yc);
hwnd = MyWindowFromPt(&pt, &wType, &rc, &i, FALSE);
if (wType == HTY_NONE) {
/*
* No hit means we want to move the Topdesk window directly
*/
SendMessage(hwndTopdesk, WM_NCLBUTTONDOWN, HTCAPTION,
MAKELONG((SHORT)pt.x, (SHORT)pt.y));
return;
}
if (wType == HTY_REAL && winstate[i].style & WS_MINIMIZE) {
return; // can't drag minimized windows.
}
fDesktopGrid = (wType & (HTY_DESKTOP | HTY_HOME)) ||
(wType == HTY_REAL && winstate[i].style & WS_MAXIMIZE) ||
(GetKeyState(VK_CONTROL) & 0x8000);
fLocked = (wType & HTY_REAL && winstate[i].style & WISF_FIXED) ||
(wType & HTY_GHOST && ghoststate[i].style & WISF_FIXED);
if (fLocked && fDesktopGrid) {
return;
}
/*
* Now let the user drag the ghost or real or desktop or home window.
*/
width = rc.right - rc.left;
height = rc.bottom - rc.top;
GetCriticalPoint(&rc, &xCrit, &yCrit);
xCrit -= rc.left;
yCrit -= rc.top;
xOrg = rc.left;
yOrg = rc.top;
rRect2cRect(&rc);
ti.cxBorder = 2;
ti.cyBorder = 2;
ti.cxGrid = fDesktopGrid ? cxcDT : 1;
ti.cyGrid = fDesktopGrid ? cycDT : 1;
ti.cxKeyboard = ti.cxGrid;
ti.cyKeyboard = ti.cyGrid;
ti.rcTrack = rc;
GetClientRect(hwndTopdesk, &rcClient);
if (fLocked) {
/*
* Don't allow locked windows to be tracked off of the current
* desktop.
*/
ti.rcBoundary = rcrDT;
ti.rcBoundary.left -= xCrit - 1;
ti.rcBoundary.right += (width - xCrit) - 1;
ti.rcBoundary.top -= yCrit - 1;
ti.rcBoundary.bottom += (height - yCrit) - 1;
rRect2cRect(&ti.rcBoundary);
IntersectRect(&ti.rcBoundary, &ti.rcBoundary, &rcClient);
} else {
ti.rcBoundary = rcClient;
}
ti.ptMinTrackSize.x = 0;
ti.ptMinTrackSize.y = 0;
ti.fs = TF_MOVE | TF_ALLINBOUNDARY | TF_GRID | TF_SETPOINTERPOS;
if (hwnd == hwndTopdesk) {
ti.rcBoundary = rcrDT;
rRect2cRect(&ti.rcBoundary);
}
if (TrackRect(hInst, hwndTopdesk, &ti)) {
if (!EqualRect(&rc, &ti.rcTrack)) {
/*
* it has moved, update our database.
*/
cRect2rRect(&ti.rcTrack);
if (fDesktopGrid) {
int dx, dy;
dx = ti.rcTrack.left - xOrg;
if (dx > 0) {
/*
* round dx to an integral of cxrDT.
*/
dx = ((dx + (cxrDT >> 1)) / cxrDT) * cxrDT;
} else if (dx < 0) {
/*
* round dx to an integral of cxrDT.
*/
dx = -(((-dx + (cxrDT >> 1)) / cxrDT) * cxrDT);
}
dy = ti.rcTrack.top - yOrg;
if (dy > 0) {
/*
* round dy to an integral of cyrDT.
*/
dy = ((dy + (cyrDT >> 1)) / cyrDT) * cyrDT;
} else if (dy < 0) {
/*
* round dy to an integral of cyrDT.
*/
dy = -(((-dy + (cyrDT >> 1)) / cyrDT) * cyrDT);
}
ti.rcTrack.left = xOrg + dx;
ti.rcTrack.top = yOrg + dy;
ti.rcTrack.right = ti.rcTrack.left + width;
ti.rcTrack.bottom = ti.rcTrack.top + height;
}
if (wType & HTY_DESKTOP) {
MoveChildren(-ti.rcTrack.left, -ti.rcTrack.top);
} else if (wType & HTY_REAL) {
MyMoveWindow(hwnd, ti.rcTrack.left, ti.rcTrack.top, width, height);
} else if (wType & HTY_GHOST) {
ghoststate[i].rc = ti.rcTrack;
SaveGhostState();
} else if (wType & HTY_HOME) {
if (pro.fRelative) {
oxrHDT = ti.rcTrack.left;
oyrHDT = ti.rcTrack.top;
} else {
oxrCDT = -ti.rcTrack.left;
oyrCDT = -ti.rcTrack.top;
}
}
}
}
}
VOID MultiStart(
INT xc,
INT yc)
{
TRACKINFO ti;
INT iGhost;
RECT rc;
ti.cxGrid = 1;
ti.cyGrid = 1;
ti.cxBorder = 2;
ti.cyBorder = 2;
ti.cxKeyboard = 1;
ti.cyKeyboard = 1;
ti.rcTrack.left = ti.rcTrack.right = xc;
ti.rcTrack.top = ti.rcTrack.bottom = yc;
GetClientRect(hwndTopdesk, &ti.rcBoundary);
ti.ptMinTrackSize.x = -ti.rcBoundary.right;
ti.ptMinTrackSize.y = -ti.rcBoundary.bottom;
ti.fs = TF_RUBBERBAND | TF_ALLINBOUNDARY;
TrackRect(hInst, hwndTopdesk, &ti);
cRect2rRect(&ti.rcTrack);
rcrMS = ti.rcTrack;
fStartingAnApp = TRUE;
for (iGhost = 0; iGhost < cGhosts; iGhost++) {
if (ghoststate[iGhost].hwnd == 0 &&
IntersectRect(&rc, &ghoststate[iGhost].rc, &rcrMS)) {
StartStartupInfo(FindStartupInfo(iGhost), iGhost, TRUE);
}
}
}
/* filched from progman... yeah, that's the ticket! */
BOOL ExecProgram(
LPTSTR lpszPath,
LPTSTR lpDir,
LPTSTR lpTitle)
{
LPTSTR lpP;
HINSTANCE hRet;
/* skip leading spaces
*/
while (*lpszPath == TEXT(' '))
lpszPath++;
/* skip past path
*/
lpP = (LPTSTR)LocalAlloc(0, (_tcslen(lpszPath) + 1) * sizeof(TCHAR));
if (lpP == NULL) {
return(0);
}
_tcscpy(lpP, lpszPath);
lpszPath = lpP;
for (; *lpP && *lpP != TEXT(' ';) lpP++)
;
/* if stuff on end, separate it
*/
if (*lpP)
*lpP++ = 0;
hRet = RealShellExecute(hwndTopdesk, NULL, lpszPath, lpP,
lpDir, NULL, lpTitle, NULL, SW_SHOW, NULL);
LocalFree(lpszPath);
return((DWORD)hRet >= 32);
}
VOID StartStartupInfo(
MYSTARTUPINFO *psi,
int iGhost,
BOOL fTryStartFirst)
{
FARPROC lpfp;
RECT rc;
if (cGhosts == 0) {
return; // can't look at ghost properties if there are no ghosts.
}
//
// come here if startup failed or we have a new entry or user wants
// to edit the entry.
//
lpfp = MakeProcInstance((FARPROC)StartupDlgProc, hInst);
if (fTryStartFirst) {
goto Startit;
}
while (psi != NULL) {
fBlockRefresh++;
psi = (MYSTARTUPINFO *)DialogBoxParam(hInst,
MAKEINTRESOURCE(IDD_STARTUP), hwndTopdesk,
(DLGPROC)lpfp, (LONG)(LPTSTR)psi);
fBlockRefresh--;
if (psi == NULL) {
break;
}
Startit:
//
// if iGhost doesn't match psi, find an apropriate ghost
//
if (_tcsicmp(ghoststate[iGhost].szTitle, psi->pszTitle)) {
for (iGhost = 0; iGhost < cGhosts; iGhost++) {
if (!_tcsicmp(ghoststate[iGhost].szTitle, psi->pszTitle)) {
break;
}
}
}
//
// Jerk the desktop to where the ghost is so if the window spawns
// other windows during startup, it doesn't put those guys
// somewhere in limbo.
//
if (iGhost < cGhosts && pro.fDistOnStart) {
int x, y;
GetCriticalPoint(&ghoststate[iGhost].rc, &x, &y);
JerkDesktop(x, y, NULL, -1);
}
SetCurrentDirectory(psi->pszWorkDir);
Working(&rc);
// if (WinExec(psi->pszStartup, SW_SHOW) < 32) {
if (!ExecProgram(psi->pszStartup, psi->pszWorkDir, psi->pszTitle)) {
MessageBeep(0);
} else {
iStartGhost = iGhost;
if (psi->fSetTitle) {
pszSetTitle = psi->pszTitle;
}
break;
}
};
FreeProcInstance(lpfp);
RefreshWinState();
SaveProfile(); // so startup info gets updated.
InvalidateRect(hwndTopdesk, NULL, TRUE);
}
VOID StartGhostWindow(
INT iGhost)
{
BOOL fNew = FALSE;
INT iReal;
fStartingGhost = TRUE;
/*
* See if ghost's real window already exists - if so just switch to it.
*/
if (ghoststate[iGhost].style & WISF_LINKED) {
iReal = FindLinkedReal(iGhost);
if (iReal > -1) {
int x, y;
DistributeWindow(iReal, iGhost);
GetCriticalPoint(&ghoststate[iGhost].rc, &x, &y);
JerkDesktop(x, y, winstate[iReal].hwnd, iReal);
fStartingGhost = FALSE;
return;
}
}
fStartingAnApp = TRUE;
StartStartupInfo(FindStartupInfo(iGhost), iGhost, TRUE);
fStartingGhost = FALSE;
}
UINT AppendPopupMenuItems(
HMENU hMenu,
UINT wType,
INT i,
BOOL fFirstTime)
{
TCHAR szT[MAX_SZTITLE * 2];
UINT Count = 0;
static BOOL fAppendedGhostMove;
if (fFirstTime) {
fAppendedGhostMove = FALSE;
}
if (wType == HTY_GHOST) {
if (ghoststate[i].hwnd &&
!EqualRect(&ghoststate[i].rc, &winstate[FindRealLink(i)].rc)) {
if (!fAppendedGhostMove) {
wsprintf(szT, GetResString(IDS_MOVETOGHOSTLOC), ghoststate[i].szTitle);
AppendMenu(hMenu, MF_ENABLED | MF_STRING | MF_UNCHECKED,
CMDP_DISTRIBUTE_GHOST, szT);
Count++;
wsprintf(szT, GetResString(IDS_MOVEGHOSTTO), ghoststate[i].szTitle);
AppendMenu(hMenu, MF_ENABLED | MF_STRING | MF_UNCHECKED,
CMDP_SNAPSHOT_GHOST, szT);
Count++;
fAppendedGhostMove = TRUE;
}
} else if (FindLinkedGhost(i) == -1) {
wsprintf(szT, GetResString(IDS_STARTGHOST), ghoststate[i].szTitle);
AppendMenu(hMenu, MF_ENABLED | MF_STRING | MF_UNCHECKED,
CMDP_START_GHOST, szT);
Count++;
}
wsprintf(szT, GetResString(IDS_DESTROYGHOST), ghoststate[i].szTitle);
AppendMenu(hMenu, MF_ENABLED | MF_STRING | MF_UNCHECKED,
CMDP_DESTROY_GHOST, szT);
Count++;
if (ghoststate[i].style & WISF_FIXED) {
wsprintf(szT, GetResString(IDS_UNLOCKGHOST), ghoststate[i].szTitle);
AppendMenu(hMenu, MF_ENABLED | MF_STRING | MF_UNCHECKED,
CMDP_UNLOCK_GHOST, szT);
Count++;
} else if (IsCriticalPointOnDesktop(&ghoststate[i].rc)) {
wsprintf(szT, GetResString(IDS_LOCKGHOST), ghoststate[i].szTitle);
AppendMenu(hMenu, MF_ENABLED | MF_STRING | MF_UNCHECKED,
CMDP_LOCK_GHOST, szT);
Count++;
}
wsprintf(szT, GetResString(IDS_PROPERTIES), ghoststate[i].szTitle);
AppendMenu(hMenu, MF_ENABLED | MF_STRING | MF_UNCHECKED,
CMDP_STARTUPINFO, szT);
Count++;
} else if (wType == HTY_REAL) {
wsprintf(szT, GetResString(IDS_JUMPTO), winstate[i].szTitle);
AppendMenu(hMenu, MF_ENABLED | MF_STRING | MF_UNCHECKED,
CMDP_JUMP_REAL, szT);
Count++;
if (!(winstate[i].style & WS_MINIMIZE) && FindLinkedGhost(i) != -1) {
if (!EqualRect(&winstate[i].rc, &ghoststate[FindLinkedGhost(i)].rc)) {
if (!fAppendedGhostMove) {
wsprintf(szT, GetResString(IDS_MOVETOGHOSTLOC), winstate[i].szTitle);
AppendMenu(hMenu, MF_ENABLED | MF_STRING | MF_UNCHECKED,
CMDP_DISTRIBUTE_REAL, szT);
Count++;
wsprintf(szT, GetResString(IDS_MOVEGHOSTTO), winstate[i].szTitle);
AppendMenu(hMenu, MF_ENABLED | MF_STRING | MF_UNCHECKED,
CMDP_SNAPSHOT_REAL, szT);
Count++;
}
fAppendedGhostMove = TRUE;
}
} else if (!(winstate[i].style & WS_MINIMIZE)) {
wsprintf(szT, GetResString(IDS_CREATEGHOST), winstate[i].szTitle);
AppendMenu(hMenu, MF_ENABLED | MF_STRING | MF_UNCHECKED,
CMDP_SNAPSHOT_REAL, szT);
Count++;
}
if (!(winstate[i].style & WS_MINIMIZE) && winstate[i].style & WISF_FIXED) {
wsprintf(szT, GetResString(IDS_UNLOCKWINDOW), winstate[i].szTitle);
AppendMenu(hMenu, MF_ENABLED | MF_STRING | MF_UNCHECKED,
CMDP_UNLOCK_REAL, szT);
Count++;
} else if (!(winstate[i].style & WS_MINIMIZE) && IsCriticalPointOnDesktop(&winstate[i].rc)) {
wsprintf(szT, GetResString(IDS_LOCKWINDOW), winstate[i].szTitle);
AppendMenu(hMenu, MF_ENABLED | MF_STRING | MF_UNCHECKED,
CMDP_LOCK_REAL, szT);
Count++;
}
wsprintf(szT, GetResString(IDS_CLOSE), winstate[i].szTitle);
AppendMenu(hMenu, MF_ENABLED | MF_STRING | MF_UNCHECKED,
CMDP_DESTROY_REAL, szT);
Count++;
}
return(Count);
}
VOID DoPopupMenu(
PPOINT pptMouse,
PPOINT pptReal)
{
HMENU hMenu;
UINT wType, wTypeGhost;
RECT rc;
UINT Count = 0;
BOOL fFirst = TRUE;
hMenu = CreatePopupMenu();
ClientToScreen(hwndTopdesk, pptMouse);
pptMouse->y -= GetSystemMetrics(SM_CYMENU) / 2;
PopupPt = *pptReal;
PopuphwndFocus = MyWindowFromPt(pptReal, &wTypeGhost, &rc, &PopupGhostIndex,
FALSE);
if (wTypeGhost == HTY_GHOST) {
/*
* Allow popup menus to see through ghosts - real actions have
* priority over ghost actions.
*/
PopuphwndFocus = MyWindowFromPt(pptReal, &wType, &rc, &PopupRealIndex,
TRUE);
Count += AppendPopupMenuItems(hMenu, wType, PopupRealIndex, fFirst);
fFirst = FALSE;
} else {
PopupRealIndex = PopupGhostIndex;
wType = wTypeGhost;
}
Count += AppendPopupMenuItems(hMenu, wTypeGhost, PopupGhostIndex, fFirst);
if (!PtInRect(&rcrDT, *pptReal)) {
AppendMenu(hMenu, MF_ENABLED | MF_STRING | MF_UNCHECKED,
CMDP_JUMP_DESKTOP, GetResString(IDS_JUMPTOTHISDESKTOP));
Count++;
}
if (pro.fRelative) {
SetRect(&rc, oxrHDT, oyrHDT, oxrHDT + cxrDT, oyrHDT + cyrDT);
} else {
SetRect(&rc, -oxrCDT, -oyrCDT, -oxrCDT + cxrDT, -oyrCDT + cyrDT);
}
if (!PtInRect(&rc, *pptReal)) {
AppendMenu(hMenu, MF_ENABLED | MF_STRING | MF_UNCHECKED,
CMDP_SETHOME, GetResString(IDS_MAKETHISHOME));
Count++;
}
if (!pro.fShowFrameCtrls) {
if (Count) {
AppendMenu(hMenu, MF_SEPARATOR, 0, 0);
}
AppendMenu(hMenu, MF_ENABLED | MF_STRING | MF_UNCHECKED,
CMD_CONFIG, GetResString(IDS_OPTIONS));
Count++;
AppendMenu(hMenu, MF_ENABLED | MF_STRING | MF_UNCHECKED,
CMD_DISTRIBUTE, GetResString(IDS_MOVEWINDOWSTOGHOSTS));
Count++;
AppendMenu(hMenu, MF_ENABLED | MF_STRING | MF_UNCHECKED,
CMD_SNAPSHOT, GetResString(IDS_CREATEGHOSTS));
Count++;
if (cGhosts) {
AppendMenu(hMenu, MF_ENABLED | MF_STRING | MF_UNCHECKED,
CMD_ERASEGHOSTS, GetResString(IDS_DELETEGHOSTS));
Count++;
}
AppendMenu(hMenu, MF_ENABLED | MF_STRING | MF_UNCHECKED,
CMD_TOGGLE_GHOSTS, GetResString(IDS_TOGGLEGHOSTS));
Count++;
AppendMenu(hMenu, MF_SEPARATOR, 0, 0);
Count++;
AppendMenu(hMenu, MF_ENABLED | MF_STRING | MF_UNCHECKED,
CMD_HELP, GetResString(IDS_HELP));
Count++;
}
if (Count) {
TrackPopupMenu(hMenu, TPM_CENTERALIGN | TPM_RIGHTBUTTON,
pptMouse->x, pptMouse->y, 0, hwndTopdesk, NULL);
}
DestroyMenu(hMenu);
}
/********** TopDesk Window Procedure **************/
LONG APIENTRY TopDeskWndProc(
HWND hwnd,
UINT msg,
WPARAM wParam,
LPARAM lParam)
{
INT iReal;
RECT rc;
HMENU hMenu;
HWND hwndTop;
if (msg == wmRefreshMsg) {
MSG msg;
while (PeekMessage(&msg, hwnd, wmRefreshMsg, wmRefreshMsg, PM_REMOVE)) {
if (msg.lParam) {
lParam = msg.lParam;
wParam = msg.wParam; // grab the most recent event
}
}
RefreshWinState();
/*
* Hack to make Alt-Tab work on CMD windows:
*
* Cmd windows can't be hooked so we can't know when they get
* focus. This check causes the desktop to jerk to whoever has
* the focus if its not us and the window is not on the current
* desktop.
*/
hwndTop = GetForegroundWindow();
if (!fStartingGhost && hwndTop != NULL && hwndTop != hwndTopdesk) {
GetWindowRect(hwndTop, &rc);
if (!IsCriticalPointOnDesktop(&rc)) {
lParam = TRUE;
wParam = (WPARAM)hwndTop;
}
}
if (lParam) { // fJerkDesktop
for (iReal = 0; iReal < cWindows; iReal++) {
if (winstate[iReal].hwnd == (HWND)wParam) {
int x, y;
GetBestGuessRect(&rc, &winstate[iReal]);
GetCriticalPoint(&rc, &x, &y);
JerkDesktop(x, y, NULL, iReal);
break;
}
}
}
return(0);
}
switch (msg) {
case WM_NCCREATE:
return(ibDefWindowProc(hwnd, msg, wParam, lParam));
case WM_CREATE:
hwndTopdesk = hwnd;
hMenu = GetSystemMenu( hwndTopdesk, FALSE );
AppendMenu( hMenu, MF_SEPARATOR, 0, NULL );
AppendMenu( hMenu, MF_ENABLED | MF_CHECKED | MF_STRING, CMD_TOPMOST,
pszTopmost );
AppendMenu(GetSystemMenu(hwndTopdesk, FALSE),
MF_ENABLED | MF_STRING, CMD_TOGGLE_FRM_CTRLS,
pszShowFrmCtrls );
SetWindowPos(hwndTopdesk,
pro.fAlwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0,
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
if (!pro.fShowFrameCtrls) {
INT mfT ;
mfT = pro.mfx; // swap these so that when frame controls
pro.mfx = pro.mfxAlt; // are changed we revert back to what we
pro.mfxAlt = mfT; // last had before recalcing.
mfT = pro.mfy;
pro.mfy = pro.mfyAlt;
pro.mfyAlt = mfT;
pro.fShowFrameCtrls = TRUE;
PostMessage(hwnd, WM_COMMAND, GET_WM_COMMAND_MPS(CMD_TOGGLE_FRM_CTRLS, 0, 0));
}
return(FALSE);
break;
case WM_HOTKEY:
if (hwndTopdesk == GetForegroundWindow()) {
HWND hwndTop = GetTopAppHwnd();
#ifdef WIN16
SetActiveWindow(hwndTop);
#else // WIN32
SetForegroundWindow(hwndTop);
#endif // WIN16
} else {
#ifdef WIN16
SetActiveWindow(hwndTopdesk);
#else // WIN32
SetForegroundWindow(hwndTopdesk);
#endif // WIN16
if (IsIconic(hwndTopdesk)) {
ShowWindow(hwndTopdesk, SW_RESTORE);
}
}
break;
case WM_ENDSESSION:
case WM_CLOSE:
/*
* Hack for Johnsp - don't gather if shift-key is down.
*/
if (!(GetKeyState(VK_SHIFT) & 0x8000)) {
GatherWindows();
}
SaveProfile();
FreeStartupInfo();
#ifdef WIN32
UnregisterHotKey(hwndTopdesk, 1);
#endif
DestroyWindow(hwndTopdesk);
DeleteBrushes();
SelectObject(hdcMem, hbmOldMem);
DeleteObject(hbmMem);
DeleteDC(hdcMem);
DeleteObject(hMyFont);
break;
case WM_SYSCOLORCHANGE:
DeleteBrushes();
CreateBrushes();
InvalidateRect(hwndTopdesk, NULL, TRUE);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_ERASEBKGND:
return(1); // we handle this in the paint processing.
break;
case WM_TIMER:
PostMessage(hwnd, wmRefreshMsg, 0, 0);
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
RECT rc;
GetClientRect(hwndTopdesk, &rc);
BeginPaint(hwnd, &ps);
TopDeskPaint(hdcMem, rc);
BitBlt(ps.hdc, rc.left, rc.top,
rc.right - rc.left,
rc.bottom - rc.top,
hdcMem, rc.left, rc.top, SRCCOPY);
EndPaint(hwnd, &ps);
}
break;
case WM_INITMENU:
case WM_INITMENUPOPUP:
// CMD_TOPMOST
CheckMenuItem((HMENU)wParam, CMD_TOPMOST,
pro.fAlwaysOnTop ? MF_CHECKED : MF_UNCHECKED);
// CMD_MAGNIFY
EnableMenuItem((HMENU)wParam, CMD_MAGNIFY,
(pro.mfx > 0 || pro.mfy > 0) ? MF_ENABLED : MF_DISABLED | MF_GRAYED);
// CMD_REDUCE
EnableMenuItem((HMENU)wParam, CMD_REDUCE,
(cxcDT > cxcDTmin || cycDT > cycDTmin) ? MF_ENABLED : MF_DISABLED | MF_GRAYED);
// CMD_GOHOME
EnableMenuItem((HMENU)wParam, CMD_GOHOME,
(oxrHDT != oxrCDT || oyrHDT != oyrCDT) ?
MF_ENABLED : MF_DISABLED | MF_GRAYED);
// CMD_SETHOME
EnableMenuItem((HMENU)wParam, CMD_SETHOME,
(oxrHDT != oxrCDT || oyrHDT != oyrCDT) ?
MF_ENABLED : MF_DISABLED | MF_GRAYED);
// CMD_RELAVIVE_VIEW
CheckMenuItem((HMENU)wParam, CMD_RELATIVE_VIEW, pro.fRelative ? MF_CHECKED : MF_UNCHECKED);
// CMD_ABSOLUTE_VIEW
CheckMenuItem((HMENU)wParam, CMD_ABSOLUTE_VIEW, pro.fRelative ? MF_UNCHECKED : MF_CHECKED);
// CMD_TOGGLE_FRM_CTRLS
CheckMenuItem((HMENU)wParam, CMD_TOGGLE_FRM_CTRLS, pro.fShowFrameCtrls ? MF_CHECKED : MF_UNCHECKED);
// CMD_CONFIG
// CMD_EXIT
// CMD_DISTRIBUTE
EnableMenuItem((HMENU)wParam, CMD_DISTRIBUTE,
cGhosts ? MF_ENABLED : MF_DISABLED | MF_GRAYED);
// CMD_GATHER
// CMD_HIDE_GHOSTS
EnableMenuItem((HMENU)wParam, CMD_HIDE_GHOSTS,
cGhosts ? MF_ENABLED : MF_DISABLED | MF_GRAYED);
CheckMenuItem((HMENU)wParam,
CMD_HIDE_GHOSTS, pro.iShowGhosts == SG_NONE ?
MF_CHECKED : MF_UNCHECKED);
// CMD_PARTIAL_GHOSTS
EnableMenuItem((HMENU)wParam, CMD_PARTIAL_GHOSTS,
cGhosts ? MF_ENABLED : MF_DISABLED | MF_GRAYED);
CheckMenuItem((HMENU)wParam,
CMD_PARTIAL_GHOSTS, pro.iShowGhosts == SG_PARTIAL ?
MF_CHECKED : MF_UNCHECKED);
// CMD_SHOW_GHOSTS
EnableMenuItem((HMENU)wParam, CMD_SHOW_GHOSTS,
cGhosts ? MF_ENABLED : MF_DISABLED | MF_GRAYED);
CheckMenuItem((HMENU)wParam,
CMD_SHOW_GHOSTS, pro.iShowGhosts == SG_ALL ?
MF_CHECKED : MF_UNCHECKED);
// CMD_SNAPSHOT
// CMD_ERASEGHOSTS
EnableMenuItem((HMENU)wParam, CMD_ERASEGHOSTS,
cGhosts ? MF_ENABLED : MF_DISABLED | MF_GRAYED);
// CMD_STARTUPINFO
EnableMenuItem((HMENU)wParam, CMD_STARTUPINFO,
(pStartupInfo != NULL) && cGhosts ? MF_ENABLED : MF_DISABLED | MF_GRAYED);
// CMD_HELP
// CMD_ABOUT
break;
case WM_LBUTTONDOWN:
TrackWindow(LOWORD(lParam), HIWORD(lParam));
InvalidateRect(hwndTopdesk, NULL, TRUE);
return(CondDefWindowProc(hwnd, msg, wParam, lParam));
break;
case WM_RBUTTONDOWN:
{
UINT wType;
RECT rc;
POINT pt;
INT i;
DWORD time;
BOOL fSkipMenu;
MSG msgS;
pt.x = xc2xr(LOWORD(lParam));
pt.y = yc2yr(HIWORD(lParam));
time = GetTickCount();
fSkipMenu = FALSE;
while (GetTickCount() < time + DEBOUNCE_TIMEOUT) {
if (PeekMessage(&msgS, hwnd, WM_RBUTTONUP, WM_RBUTTONUP,
PM_NOREMOVE)) {
fSkipMenu = TRUE;
break;
}
}
if (fSkipMenu) {
hwndFocus = MyWindowFromPt(&pt, &wType, &rc, &i, FALSE);
if ((wType & HTY_REAL) && (hwndFocus != hwndTopdesk)) {
JerkDesktop(pt.x, pt.y, hwndFocus, i);
} else if (wType == HTY_NONE || wType & HTY_HOME) {
JerkDesktop(pt.x, pt.y, (HWND)0, -1);
} else if ((wType & HTY_GHOST)) {
StartGhostWindow(i);
}
} else {
POINT ptMouse;
ptMouse.x = LOWORD(lParam);
ptMouse.y = HIWORD(lParam);
DoPopupMenu(&ptMouse, &pt);
}
}
break;
case WM_LBUTTONDBLCLK:
CommandMsg(CMD_TOGGLE_FRM_CTRLS);
break;
case WM_COMMAND:
if (!CommandMsg(GET_WM_COMMAND_ID(wParam, lParam)))
goto DoDWP;
break;
case WM_SYSCOMMAND:
CommandMsg(GET_WM_COMMAND_ID(wParam, lParam));
goto DoDWP;
case WM_SIZE:
if (fStarted && !fFrameToggleSize && (wParam != SIZE_MINIMIZED)) {
cxc = LOWORD(lParam);
cyc = HIWORD(lParam);
CalcConversionFactors(TRUE);
pro.mfxAlt = pro.mfx;
pro.mfyAlt = pro.mfy;
}
fFrameToggleSize = FALSE;
RefreshWinState();
break;
case WM_KILLFOCUS:
if (pro.fHideNoFocus && GetForegroundWindow() != hwndTopdesk) {
#ifdef HIDEIT
GetWindowRect(hwndTopdesk, &rc);
if (IntersectRect(&rc2, &rc, &rcrDT)) {
SetWindowPos(hwndTopdesk, NULL, rc.left + rcrDT.right,
rc.top + rcrDT.bottom, 0, 0,
SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER);
}
#else
ShowWindow(hwndTopdesk, SW_SHOWMINNOACTIVE);
#endif // HIDEIT
}
goto DoDWP;
break;
case WM_SETFOCUS:
if (pro.fHideNoFocus) {
#ifdef HIDEIT
GetWindowRect(hwndTopdesk, &rc);
if (!IntersectRect(&rc2, &rc, &rcrDT)) {
SetWindowPos(hwndTopdesk, NULL, rc.left - rcrDT.right,
rc.top - rcrDT.bottom, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
}
#endif // HIDEIT
}
// fall through
case WM_MOVE:
if (fStarted) {
RefreshWinState();
}
// fall through
default:
DoDWP:
return(CondDefWindowProc(hwnd, msg, wParam, lParam));
break;
}
return(0L);
}
BOOL InitApplication(
HANDLE hInst)
{
WNDCLASS wc;
InitResString(&pszTopmost, IDS_TOPMOST);
InitResString(&pszShowFrmCtrls, IDS_SHOWFRMCTRLS);
InitResString(&pszData, IDS_DATA);
InitResString(&pszTopdeskHelpTitle, IDS_TOPDESKHELPTITLE);
InitResString(&pszHelpFileName, IDS_HELPFILENAME);
InitResString(&pszWorking, IDS_WORKING);
InitResString(&pszProfile, IDS_PROFILE);
InitResString(&pszStartupInfo, IDS_STARTUPINFO);
InitResString(&pszTitle, IDS_TITLE);
InitSubstResString(&pszSubKey, IDS_SUBKEY, IDS_VERSION_NUM);
InitSubstResString(&pszVersion, IDS_VERSION, IDS_VERSION_NUM);
InitResString(&pszElementNames[SPACECOLOR], IDS_SPACECOLOR);
InitResString(&pszElementNames[WINDOWFILLCOLOR], IDS_WINDOWFILLCOLOR);
InitResString(&pszElementNames[WINDOWFRAMECOLOR], IDS_WINDOWFRAMECOLOR);
InitResString(&pszElementNames[DESKFRAMECOLOR], IDS_DESKFRAMECOLOR);
InitResString(&pszElementNames[GRIDCOLOR], IDS_GRIDCOLOR);
InitResString(&pszElementNames[GHOSTFRAMECOLOR], IDS_GHOSTFRAMECOLOR);
InitResString(&pszElementNames[WINDOWTEXT], IDS_WINDOWTEXT);
InitResString(&pszElementNames[FIXEDFRAMECOLOR], IDS_FIXEDFRAMECOLOR);
InitResString(&pszElementNames[GHOSTTEXTCOLOR], IDS_GHOSTTEXTCOLOR);
if (hwndTopdesk = FindWindow(pszTitle, pszTitle)) {
DPRINTF((hfDbgOut, "Found another TopDesk.\n"));
SendMessage(hwndTopdesk, WM_HOTKEY, 0, 0);
return(FALSE); // we are already running!
}
wc.style = CS_HREDRAW | CS_VREDRAW | CS_SAVEBITS | CS_DBLCLKS;
wc.lpfnWndProc = TopDeskWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInst;
wc.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDR_ICON));
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = NULL;
wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU);
wc.lpszClassName = pszTitle;
if (RegisterClass(&wc)) {
return(TRUE);
} else {
DPRINTF((hfDbgOut, "RegisterClass failed!"));
return(FALSE);
}
}
BOOL InitSubstResString(
LPTSTR *ppsz,
DWORD id1,
DWORD id2)
{
LPTSTR pszT;
pszT = GetResString(id2);
_tcscpy(szResString2, pszT);
pszT = GetResString(id1);
*ppsz = LocalAlloc(LPTR, (_tcslen(pszT) + _tcslen(szResString2) + 1) * sizeof(TCHAR));
if (*ppsz != NULL) {
wsprintf(*ppsz, pszT, szResString2);
return(TRUE);
}
DPRINTF((hfDbgOut, "InitSubstResString(%d, %d) failed.\n", id1, id2));
return(FALSE);
}
BOOL InitResString(
LPTSTR *ppsz,
DWORD id)
{
LPTSTR pszT;
pszT = GetResString(id);
*ppsz = LocalAlloc(LPTR, (_tcslen(pszT) + 1) * sizeof(TCHAR));
if (*ppsz != NULL) {
_tcscpy(*ppsz, pszT);
return(TRUE);
}
DPRINTF((hfDbgOut, "InitResString(%d) failed.\n", id));
return(FALSE);
}
BOOL TopDeskInit()
{
HDC hdc;
int i;
OSVERSIONINFO ovi;
wmRefreshMsg = RegisterWindowMessage(TEXT(szMYWM_REFRESH));
if (RegOpenKey(HKEY_CURRENT_USER, pszSubKey, &hKeyTopDesk) != ERROR_SUCCESS) {
if (RegCreateKey(HKEY_CURRENT_USER, pszSubKey, &hKeyTopDesk) != ERROR_SUCCESS) {
DPRINTF((hfDbgOut, "Could not open registry key.\n"));
return(FALSE);
}
}
for (i = 0; i < MAX_ICOLOR; i++) {
pro.ahbr[i] = orgColors[i];
}
cxrDT = GetSystemMetrics(SM_CXSCREEN);
cyrDT = GetSystemMetrics(SM_CYSCREEN);
cxFrame = GetSystemMetrics(SM_CXFRAME);
cyFrame = GetSystemMetrics(SM_CYFRAME);
ovi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&ovi);
fCairoShell = ovi.dwMajorVersion >= 4;
if (!GetProfile()) {
pro.x = 0;
pro.y = 0;
pro.cx = cxrDT / 4;
pro.cy = cyrDT / 3;
}
hMyFont = CreateFontIndirect(&pro.lf);
if (!hMyFont) {
DPRINTF((hfDbgOut, "Could not create font.\n"));
return(FALSE);
}
fpRefreshEnumProc = MakeProcInstance((FARPROC)RefreshEnumProc, hInst);
if (fpRefreshEnumProc == NULL) {
DPRINTF((hfDbgOut, "MakeProcInstance failied.\n"));
return(FALSE);
}
hAccel = LoadAccelerators(hInst, MAKEINTRESOURCE(IDR_ACCEL));
if (!hAccel) {
DPRINTF((hfDbgOut, "Could not load accelerators.\n"));
return(FALSE);
}
SetRect(&rcrDT, 0, 0, cxrDT, cyrDT);
cxcDTmin = GetSystemMetrics(SM_CXICON) / 2;
cycDTmin = GetSystemMetrics(SM_CYICON) / 2;
hwndDT = GetDesktopWindow();
CreateBrushes();
hdc = GetDC(NULL);
hdcMem = CreateCompatibleDC(hdc);
hbmMem = CreateCompatibleBitmap(hdc, GetDeviceCaps(hdc, HORZRES),
GetDeviceCaps(hdc, VERTRES));
hbmOldMem = SelectObject(hdcMem, hbmMem);
ReleaseDC(NULL, hdc);
return(TRUE);
}
int WINAPI WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
MSG msg;
lpCmdLine;
nCmdShow;
hInst = hInstance;
#ifdef DEBUG
hfDbgOut = fopen("topdesk.log", "w");
if (hfDbgOut == NULL) {
MessageBeep(0);
MessageBeep(0);
MessageBeep(0);
return(0);
}
#endif // DEBUG
if (!InitApplication(hInstance)) {
return (FALSE);
}
if (!TopDeskInit()) {
return(FALSE);
}
hwndTopdesk = CreateWindow(pszTitle, pszTitle,
WS_OVERLAPPED | WS_THICKFRAME | MD_FRAMESTYLES | IBS_HORZCAPTION,
0, 0, 0, 0, NULL, NULL, hInst, NULL);
if (!hwndTopdesk) {
DPRINTF((hfDbgOut, "CreateWindow failed.\n"));
return(0);
}
SetWindowLong(hwndTopdesk, GWL_STYLE,
GetWindowLong(hwndTopdesk, GWL_STYLE) | WS_DLGFRAME);
ibSetCaptionSize(hwndTopdesk, GetSystemMetrics(SM_CYCAPTION) / 2 + 1);
SetTimer(hwndTopdesk, 1, TIMEOUT_REFRESH, NULL);
MoveWindow(hwndTopdesk, pro.x, pro.y, pro.cx, pro.cy, TRUE);
ShowWindow(hwndTopdesk, SW_SHOW);
SetActiveWindow(hwndTopdesk);
fStarted = TRUE;
CommandMsg(CMD_GOHOME);
RegisterHotKey(hwndTopdesk, 1,
(pro.fShift ? MOD_SHIFT : 0) |
(pro.fControl ? MOD_CONTROL : 0) |
(pro.fAlt ? MOD_ALT : 0),
pro.vkey);
if (SetTopDeskHooks(hwndTopdesk)) {
while (GetMessage(&msg, NULL, 0, 0)) {
if (IsIconic(hwndTopdesk) ||
!TranslateAccelerator(hwndTopdesk, hAccel, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
} else {
MessageBox(hwndTopdesk, GetResString(IDS_CANTSETHOOKS),
pszTitle, MB_OK);
DPRINTF((hfDbgOut, "Could not set hooks.\n"));
}
if (hKeyTopDesk) {
RegCloseKey(hKeyTopDesk);
}
FreeProcInstance(fpRefreshEnumProc);
#ifdef DEBUG
fclose(hfDbgOut);
#endif // DEBUG
return(0);
}