#include "cCrossCall_12.h" #include "cpicture_12.h" /* Mike... */ #include "cGameLib_12.h" /* ...Mike */ // MW... #include "cprinter_12.h" #include "cTCP.h" #include "winsock.h" #ifdef HILT #include int htmlHelpInitialized = FALSE; DWORD htmlHelpCookie; #endif #include extern BOOL bUserAbort; extern HWND hDlgPrint; /* MW: hDlgPrint is the handle of the "Cancel Printing" dialog. */ extern HWND hwndText; /* MW: hwndText is the handle of the page count text in the dialog. */ DNSInfo *DNSInfoList=NULL; // ...MW CrossCallInfo gCci; static BOOL gEventsInited = FALSE; static BOOL gAppRunning = FALSE; /* Mike... */ char *gAppName; /* Mike: should not be static because refered to elsewhere. */ /* ...Mike */ static HANDLE gCLEAN_DONE; static HANDLE gOS_DONE; static DWORD gCleanThreadId; static DWORD gOsThreadId; static HANDLE ghOSThreadHandle = NULL; HINSTANCE ghInst; HWND ghMainWindow = NULL; /* RWS ... */ static HWND gNextClipboardViewer = NULL; /* PA: name was not used anymore. Now using it again for storing next clipboardviewer. */ /* ... RWS */ static int gClipboardCount = 0; /* PA: keeps track of changes of clipboard. */ static HACCEL gAcceleratorTable = NULL; /* Refers to the accelerator table of the active frame. */ static BOOL gAcceleratorTableIsUpToDate = TRUE; static PAINTSTRUCT gPaintStruct; static HWND ghTopDocWindow = NULL; static HWND ghActiveFrameWindow = NULL; /* The currently active frame window (MDI/SDI). */ static HWND ghActiveClientWindow = NULL; /* The currently active client window (MDI). */ static HWND gActiveDialog = NULL; static HWND ghwndLastModalDialog = NULL; /* Keeps track of last modal dialog. */ static BOOL gPopupIsOpen = FALSE; /* Only one PopupMenu can be open at a time. */ static BOOL gInMouseDown = FALSE; static HCURSOR ghFatCrossCursor = NULL; static HCURSOR ghHiddenCursor = NULL; static int gProhibitWindowActivation = 0; static int gDoubleDownDistance = -1; static int gGlobalCursorCode = -1; static int gNextItemHandle = 0; /* PA: this global is now used only for timers; improve name. */ static int gClicks = 0; static UINT gClTime; static int gClX, gClY; static HWND gClHwnd; static HFONT gDlogFont = NULL; static HFONT gWinFont = NULL; /* The font used for controls in windows. */ static int gComboSelection = -1; static BOOL gInKey = FALSE; static int gCurChar; static LONG gPrevMsgTime = -1; static BOOL gMessStored = FALSE; static MSG gStoredMess; static BOOL gIdleTimerOn = FALSE; static BOOL gSleeptime = 0; /* The sleep time required by Clean timers/receivers. */ static LONG stdEditCallback = 0; /* The standard internal Windows callback routine of edit controls. */ static LONG stdPopUpCallback = 0; /* The standard internal Windows callback routine of pop up controls. */ static LONG stdMDIClientCallback = 0; /* The standard internal Windows callback routine of MDI client windows. */ static HFONT gControlFont; /* The handle to the logical FONT that is used in all controls. */ static HWND ghwndTT = NULL; /* The tooltip control. */ static CrossCallInfo *MakeQuitCci (CrossCallInfo * pcci); static CrossCallInfo *MakeReturn0Cci (CrossCallInfo * pcci); static CrossCallInfo *MakeReturn1Cci (CrossCallInfo * pcci, int v); static CrossCallInfo *MakeReturn2Cci (CrossCallInfo * pcci, int v1, int v2); static CrossCallInfo *MakeReturn3Cci (CrossCallInfo * pcci, int v1, int v2, int v3); static CrossCallInfo *MakeReturn4Cci (CrossCallInfo * pcci, int v1, int v2, int v3, int v4); static CrossCallInfo *MakeReturn5Cci (CrossCallInfo * pcci, int v1, int v2, int v3, int v4, int v5); static CrossCallInfo *MakeReturn6Cci (CrossCallInfo * pcci, int v1, int v2, int v3, int v4, int v5, int v6); /* Menu(item)IDs are not allowed to exceed OSMenuIDEnd. This is because window ids start at (OSMenuIDEnd+5), and need to be distinct from menu ids in case of MDI processes. The global gMenuItemID (initially 0) is incremented by NextMenuItemID each time a new menu(item)ID is required. This implementation does not reuse freed ids and is therefore not adequate!! */ #define OSMenuIDEnd 10000 static int gMenuItemID = 0; static UINT NextMenuItemID (void) { if (gMenuItemID>=OSMenuIDEnd) ErrorExit ("NextMenuItemID exceeded number of internal menu(item)IDs: %d",OSMenuIDEnd); gMenuItemID++; return gMenuItemID; } /* Implementation of accelerator tables. Now for each MDI and SDI frame window, a private accelerator table is stored. NDI processes have no frame window, and also don't need an accelerator table. A global AcceleratorTable is maintained, gAcceleratorTable. It contains the HACCEL of the current frame window. A global BOOL is maintained, gAcceleratorTableIsUpToDate. It is TRUE if gAcceleratorTable represents the correct acceleratortable. It is FALSE if not. For each accelerator key four entries are stored in the acceleratortable: Ctrl +key Ctrl+Shift +key Ctrl +Alt+key Ctrl+Shift+Alt+key For this reason a minimum size of 4 (MINSIZEPROCESSSHORTCUTTABLE) has been set. Deflating the table never decreases below this value. */ struct ProcessShortcutTable { int pst_size; // The current size of the table int pst_used; // The current number of filled items ACCEL *pst_shortcuts; // The current table, implemented as a pointer to ACCELs }; typedef struct ProcessShortcutTable *ProcessShortcutTable; #define MINSIZEPROCESSSHORTCUTTABLE 4 // The minimum size of an accelerator table is 4 static void CopyACCEL (ACCEL *source, ACCEL *dest) { dest->fVirt = source->fVirt; dest->key = source->key; dest->cmd = source->cmd; } /* AllocateProcessShortcutTable (size) creates a shortcut table of the given size. */ static ProcessShortcutTable AllocateProcessShortcutTable (int size) { ProcessShortcutTable table; ACCEL *shortcuts; table = (ProcessShortcutTable) rmalloc (sizeof (struct ProcessShortcutTable)); shortcuts = (ACCEL *) rmalloc (size * sizeof (ACCEL)); table->pst_size = size; table->pst_used = 0; table->pst_shortcuts = shortcuts; return (table); } /* DestroyProcessShortcutTable (table) frees the memory used by the table. */ static void DestroyProcessShortcutTable (ProcessShortcutTable table) { rfree (table->pst_shortcuts); rfree (table); } /* InflateProcessShortcutTable (table) returns a new table double the size of the argument table. */ static ProcessShortcutTable InflateProcessShortcutTable (ProcessShortcutTable oldTable) { int i, oldSize, newSize; ProcessShortcutTable newTable; oldSize = oldTable->pst_size; newSize = oldSize*2; newTable = (ProcessShortcutTable) AllocateProcessShortcutTable (newSize); for (i=0; ipst_shortcuts[i], &newTable->pst_shortcuts[i]); newTable->pst_used = oldTable->pst_used; rfree (oldTable); return (newTable); } /* DeflateProcessShortcutTable (table) returns a new table half the size of the argument table. In case the table already is at its minimum size (MINSIZEPROCESSSHORTCUTTABLE) the argument table is returned. */ static ProcessShortcutTable DeflateProcessShortcutTable (ProcessShortcutTable oldTable) { int i, oldSize, newSize; ProcessShortcutTable newTable; oldSize = oldTable->pst_size; newSize = oldSize/2; if (newSize < MINSIZEPROCESSSHORTCUTTABLE) { return (oldTable); } else { newTable = (ProcessShortcutTable) AllocateProcessShortcutTable (newSize); for (i=0; ipst_shortcuts[i], &newTable->pst_shortcuts[i]); newTable->pst_used = min (oldTable->pst_used, newSize); rfree (oldTable); return (newTable); } } static void SetACCELentry (ACCEL *entry, BYTE flags, int key, int id) { entry->fVirt = flags; entry->key = (WORD) ((BYTE) VkKeyScan ((char) key)); entry->cmd = (WORD) id; } /* AddProcessShortcut (key,id,table) returns a new table in which the shortkey (id,key) has been added. The new table may have been inflated to accomodate the new shortkey. For each shortkey the following four accelerator flags are entered as separate entries: FVIRTKEY | FCONTROL FVIRTKEY | FCONTROL | FSHIFT FVIRTKEY | FCONTROL | FALT FVIRTKEY | FCONTROL | FSHIFT | FALT */ static ProcessShortcutTable AddProcessShortcut (int key, int id, ProcessShortcutTable oldTable) { ACCEL *newentry; ProcessShortcutTable newTable; int used = oldTable->pst_used; // first make sure that the table has the proper size. if (used+4 >= oldTable->pst_size) { newTable = InflateProcessShortcutTable (oldTable); } else { newTable = oldTable; } // Add Ctrl+key: newentry = &newTable->pst_shortcuts[used]; SetACCELentry (newentry, (BYTE) FCONTROL | FVIRTKEY, key, id); // Add Ctrl+Shift+key: newentry = &newTable->pst_shortcuts[used+1]; SetACCELentry (newentry, (BYTE) FCONTROL | FSHIFT | FVIRTKEY, key, id); // Add Ctrl+Alt+key: newentry = &newTable->pst_shortcuts[used+2]; SetACCELentry (newentry, (BYTE) FCONTROL | FALT | FVIRTKEY, key, id); // Add Ctrl+Shift+Alt+key: newentry = &newTable->pst_shortcuts[used+3]; SetACCELentry (newentry, (BYTE) FCONTROL |FSHIFT | FALT | FVIRTKEY, key, id); newTable->pst_used = used+4; return(newTable); } /* RemoveProcessShortcut (id,table) returns a new table in which the shortkey (id,_) has been removed. The new table may have been deflated to use up less memory space. In case the entry (id,_) has been located, the consecutive 3 entries are also removed as these encode the accelerator flag versions. */ static ProcessShortcutTable RemoveProcessShortcut (int id, ProcessShortcutTable oldTable) { int i; int foundat = 0; int used = oldTable->pst_used; // search for the element to be deleted. while (foundatpst_shortcuts[foundat].cmd != id) { foundat++; } if (foundat>=used) { return (oldTable); // the element was not found, so return argument table } used -= 4; for (i=foundat; ipst_shortcuts[i+4], &oldTable->pst_shortcuts[i]); oldTable->pst_used = used; if (used < oldTable->pst_size/2 && used > MINSIZEPROCESSSHORTCUTTABLE) // check if table needs to be deflated { return (DeflateProcessShortcutTable (oldTable)); } else { return (oldTable); } } static void UpdateAcceleratorTable (void) { ProcessShortcutTable table; if (!gAcceleratorTableIsUpToDate) // The accelerator table is not up to date { if (gAcceleratorTable!=NULL) // Destroy the previous version if exists { DestroyAcceleratorTable (gAcceleratorTable); } gAcceleratorTable = NULL; if (ghActiveFrameWindow!=NULL) // The current frame is an (MDI/SDI) frame { table = (ProcessShortcutTable) GetWindowLong (ghActiveFrameWindow, 0); if (table!=NULL) { gAcceleratorTable = CreateAcceleratorTable (table->pst_shortcuts,table->pst_used); } } } } /* End of implementation of accelerator tables. */ /* Local window data structures: */ struct LocalWindowData { int lwd_cursorcode; /* The cursor shape of the window */ BOOL lwd_usersizemoving; /* The user is sizing/moving the window */ }; typedef struct LocalWindowData *LocalWindowData; static LocalWindowData AllocateLocalWindowData () { LocalWindowData lwd_wdata; lwd_wdata = (LocalWindowData) rmalloc (sizeof (struct LocalWindowData)); lwd_wdata->lwd_cursorcode = 0; lwd_wdata->lwd_usersizemoving = (BOOL)FALSE; return (lwd_wdata); } /* DestroyLocalWindowData (wdata) frees the memory used by the wdata. */ static void DestroyLocalWindowData (LocalWindowData wdata) { rfree (wdata); } extern EXPORT_TO_CLEAN int WinBeep (int ios) { MessageBeep (MB_ICONASTERISK); return ios; } extern EXPORT_TO_CLEAN void WinGetTime (int ios, int * hour, int * minute, int * second, int * oos) { SYSTEMTIME time; GetLocalTime (&time); *hour = time.wHour; *minute = time.wMinute; *second = time.wSecond; *oos = ios; } extern EXPORT_TO_CLEAN void WinGetDate (int ios, int * year, int * month, int * day, int * weekday, int * oos) { SYSTEMTIME time; GetLocalTime (&time); *year = time.wYear; *month = time.wMonth; *day = time.wDay; *weekday = time.wDayOfWeek + 1; *oos = ios; } extern EXPORT_TO_CLEAN int WinWait (int delay, int ios) { Sleep (delay); return ios; } extern EXPORT_TO_CLEAN void WinGetBlinkTime (int ios, int* blinktime, int* oos) { *blinktime = (int) GetCaretBlinkTime (); *oos = ios; } static void InitGlobals (void) { LOGFONT lf; /* Mike... */ InitGameGlobals (); /* ...Mike */ gAppRunning = FALSE; ghOSThreadHandle = NULL; ghMainWindow = NULL; /* RWS ... */ gNextClipboardViewer = NULL; /* ... RWS */ gAcceleratorTable = NULL; ghTopDocWindow = NULL; ghActiveFrameWindow = NULL; ghActiveClientWindow = NULL; gActiveDialog = NULL; ghwndLastModalDialog = NULL; gPopupIsOpen = FALSE; gInMouseDown = FALSE; ghFatCrossCursor = NULL; ghHiddenCursor = NULL; gProhibitWindowActivation = 0; gDoubleDownDistance = -1; gGlobalCursorCode = -1; gNextItemHandle = 0; gClicks = 0; gDlogFont = NULL; gWinFont = NULL; gComboSelection = -1; gInKey = FALSE; gPrevMsgTime = -1; gMessStored = FALSE; gIdleTimerOn = FALSE; gSleeptime = 0; // Globally, we create a logical font that is used in all controls. SetLogFontData (&lf, "MS Sans Serif", 0, 8); gControlFont = CreateFontIndirect (&lf); } static char CustomControlClassName[] = "__CleanCustomControl"; static char CompoundControlClassName[] = "__CleanCompoundControl"; /* Class for CompoundControls */ static char MainWindowClassName[] = "__CleanMainWindow"; static char SDIWindowClassName[] = "__CleanSDIWindow"; /* Class for SDI windows (must have same length as MDIWindowClassName). */ static char SDIFrameClassName[] = "__CleanSDIFrame"; /* Class for SDI frames. */ static char MDIWindowClassName[] = "__CleanMDIWindow"; /* Class for MDI windows (must have same length as SDIWindowClassName). */ static char MDIFrameClassName[] = "__CleanMDIFrame"; /* Class for MDI frames. */ int nCopyAnsiToWideChar (LPWORD lpWCStr, LPSTR lpAnsiIn) { int nChar = 0; do { *lpWCStr++ = (WORD) * lpAnsiIn; nChar++; } while (*lpAnsiIn++); return nChar; } static void GetAppFileName (void) { char path[MAX_PATH + 1]; int length, index; int start, end; BOOL newword; length = GetModuleFileName (NULL, path, MAX_PATH); for (index = length - 1; path[index] != '.'; index--) ; end = index - 1; for (index = end; path[index] != '/' && path[index] != '\\' && path[index] != ':'; index--) ; start = index + 1; if (end - start > 31) end = start + 31; if (end - start >= 0) { gAppName = rmalloc (end - start + 2); for (index = 0; index <= end - start; index++) gAppName[index] = path[start + index]; gAppName[index] = '\0'; } else { gAppName = "Clean Application"; } newword = TRUE; for (index = 0; gAppName[index] != '\0'; index++) { if (gAppName[index] >= 'A' && gAppName[index] <= 'Z' && !newword) gAppName[index] = gAppName[index] - ('A' - 'a'); if (gAppName[index] == ' ') newword = TRUE; else newword = FALSE; } } extern EXPORT_TO_CLEAN PSTR WinGetAppPath (void) { char *path; int idx, length; path = rmalloc (261); length = GetModuleFileName (NULL, path, 260); for (idx = length - 1; path[idx] != '/' && path[idx] != '\\' && path[idx] != ':'; idx--) ; path[idx + 1] = 0; return path; /* relying on the calling clean function to de-allocate path. */ } /* Cursor handling routines. */ static BYTE FatCrossCursorANDmask[128] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0xff, 0xff, 0xff, 0x80, 0x7f, 0xff, 0xff, 0x80, 0x7f, 0xff, 0xff, 0x80, 0x7f, 0xff, 0xff, 0x80, 0x7f, 0xff, 0xff, 0x80, 0x7f, 0xff, 0xe0, 0x00, 0x03, 0xff, 0xe0, 0x3e, 0x01, 0xff, 0xe0, 0x3e, 0x01, 0xff, 0xe0, 0x3e, 0x01, 0xff, 0xe0, 0x3e, 0x01, 0xff, 0xe0, 0x3e, 0x01, 0xff, 0xe0, 0x00, 0x01, 0xff, 0xf0, 0x00, 0x01, 0xff, 0xff, 0x80, 0x7f, 0xff, 0xff, 0x80, 0x7f, 0xff, 0xff, 0x80, 0x7f, 0xff, 0xff, 0x80, 0x7f, 0xff, 0xff, 0x80, 0x7f, 0xff, 0xff, 0xc0, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; static BYTE FatCrossCursorXORmask[128] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x0f, 0xff, 0xf8, 0x00, 0x0f, 0xe3, 0xf8, 0x00, 0x0f, 0xe3, 0xf8, 0x00, 0x0f, 0xe3, 0xf8, 0x00, 0x0f, 0xff, 0xf8, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; static BYTE HiddenCursorANDmask[128] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; static BYTE HiddenCursorXORmask[128] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; static HCURSOR GetFatCrossCursor (void) { if (ghFatCrossCursor != NULL) return ghFatCrossCursor; ghFatCrossCursor = CreateCursor (ghInst, 12, 13, /* Hot spot */ 32, 32, /* width, heigth */ FatCrossCursorANDmask, FatCrossCursorXORmask ); return ghFatCrossCursor; } static HCURSOR GetHiddenCursor (void) { if (ghHiddenCursor != NULL) return ghHiddenCursor; ghHiddenCursor = CreateCursor (ghInst, 16, 16, /* Hot spot */ 32, 32, /* width, heigth */ HiddenCursorANDmask, HiddenCursorXORmask ); return ghHiddenCursor; } static void DeleteCursors (void) { if (ghFatCrossCursor != NULL) { DestroyCursor (ghFatCrossCursor); ghFatCrossCursor = NULL; } if (ghHiddenCursor != NULL) { DestroyCursor (ghHiddenCursor); ghHiddenCursor = NULL; } } static int GetDoubleDownDistance (void) { if (gDoubleDownDistance == -1) gDoubleDownDistance = GetSystemMetrics (SM_CXDOUBLECLK) / 2; return gDoubleDownDistance; } extern EXPORT_TO_CLEAN OS WinSetDoubleDownDist (int dd, OS ios) { gDoubleDownDistance = dd; return ios; } static HCURSOR SetCursorFromCode (int code) { switch (code) { case CURSARROW: return SetCursor (LoadCursor (0, IDC_ARROW)); case CURSBUSY: return SetCursor (LoadCursor (0, IDC_WAIT)); case CURSIBEAM: return SetCursor (LoadCursor (0, IDC_IBEAM)); case CURSCROSS: return SetCursor (LoadCursor (0, IDC_CROSS)); case CURSFATCROSS: return SetCursor (GetFatCrossCursor ()); case CURSHIDDEN: return SetCursor (GetHiddenCursor ()); default: return NULL; } } static BOOL IsApplicationWindow (HWND hw) { while (hw != NULL && hw != ghMainWindow) hw = GetWindow (hw, GW_OWNER); return (hw != NULL); } static HWND ApplicationWindowUnderCursor (void) { POINT p; HWND hwin; GetCursorPos (&p); hwin = WindowFromPoint (p); if (IsApplicationWindow (hwin)) return hwin; else return NULL; } static int CALLBACK EnumFontNameProc (ENUMLOGFONT FAR * lpelf, /* pointer to logical-font data */ NEWTEXTMETRIC FAR * lpntm, /* pointer to physical-font data */ int fontType, /* type of font */ LPARAM lParam /* address of application-defined data */ ) { SendMessage1ToClean (CcCbFONTNAME, lpelf->elfLogFont.lfFaceName); return 1; } static int CALLBACK EnumFontSizeProc (ENUMLOGFONT FAR * lpelf, /* pointer to logical-font data */ NEWTEXTMETRIC FAR * lpntm, /* pointer to physical-font data */ int fontType, /* type of font */ LPARAM lParam /* address of application-defined data */ ) { SendMessage2ToClean (CcCbFONTSIZE, lpntm->tmHeight - lpntm->tmInternalLeading, fontType == TRUETYPE_FONTTYPE); if (fontType == TRUETYPE_FONTTYPE) return 0; else return 1; } static void AdjustMenuBarName (void) { /* PA: previous version did not set the frame window title. Appending the topDocWindow title should be done by the MDI interface. char apptitle[70]; char wintitle[32]; if (ghTopDocWindow != NULL) { GetWindowText (ghTopDocWindow, wintitle, 31); wsprintf (apptitle, "%s - [%s]", gAppName, wintitle); SetWindowText (ghActiveFrameWindow, apptitle); } else { SetWindowText (ghMainWindow, gAppName); } */ if (ghActiveFrameWindow != NULL) { SetWindowText (ghActiveFrameWindow, gAppName); } } /* Win(M/S)DIClientToOuterSizeDims returns the width and height needed to add/subtract from the client/outer size to obtain the outer/client size. These values must be the same as used by W95AdjustClean(M/S)DIWindowDimensions! */ extern EXPORT_TO_CLEAN void WinMDIClientToOuterSizeDims (int styleFlags, OS ios, int *dw, int *dh, OS *oos) { if ((styleFlags&WS_THICKFRAME) != 0) { /* resizable window */ *dw = 2 * GetSystemMetrics (SM_CXSIZEFRAME); *dh = 2 * GetSystemMetrics (SM_CYSIZEFRAME) + GetSystemMetrics (SM_CYCAPTION); } else { /* fixed size window */ *dw = 2 * GetSystemMetrics (SM_CXFIXEDFRAME); *dh = 2 * GetSystemMetrics (SM_CYFIXEDFRAME) + GetSystemMetrics (SM_CYCAPTION); } *oos = ios; } extern EXPORT_TO_CLEAN void WinSDIClientToOuterSizeDims (int styleFlags, OS ios, int *dw, int *dh, OS *oos) { *dw = 2 * GetSystemMetrics (SM_CXSIZEFRAME); *dh = 2 * GetSystemMetrics (SM_CYSIZEFRAME) + GetSystemMetrics (SM_CYCAPTION); *oos = ios; } /* Adjust the dimensions of a Clean MDI document window with W95 frame dimensions. These values must be the same as returned by WinMDIClientToOuterSizeDims! */ static void W95AdjustCleanMDIWindowDimensions (DWORD styleFlags, POINT * dim) { if ((styleFlags&WS_THICKFRAME) != 0) { /* resizable window */ dim->x += 2 * GetSystemMetrics (SM_CXSIZEFRAME); dim->y += 2 * GetSystemMetrics (SM_CYSIZEFRAME) + GetSystemMetrics (SM_CYCAPTION); } else { /* fixed size window */ dim->x += 2 * GetSystemMetrics (SM_CXFIXEDFRAME); dim->y += 2 * GetSystemMetrics (SM_CYFIXEDFRAME) + GetSystemMetrics (SM_CYCAPTION); } } /* Adjust the dimensions of a Clean SDI frame window with W95 frame and menu dimensions. These values must be the same as returned by WinSDIClientToOuterSizeDims! */ static void W95AdjustCleanSDIWindowDimensions (DWORD styleFlags, POINT * dim) { dim->x += 2 * GetSystemMetrics (SM_CXSIZEFRAME); dim->y += 2 * GetSystemMetrics (SM_CYSIZEFRAME) + GetSystemMetrics (SM_CYCAPTION); } static int GetModifiers (void) { int mods; mods = 0; if (GetKeyState (VK_SHIFT) < 0) mods |= SHIFTBIT; if (GetKeyState (VK_CONTROL) < 0) mods |= CTRLBIT; if (GetKeyState (VK_MENU) < 0) mods |= ALTBIT; return mods; } static BOOL mystrequal (int length, char *s1, char *s2) { int i = 0; while (s1[i] == s2[i]) { if (i >= length) return TRUE; i++; } return FALSE; } /* Find the first non CompoundControl parent window of the argument hwnd. This procedure assumes that hwnd is the handle of a control. */ static HWND GetControlParent (HWND hwndControl) { HWND parent; char *parentclassname; int classnamelength; parent = GetParent (hwndControl); classnamelength = lstrlen (CompoundControlClassName) + 1; parentclassname = rmalloc (classnamelength); GetClassName (parent, parentclassname, classnamelength); while (mystrequal (classnamelength, parentclassname, CompoundControlClassName)) { parent = GetParent (parent); GetClassName (parent,parentclassname,classnamelength); } rfree (parentclassname); return parent; } /* Return the hwnd of the parent window only if this is a Dialog (actually: is neither a SDIWindow or MDIWindow). If the parent is not a Dialog then NULL is returned. This procedure assumes that hwnd is the handle of a control. */ static HWND GetControlParentDialog (HWND hwndControl) { HWND parent; char *parentclassname; int classnamelength; parent = GetControlParent (hwndControl); classnamelength = lstrlen (SDIWindowClassName) + 1; parentclassname = rmalloc (classnamelength); GetClassName (parent, parentclassname, classnamelength); if (mystrequal (classnamelength, parentclassname, SDIWindowClassName)) { parent = NULL; } else if (mystrequal (classnamelength, parentclassname, MDIWindowClassName)) { parent = NULL; } rfree (parentclassname); return parent; } /* IsSDIDocumentWindow (hwnd) returns TRUE if the class name of hwnd is SDIWindowClassName. */ static BOOL IsSDIDocumentWindow (HWND hwnd) { char *classname; int classnamelength; BOOL isSDI; classnamelength = lstrlen (SDIWindowClassName) + 1; classname = rmalloc (classnamelength); GetClassName (hwnd, classname, classnamelength); isSDI = mystrequal (classnamelength, classname, SDIWindowClassName); rfree (classname); return isSDI; } /* IsMDIDocumentWindow (hwnd) returns TRUE if the class name of hwnd is MDIWindowClassName. */ static BOOL IsMDIDocumentWindow (HWND hwnd) { char *classname; int classnamelength; BOOL isMDI; classnamelength = lstrlen (MDIWindowClassName) + 1; classname = rmalloc (classnamelength); GetClassName (hwnd, classname, classnamelength); isMDI = mystrequal (classnamelength, classname, MDIWindowClassName); rfree (classname); return isMDI; } /* GetSDIClientWindow finds the first SDI client window of the argument hwnd. This procedure assumes that hwnd is the handle of a SDI frame window. If no SDI client window could be found then GetSDIClientWindow returns NULL. */ static HWND GetSDIClientWindow (HWND hwndFrame) { HWND client; char *clientclassname; int classnamelength; client = GetWindow (hwndFrame,GW_CHILD); classnamelength = lstrlen (SDIWindowClassName) + 1; clientclassname = rmalloc (classnamelength); GetClassName (client, clientclassname, classnamelength); while (client != NULL && !mystrequal (classnamelength, clientclassname, SDIWindowClassName)) { client = GetWindow (client,GW_HWNDNEXT); GetClassName (client,clientclassname,classnamelength); } rfree (clientclassname); return client; } /* Set and get the GWL_USERDATA of a windowhandle. */ static void SetGWL_USERDATA (LONG data, HWND hwnd) { SetWindowLong (hwnd, GWL_USERDATA, data); } static LONG GetGWL_USERDATA (HWND hwnd) { return GetWindowLong (hwnd, GWL_USERDATA); } /* Access the GWL_STYLE of a windowhandle: GetGWL_STYLE (hwnd) returns the GWL_STYLE value of hwnd; WindowHasHScroll (hwnd) returns TRUE iff hwnd has a horizontal scrollbar; WindowHasVScroll (hwnd) returns TRUE iff hwnd has a vertical scrollbar; */ static LONG GetGWL_STYLE (HWND hwnd) { return GetWindowLong (hwnd, GWL_STYLE); } static BOOL WindowHasHScroll (HWND hwnd) { LONG hwndStyle = GetGWL_STYLE (hwnd); return (hwndStyle & WS_HSCROLL); } static BOOL WindowHasVScroll (HWND hwnd) { LONG hwndStyle = GetGWL_STYLE (hwnd); return (hwndStyle & WS_VSCROLL); } /* Translate virtual key codes to the codes shared with Clean. This procedure has been filtered from RbrtTranslateMessage. If the keycode could not be translated, zero is returned. */ static int CheckVirtualKeyCode (int keycode) { int c = 0; switch (keycode) { case VK_UP: c = WinUpKey; break; case VK_DOWN: c = WinDownKey; break; case VK_LEFT: c = WinLeftKey; break; case VK_RIGHT: c = WinRightKey; break; case VK_PRIOR: c = WinPgUpKey; break; case VK_NEXT: c = WinPgDownKey; break; case VK_END: c = WinEndKey; break; case VK_HOME: c = WinBeginKey; break; case VK_BACK: c = WinBackSpKey; break; case VK_DELETE: c = WinDelKey; break; case VK_TAB: c = WinTabKey; break; case VK_RETURN: c = WinReturnKey; break; case VK_ESCAPE: c = WinEscapeKey; break; case VK_HELP: c = WinHelpKey; break; case VK_F1: c = WinF1Key; break; case VK_F2: c = WinF2Key; break; case VK_F3: c = WinF3Key; break; case VK_F4: c = WinF4Key; break; case VK_F5: c = WinF5Key; break; case VK_F6: c = WinF6Key; break; case VK_F7: c = WinF7Key; break; case VK_F8: c = WinF8Key; break; case VK_F9: c = WinF9Key; break; case VK_F10: c = WinF10Key; break; case VK_F11: c = WinF11Key; break; case VK_F12: c = WinF12Key; break; } return c; } static void SendKeyDownToClean (HWND hwndParent, HWND hwndChild, int c) { SendMessage5ToClean (CcWmKEYBOARD, hwndParent, hwndChild, c, KEYDOWN, GetModifiers ()); } static void SendKeyStillDownToClean (HWND hwndParent, HWND hwndChild, int c) { SendMessage5ToClean (CcWmKEYBOARD, hwndParent, hwndChild, c, KEYREPEAT, GetModifiers ()); } static void SendKeyUpToClean (HWND hwndParent, HWND hwndChild, int c) { SendMessage5ToClean (CcWmKEYBOARD, hwndParent, hwndChild, c, KEYUP, GetModifiers ()); } static void SendMouseUpToClean (HWND hwndParent, HWND hwndChild, int x, int y) { gInMouseDown = FALSE; KillTimer (hwndChild, (UINT) - 1); SendMessage6ToClean (CcWmMOUSE, hwndParent, hwndChild, BUTTONUP, x, y, GetModifiers ()); } static void SendMouseStillDownToClean (HWND hwndParent, HWND hwndChild, int x, int y) { SendMessage6ToClean (CcWmMOUSE, hwndParent, hwndChild, BUTTONSTILLDOWN, x, y, GetModifiers ()); } static void SendMouseStillUpToClean (HWND hwndParent, HWND hwndChild, int x, int y) { SendMessage6ToClean (CcWmMOUSE, hwndParent, hwndChild, BUTTONSTILLUP, x, y, GetModifiers ()); } static BOOL inDcSpaceTime (HWND curwin, int curx, int cury, UINT curtime, HWND prevwin, int prevx, int prevy, UINT prevtime) { if (rabs (curx - prevx) > GetDoubleDownDistance ()) return FALSE; if (rabs (cury - prevy) > GetDoubleDownDistance ()) return FALSE; if (curtime - prevtime > GetDoubleClickTime ()) return FALSE; if (curwin != prevwin) return FALSE; return TRUE; } static void SendMouseDownToClean (HWND hwndParent, HWND hwndChild, int x, int y) { gInMouseDown = TRUE; SetCapture (hwndChild); SetFocus (hwndChild); /* Pressing the mouse must also set the keyboard input to that object. */ SetTimer (hwndChild, (UINT) - 1, (UINT) 1, NULL); if (gClicks != 0 && !inDcSpaceTime (hwndChild, x, y, GetMessageTime (), gClHwnd, gClX, gClY, gClTime)) gClicks = 0; if (gClicks == 0) { gClTime = GetMessageTime (); gClX = x; gClY = y; gClHwnd = hwndChild; } gClicks++; SendMessage6ToClean (CcWmMOUSE, hwndParent, hwndChild, gClicks, x, y, GetModifiers ()); if (gClicks == 3) gClicks = 0; } /* This routine should be applied only in case of WM_DROPFILES messages. It will copy a buffer of all involved file names into one string and send it to Clean. */ static void SendDropFilesToClean (HWND hWin,WPARAM wPara) { int nrFiles, fileNr, nrChars, charCount; char * filenames; /* first retrieve the number of files. */ nrFiles = DragQueryFile ((HANDLE)wPara, 0xFFFFFFFF, (LPSTR)NULL, 0); /* calculate the number of characters. */ nrChars = 0; for (fileNr=0; fileNrCtlType) { case ODT_COMBOBOX: { char text[256]; COLORREF forecolor, bkcolor; SendMessage (lpdis->hwndItem, CB_GETLBTEXT, lpdis->itemID, (LPARAM) text); if (lpdis->itemState & ODS_DISABLED) { forecolor = SetTextColor (lpdis->hDC, GetSysColor (COLOR_GRAYTEXT)); bkcolor = SetBkColor (lpdis->hDC, GetSysColor (COLOR_3DFACE)); } else if (lpdis->itemState & ODS_SELECTED) { if (lpdis->itemData) { forecolor = SetTextColor (lpdis->hDC, GetSysColor (COLOR_HIGHLIGHTTEXT)); bkcolor = SetBkColor (lpdis->hDC, GetSysColor (COLOR_HIGHLIGHT)); } else { forecolor = SetTextColor (lpdis->hDC, GetSysColor (COLOR_GRAYTEXT)); bkcolor = SetBkColor (lpdis->hDC, GetSysColor (COLOR_WINDOW)); } } else { if (lpdis->itemData) forecolor = SetTextColor (lpdis->hDC, GetSysColor (COLOR_WINDOWTEXT)); else forecolor = SetTextColor (lpdis->hDC, GetSysColor (COLOR_GRAYTEXT)); bkcolor = SetBkColor (lpdis->hDC, GetSysColor (COLOR_WINDOW)); } ExtTextOut (lpdis->hDC, /* device context */ lpdis->rcItem.left + 2, /* ref point x */ lpdis->rcItem.top + 1, /* ref point y */ ETO_CLIPPED | ETO_OPAQUE, /* options */ &lpdis->rcItem, /* clipping rect */ text, /* text to draw */ lstrlen (text), /* length of text to draw */ NULL /* no kerning array */ ); SetTextColor (lpdis->hDC, forecolor); SetBkColor (lpdis->hDC, bkcolor); if (lpdis->itemState & ODS_FOCUS) DrawFocusRect (lpdis->hDC, &lpdis->rcItem); return TRUE; } break; case ODT_BUTTON: { SendMessage3ToClean (CcWmDRAWCONTROL, hwnd, lpdis->hwndItem, lpdis->hDC); if (lpdis->itemState & ODS_SELECTED) InvertRect (lpdis->hDC, &lpdis->rcItem); if (lpdis->itemState & ODS_FOCUS) DrawFocusRect (lpdis->hDC, &lpdis->rcItem); return TRUE; } break; } return FALSE; } break; /* WM_SETFOCUS alternative circumvents application-crash when dialog is closed from the inside (by an element button or close box). */ case WM_SETFOCUS: { return TRUE; } break; default: return FALSE; break; } ErrorExit ("Fatal error: case leak in DialogProcedure (%d).",message); } /* End of DialogProcedure callback routine. */ // MW... void lookUpAndRemove(WPARAM dnsHdl,DNSInfo **listPtr,DNSInfo **elPtr) // This function is used to look up an element with a matching dnsHdl-field in // the DNSInfoList. This element will then be removed from the list. { if ((WPARAM)(*listPtr)->dnsHdl==dnsHdl) { // the object to look up has been found, so remove it from the list // and give it back via elPtr. *elPtr = *listPtr; *listPtr = (*listPtr)->next; } else lookUpAndRemove(dnsHdl, &(*listPtr)->next, elPtr); } // ... MW /* The callback routine for the main window. PA: The WM_CREATE message registers the main window as a clipboard viewer. The WM_DESTROY message unregisters the main window. */ static LRESULT CALLBACK MainWindowProcedure (HWND hWin, UINT uMess, WPARAM wPara, LPARAM lPara) { printMessage ("Main Window", hWin, uMess, wPara, lPara); switch (uMess) { case WM_NCPAINT: break; case WM_ACTIVATEAPP: { if (wPara) { gAppRunning = TRUE; } else { gAppRunning = FALSE; } } break; /* WM_ENTERIDLE message is used to let Clean evaluate the initialisation action of a modal dialog by sending the CcWmIDLEDIALOG message. */ case WM_ENTERIDLE: { HWND hwndModalDialog; hwndModalDialog = (HWND)lPara; if (wPara == MSGF_DIALOGBOX && hwndModalDialog != ghwndLastModalDialog) { SendMessage1ToClean (CcWmIDLEDIALOG,(int)hwndModalDialog); ghwndLastModalDialog = hwndModalDialog; } else { SendMessage0ToClean (CcWmIDLETIMER); } return 0; } break; case WM_TIMER: { SendMessage2ToClean (CcWmTIMER, wPara, GetMessageTime ()); } break; case WM_ENABLE: { HWND hwin; char title[64]; hwin = GetWindow (ghMainWindow, GW_HWNDFIRST); while (hwin != NULL) { GetWindowText (hwin, title, 63); if (GetWindow (hwin, GW_OWNER) == ghMainWindow) { RECT r; GetWindowRect (hwin, &r); if (r.top != -1 || r.left != -1 || r.right != 0 || r.bottom != 0) { EnableWindow (hwin, (BOOL) wPara); } } hwin = GetWindow (hwin, GW_HWNDNEXT); } } break; /* PA: The WM_CREATE message registers the ghMainWindow (hWin) as a clipboard viewer. */ case WM_CREATE: { gNextClipboardViewer = SetClipboardViewer (hWin); } break; /* PA: The WM_DESTROY message unregisters the ghMainWindow (hWin) as a clipboard viewer. */ case WM_DESTROY: { ChangeClipboardChain (hWin, gNextClipboardViewer); } break; /* PA: other clipboard chain management messages: */ case WM_DRAWCLIPBOARD: { gClipboardCount += 1; if (gNextClipboardViewer != NULL) SendMessage (gNextClipboardViewer, uMess, wPara, lPara); return 0; } break; case WM_CHANGECBCHAIN: { if ((HWND)wPara == gNextClipboardViewer) /* gNextClipboardViewer is no longer a clipboard viewer. */ gNextClipboardViewer = (HWND)lPara; /* then store the new viewer. */ else if (gNextClipboardViewer != NULL) SendMessage (gNextClipboardViewer, uMess, wPara, lPara); return 0; } break; // MW... case PM_SOCKET_EVENT: { // wPara is the socket handle // LOWORD(lPara) is the message // HIWORD(lPara) is an error code switch (LOWORD(lPara)) { case FD_OOB: case FD_READ: SendMessage3ToClean(CcWmINETEVENT,IE_RECEIVED, wPara, RChanReceiver); break; case FD_WRITE: SendMessage3ToClean(CcWmINETEVENT,IE_SENDABLE, wPara, SChanReceiver); break; case FD_ACCEPT: SendMessage3ToClean(CcWmINETEVENT,IE_CONNECTREQUEST, wPara, ListenerReceiver); break; case FD_CONNECT:SendMessage3ToClean( CcWmINETEVENT, HIWORD(lPara)==0 ? IE_ASYNCCONNECTCOMPLETE : IE_ASYNCCONNECTFAILED, wPara, ConnectReceiver); break; case FD_CLOSE: { dictitem *pDictitem; pDictitem = lookup(wPara); if (pDictitem) { if (pDictitem->hasReceiveNotifier) SendMessage3ToClean(CcWmINETEVENT,IE_EOM, wPara, RChanReceiver); if (pDictitem->hasSendableNotifier && HIWORD(lPara)!=0) SendMessage3ToClean(CcWmINETEVENT,IE_DISCONNECTED, wPara, SChanReceiver); }; }; break; }; }; break; case PM_DNS_EVENT: { // wPara contains the DNS handle (the handle created by WSAAsyncGetHostByName // The IP-adress of the looked up host will have been written into the // corresponding element of the DNSInfoList. Look it up: struct DNSInfo *elPtr; int errCode; errCode = HIWORD(lPara); lookUpAndRemove(wPara,&DNSInfoList,&elPtr); // *elPtr contains the info SendMessage4ToClean( CcWmINETEVENT, errCode ? IE_IPADDRESSNOTFOUND : IE_IPADDRESSFOUND, , elPtr->dnsHdl, DNSReceiver, errCode ? 0 : ntohl(((int*)(*(elPtr->junion.Hostent.h_addr_list)))[0]) ); // deallocate unused memory LocalFree(elPtr); }; break; // ... MW case WM_DDE_INITIATE: { static char apptext[256], topictext[256]; ATOM aApp, aTopic; /* RWS ... */ BOOL handleTopic; /* ... RWS */ GlobalGetAtomName (HIWORD (lPara), topictext, 256); if (lstrcmp (topictext, "CLEANOPEN") == 0) /* RWS: compare application name */ { GlobalGetAtomName (LOWORD (lPara), apptext, 256); handleTopic = CompareStringA (LOCALE_USER_DEFAULT, NORM_IGNORECASE, apptext, lstrlen (apptext), gAppName, lstrlen (gAppName)) == 2; /* 2 means they are equal */ } else handleTopic = FALSE; if (handleTopic) { /* ... RWS */ aApp = GlobalAddAtom (apptext); aTopic = GlobalAddAtom (topictext); SendMessage ((HWND) wPara, WM_DDE_ACK, (WPARAM) hWin, MAKELONG (aApp, aTopic)); GlobalDeleteAtom (aApp); GlobalDeleteAtom (aTopic); } else { return DefWindowProc (hWin, uMess, wPara, lPara); } } break; case WM_DDE_EXECUTE: { char *commandstring; char *pcommand; int len; union { DDEACK ddeack; WORD w; } da; pcommand = GlobalLock ((HANDLE) lPara); len = lstrlen (pcommand) + 1; commandstring = rmalloc (len); /* this pointer is passed to and freed in the Clean code. */ lstrcpyn (commandstring, pcommand, len); GlobalUnlock ((HANDLE) lPara); SendMessage1ToClean (CcWmDDEEXECUTE, commandstring); da.ddeack.bAppReturnCode = 0; da.ddeack.fBusy = 0; da.ddeack.fAck = 1; PostMessage ((HWND) wPara, WM_DDE_ACK, (WPARAM) hWin, PackDDElParam (WM_DDE_ACK, (UINT) da.w, lPara)); return 0; } break; case WM_DDE_TERMINATE: { PostMessage ((HWND) wPara, WM_DDE_TERMINATE, (WPARAM) hWin, 0); } return 0; default: return DefWindowProc (hWin, uMess, wPara, lPara); break; } return 0; } /* End of MainWindowProcedure callback routine. */ /* The callback routine for custom controls. */ static LRESULT CALLBACK CustomControlProcedure (HWND hwnd, UINT uMess, WPARAM wParam, LPARAM lParam) { printMessage ("CustomControlProcedure", hwnd, uMess, wParam, lParam); switch (uMess) { case WM_PAINT: { HWND parent; HDC hdc; PAINTSTRUCT ps; parent = GetControlParent (hwnd); hdc = BeginPaint (hwnd, &ps); SendMessage3ToClean (CcWmDRAWCONTROL, parent, hwnd, hdc); EndPaint (hwnd, &ps); return 0; } break; case WM_LBUTTONDOWN: { SendMouseDownToClean (GetControlParent (hwnd), hwnd, SIGNEDLOWORD (lParam), SIGNEDHIWORD (lParam)); return 0; } break; case WM_MOUSEMOVE: { if (gInMouseDown) { SendMouseStillDownToClean (GetControlParent (hwnd), hwnd, SIGNEDLOWORD (lParam), SIGNEDHIWORD (lParam)); } else { SendMouseStillUpToClean (GetControlParent (hwnd), hwnd, SIGNEDLOWORD (lParam), SIGNEDHIWORD (lParam)); } return 0; } break; case WM_LBUTTONUP: { if (gInMouseDown) { ReleaseCapture (); /* rely on WM_CAPTURECHANGED to send the mouseUp event */ } return 0; } break; case WM_CANCELMODE: { if (gInMouseDown) { ReleaseCapture (); /* rely on WM_CAPTURECHANGED to send the mouseUp event */ } return DefWindowProc (hwnd, uMess, wParam, lParam); } break; case WM_CAPTURECHANGED: { if (gInMouseDown) { POINT p; GetCursorPos (&p); ScreenToClient (hwnd, &p); SendMouseUpToClean (GetControlParent (hwnd), hwnd, p.x, p.y); } return 0; } break; case WM_TIMER: { if ((int) wParam == -1) { POINT p; GetCursorPos (&p); ScreenToClient (hwnd, &p); SendMouseStillDownToClean (GetControlParent (hwnd), hwnd, p.x, p.y); } else { rprintf ("Custom control did not expect normal WM_TIMER message with id = %d.\n", wParam); } return 0; } break; case WM_SYSKEYDOWN: case WM_KEYDOWN: { int c = 0; HWND hwndParent; c = CheckVirtualKeyCode ((int) wParam); if (!c) /* Ignore non-virtual keys, because they arrive as WM_SYSCHAR and WM_CHAR. */ { return DefWindowProc (hwnd, uMess, wParam, lParam); } /* Handle virtual keys analogously to keys received as WM_SYSCHAR and WM_CHAR. */ hwndParent = GetControlParent (hwnd); if (gInKey) { if (gCurChar == c) SendKeyStillDownToClean (hwndParent, hwnd, gCurChar); else { SendKeyUpToClean (hwndParent, hwnd, gCurChar); gCurChar = c; SendKeyDownToClean (hwndParent, hwnd, gCurChar); } } else { gCurChar = c; SendKeyDownToClean (hwndParent, hwnd, gCurChar); gInKey = TRUE; } return 0; } break; case WM_SYSCHAR: case WM_CHAR: { HWND hwndParent = GetControlParent (hwnd); if (gInKey) { if (gCurChar == (int) wParam) SendKeyStillDownToClean (hwndParent, hwnd, gCurChar); else { SendKeyUpToClean (hwndParent, hwnd, gCurChar); gCurChar = wParam; SendKeyDownToClean (hwndParent, hwnd, gCurChar); } } else { gCurChar = wParam; SendKeyDownToClean (hwndParent, hwnd, gCurChar); gInKey = TRUE; } return 0; } break; case WM_SYSKEYUP: case WM_KEYUP: { if (gInKey) SendKeyUpToClean (GetControlParent (hwnd), hwnd, gCurChar); gInKey = FALSE; gCurChar = 0; return DefWindowProc (hwnd, uMess, wParam, lParam); } break; case WM_KILLFOCUS: { HWND hwndParent = GetControlParent (hwnd); if (gInKey) SendKeyUpToClean (hwndParent, hwnd, gCurChar); gInKey = FALSE; gCurChar = 0; /* WM_KILLFOCUS now also sends the CcWmKILLFOCUS message to Clean (because of the ControlDeactivate attribute). */ SendMessage2ToClean (CcWmKILLFOCUS, hwndParent, hwnd); return 0; } break; case WM_SETFOCUS: { /* WM_SETFOCUS sends the CcWmSETFOCUS message to Clean (because of ControlActivate attribute). */ SendMessage2ToClean (CcWmSETFOCUS, GetControlParent (hwnd), hwnd); return 0; } break; case WM_GETDLGCODE: /* Inform dialog procedure to pass all keyboard input to the control. */ return (DLGC_WANTCHARS | DLGC_WANTARROWS); break; default: return DefWindowProc (hwnd, uMess, wParam, lParam); break; } ErrorExit ("Fatal error: case leak in CustomControlProcedure (%d).",uMess); } /* End of CustomControlProcedure callback routine. */ /* Callback routine for compound controls. */ static LRESULT CALLBACK CompoundControlProcedure (HWND hwnd, UINT uMess, WPARAM wParam, LPARAM lParam) { printMessage ("CompoundControlProcedure", hwnd, uMess, wParam, lParam); switch (uMess) { case WM_COMMAND: { switch (HIWORD (wParam)) { case BN_CLICKED: { if (lParam != 0) { /* Send also modifiers to Clean */ SendMessage4ToClean (CcWmBUTTONCLICKED, GetControlParent (hwnd), lParam, GetModifiers (), LOWORD (wParam)); } return 0; } break; case CBN_SETFOCUS: { gComboSelection = SendMessage ((HWND) lParam, CB_GETCURSEL, 0, 0); return 0; } break; case CBN_KILLFOCUS: { gComboSelection = -1; return 0; } break; case CBN_SELENDOK: { char text[256]; int newsel; HWND combo; combo = (HWND) lParam; newsel = SendMessage (combo, CB_GETCURSEL, 0, 0); SendMessage (combo, CB_GETLBTEXT, newsel, (LPARAM) text); if (!SendMessage (combo, CB_GETITEMDATA, newsel, 0)) { SendMessage (combo, CB_SETCURSEL, gComboSelection, (LPARAM) text); MessageBeep (0xFFFFFFFF); return 0; } else { gComboSelection = newsel; if (newsel!=CB_ERR) SendMessage3ToClean (CcWmCOMBOSELECT, GetControlParent (hwnd), combo, newsel); return 1; } } break; } return 0; } break; case WM_PAINT: { HWND parentwindow; HDC hdc; PAINTSTRUCT ps; // if (GetUpdateRect(hwnd,NULL,FALSE)) // determine if there is really an update area. // { parentwindow = GetControlParent (hwnd); hdc = BeginPaint (hwnd, &ps); SendMessage3ToClean (CcWmDRAWCONTROL, parentwindow, hwnd, hdc); EndPaint (hwnd, &ps); // } return 0; } break; case WM_HSCROLL: { int nPos,nScrollCode,controlkind; HWND parentwindow, hwndScrollBar; nScrollCode = LOWORD (wParam); if (nScrollCode != SB_ENDSCROLL) /* Do not send the SB_ENDSCROLL to Clean. */ { nPos = (short int) HIWORD (wParam); parentwindow = GetControlParent (hwnd); hwndScrollBar = (HWND) lParam; if (hwndScrollBar==0) { controlkind = SB_HORZ; /* lParam==0 in case of Compound scrollbars. */ hwndScrollBar = hwnd; /* pass the compound control handle to Clean. */ UpdateWindow (hwnd); /* but first ensure that compound control is updated. */ } else { controlkind = SB_CTL; /* lParam!==0 in case of SliderControls. */ } SendMessage5ToClean (CcWmSCROLLBARACTION, parentwindow, hwndScrollBar, controlkind, nScrollCode, nPos); } return 0; } break; case WM_VSCROLL: { int nPos,nScrollCode,controlkind; HWND parentwindow, hwndScrollBar; nScrollCode = LOWORD (wParam); if (nScrollCode != SB_ENDSCROLL) /* Do not send the SB_ENDSCROLL to Clean. */ { nPos = (short int) HIWORD (wParam); parentwindow = GetControlParent (hwnd); hwndScrollBar = (HWND) lParam; if (hwndScrollBar==0) { controlkind = SB_VERT; /* lParam==0 in case of Compound scrollbars. */ hwndScrollBar = hwnd; /* pass the compound control handle to Clean. */ UpdateWindow (hwnd); /* but first ensure that compound control is updated. */ } else { controlkind = SB_CTL; /* lParam!==0 in case of SliderControls. */ } SendMessage5ToClean (CcWmSCROLLBARACTION, parentwindow, hwndScrollBar, controlkind, nScrollCode, nPos); } return 0; } break; /* The following cases concerning mouse events (WM_LBUTTONDOWN upto WM_TIMER) have been copied from CustomControlProcedure. */ case WM_LBUTTONDOWN: { SendMouseDownToClean (GetControlParent (hwnd), hwnd, SIGNEDLOWORD (lParam), SIGNEDHIWORD (lParam)); return 0; } break; case WM_MOUSEMOVE: { if (gInMouseDown) { SendMouseStillDownToClean (GetControlParent (hwnd), hwnd, SIGNEDLOWORD (lParam), SIGNEDHIWORD (lParam)); } else { SendMouseStillUpToClean (GetControlParent (hwnd), hwnd, SIGNEDLOWORD (lParam), SIGNEDHIWORD (lParam)); } return 0; } break; case WM_LBUTTONUP: { if (gInMouseDown) { ReleaseCapture (); /* rely on WM_CAPTURECHANGED to send the mouseUp event */ } return 0; } break; case WM_CANCELMODE: { if (gInMouseDown) { ReleaseCapture (); /* rely on WM_CAPTURECHANGED to send the mouseUp event */ } return DefWindowProc (hwnd, uMess, wParam, lParam); } break; case WM_CAPTURECHANGED: { if (gInMouseDown) { POINT p; GetCursorPos (&p); ScreenToClient (hwnd, &p); SendMouseUpToClean (GetControlParent (hwnd), hwnd, p.x, p.y); } return 0; } break; case WM_TIMER: { if ((int) wParam == -1) { POINT p; GetCursorPos (&p); ScreenToClient (hwnd, &p); SendMouseStillDownToClean (GetControlParent (hwnd), hwnd, p.x, p.y); } else { rprintf ("Compound control did not expect normal WM_TIMER message with id = %d.\n", wParam); } return 0; } break; /* The following cases concerning key events and focus events (WM_SYSKEYDOWN upto WM_GETDLGCODE) have been copied from CustomControlProcedure. */ case WM_SYSKEYDOWN: case WM_KEYDOWN: { int c = 0; HWND hwndParent; c = CheckVirtualKeyCode ((int) wParam); if (!c) /* Ignore non-virtual keys, because they arrive as WM_SYSCHAR and WM_CHAR. */ { return DefWindowProc (hwnd, uMess, wParam, lParam); } /* Handle virtual keys analogously to keys received as WM_SYSCHAR and WM_CHAR. */ hwndParent = GetControlParent (hwnd); if (gInKey) { if (gCurChar == c) SendKeyStillDownToClean (hwndParent, hwnd, gCurChar); else { SendKeyUpToClean (hwndParent, hwnd, gCurChar); gCurChar = c; SendKeyDownToClean (hwndParent, hwnd, gCurChar); } } else { gCurChar = c; SendKeyDownToClean (hwndParent, hwnd, gCurChar); gInKey = TRUE; } return 0; } break; case WM_SYSCHAR: case WM_CHAR: { HWND hwndParent = GetControlParent (hwnd); if (gInKey) { if (gCurChar == (int) wParam) SendKeyStillDownToClean (hwndParent, hwnd, gCurChar); else { SendKeyUpToClean (hwndParent, hwnd, gCurChar); gCurChar = wParam; SendKeyDownToClean (hwndParent, hwnd, gCurChar); } } else { gCurChar = wParam; SendKeyDownToClean (hwndParent, hwnd, gCurChar); gInKey = TRUE; } return 0; } break; case WM_SYSKEYUP: case WM_KEYUP: { if (gInKey) SendKeyUpToClean (GetControlParent (hwnd), hwnd, gCurChar); gInKey = FALSE; gCurChar = 0; return DefWindowProc (hwnd, uMess, wParam, lParam); } break; case WM_KILLFOCUS: { HWND hwndParent = GetControlParent (hwnd); if (gInKey) SendKeyUpToClean (hwndParent, hwnd, gCurChar); gInKey = FALSE; gCurChar = 0; /* WM_KILLFOCUS now also sends the CcWmKILLFOCUS message to Clean (because of the ControlDeactivate attribute). */ SendMessage2ToClean (CcWmKILLFOCUS, hwndParent, hwnd); return 0; } break; case WM_SETFOCUS: { /* WM_SETFOCUS sends the CcWmSETFOCUS message to Clean because of the ControlActivate attribute. */ SendMessage2ToClean (CcWmSETFOCUS, GetControlParent (hwnd), hwnd); return 0; } break; /* The WM_CLOSE event is generated when a user presses escape inside an EditControl that exists within the CompoundControl which exists within a Dialog. */ case WM_CLOSE: { SendMessage1ToClean (CcWmCLOSE, GetControlParent (hwnd)); return 0; } break; case WM_GETDLGCODE: /* Inform dialog procedure to pass all keyboard input to the control. */ return (DLGC_WANTCHARS | DLGC_WANTARROWS); break; case WM_DRAWITEM: { LPDRAWITEMSTRUCT lpdis; lpdis = (LPDRAWITEMSTRUCT) lParam; switch (lpdis->CtlType) { case ODT_COMBOBOX: { char text[256]; COLORREF forecolor, bkcolor; SendMessage (lpdis->hwndItem, CB_GETLBTEXT, lpdis->itemID, (LPARAM) text); if (lpdis->itemState & ODS_DISABLED) { forecolor = SetTextColor (lpdis->hDC, GetSysColor (COLOR_GRAYTEXT)); bkcolor = SetBkColor (lpdis->hDC, GetSysColor (COLOR_3DFACE)); } else if (lpdis->itemState & ODS_SELECTED) { if (lpdis->itemData) { forecolor = SetTextColor (lpdis->hDC, GetSysColor (COLOR_HIGHLIGHTTEXT)); bkcolor = SetBkColor (lpdis->hDC, GetSysColor (COLOR_HIGHLIGHT)); } else { forecolor = SetTextColor (lpdis->hDC, GetSysColor (COLOR_GRAYTEXT)); bkcolor = SetBkColor (lpdis->hDC, GetSysColor (COLOR_WINDOW)); } } else { if (lpdis->itemData) forecolor = SetTextColor (lpdis->hDC, GetSysColor (COLOR_WINDOWTEXT)); else forecolor = SetTextColor (lpdis->hDC, GetSysColor (COLOR_GRAYTEXT)); bkcolor = SetBkColor (lpdis->hDC, GetSysColor (COLOR_WINDOW)); } ExtTextOut (lpdis->hDC, /* device context */ lpdis->rcItem.left + 2, /* ref point x */ lpdis->rcItem.top + 1, /* ref point y */ ETO_CLIPPED | ETO_OPAQUE, /* options */ &lpdis->rcItem, /* clipping rect */ text, /* text to draw */ lstrlen (text), /* length of text to draw */ NULL /* no kerning array */ ); SetTextColor (lpdis->hDC, forecolor); SetBkColor (lpdis->hDC, bkcolor); if (lpdis->itemState & ODS_FOCUS) DrawFocusRect (lpdis->hDC, &lpdis->rcItem); return 0; } break; case ODT_BUTTON: { HWND parentwindow; parentwindow = GetControlParent (hwnd); SendMessage3ToClean (CcWmDRAWCONTROL, parentwindow, lpdis->hwndItem, lpdis->hDC); if (lpdis->itemState & ODS_SELECTED) InvertRect (lpdis->hDC, &lpdis->rcItem); if (lpdis->itemState & ODS_FOCUS) DrawFocusRect (lpdis->hDC, &lpdis->rcItem); return 0; } break; } return 0; } break; default: return DefWindowProc (hwnd, uMess, wParam, lParam); break; } ErrorExit ("Fatal error: case leak in CompoundControlProcedure (%d).",uMess); } /* End of CompoundControlProcedure callback routine. */ /* Event handler for subclassing the client window of a MDI frame window. This routine catches only WM_WINDOWPOSCHANGING event. */ static LRESULT CALLBACK MDIClientProcedure (HWND hwnd,UINT uMess,WPARAM wParam,LPARAM lParam) { printMessage ("Clean MDI Client", hwnd, uMess, wParam, lParam); switch (uMess) { case WM_WINDOWPOSCHANGING: { WINDOWPOS* wp; RECT tbRect; int tbHeight; HWND hwndFrame, hwndToolbar; wp = (LPWINDOWPOS)lParam; hwndFrame = GetParent (hwnd); hwndToolbar = (HWND)GetGWL_USERDATA (hwndFrame); if (hwndToolbar==0) { tbHeight = 0; } else { GetWindowRect (hwndToolbar,&tbRect); tbHeight = tbRect.bottom - tbRect.top; } wp->y = tbHeight; wp->cy = wp->cy - tbHeight; return 0; } break; } return CallWindowProc ((WNDPROC) stdMDIClientCallback, hwnd, uMess, wParam, lParam); } /* End of MDIClientProcedure callback routine. */ /* There are two event handlers for subclassing edit controls: * EditControlProcedure: This routine should be used for key sensitive edit controls. It processes tab advance if in a dialog, activate/deactivate, keyboard input. * SimpleEditControlProcedure: This routine should be used for non key sensitive edit controls. It processes tab advance if in a dialog, activate/deactivate. */ /* EditControlProcedure. This routine catches all keyboard input and handles it as a standard windows edit control would, but in addition it also sends each keyboard input to Clean. The only exception are tab key presses. For this keyboard input EditControlProcedure first checks if it is inside a Dialog. If so, then the keyfocus is advanced to the next control; otherwise the tab key is also sent to Clean. SetFocus/KillFocus events are passed to Clean as Activate and Deactivate events. All other events are handled as a standard windows edit control. */ static LRESULT CALLBACK EditControlProcedure (HWND hwnd,UINT uMess,WPARAM wParam,LPARAM lParam) { LRESULT stdresult; printMessage ("Clean Edit Control", hwnd, uMess, wParam, lParam); /* First preprocess all messages as if you are a standard Windows edit control. */ stdresult = CallWindowProc ((WNDPROC) stdEditCallback, hwnd, uMess, wParam, lParam); switch (uMess) { case WM_SYSKEYDOWN: case WM_KEYDOWN: { int c = 0; HWND hwndParent; c = CheckVirtualKeyCode ((int) wParam); /* Check if the keyboard input is a tab key. If we're in a Dialog then move focus to next control. */ if (c==WinTabKey) { hwndParent = GetControlParentDialog (hwnd); if (hwndParent!=NULL) /* The EditControl is in a Dialog */ { int modifiers; BOOL bPrevious; HWND hwndNextCtrl; modifiers = GetModifiers (); bPrevious = (BOOL) modifiers & SHIFTBIT; hwndNextCtrl = GetNextDlgTabItem (hwndParent,hwnd,bPrevious); if (hwndNextCtrl != hwnd) /* You're not the only focusable item. */ { SetFocus (hwndNextCtrl); /* Advance key focus to next control. */ } return stdresult; } } /* Check if the keyboard input is a escape key. If we're in a Dialog then further processing should halt, because the message has been passed along the parent hierarchy to cause a WM_CLOSE event. */ if (c==WinEscapeKey) { hwndParent = GetControlParentDialog (hwnd); if (hwndParent!=NULL) /* The EditControl is in a Dialog */ { return stdresult; } } if (!c) /* Ignore non-virtual keys, because they arrive as WM_SYSCHAR and WM_CHAR. */ { return stdresult; } /* Handle virtual keys analogously to keys received as WM_SYSCHAR and WM_CHAR. */ hwndParent = GetControlParent (hwnd); if (gInKey) { if (gCurChar == c) SendKeyStillDownToClean (hwndParent, hwnd, gCurChar); else { SendKeyUpToClean (hwndParent, hwnd, gCurChar); gCurChar = c; SendKeyDownToClean (hwndParent, hwnd, gCurChar); } } else { gCurChar = c; SendKeyDownToClean (hwndParent, hwnd, gCurChar); gInKey = TRUE; } return stdresult; } break; case WM_SYSCHAR: case WM_CHAR: { HWND hwndParent; /* First check if tab/escape key should be suppressed inside Dialog. */ if (((int)wParam == WinTabKey || (int)wParam == WinEscapeKey) && GetControlParentDialog (hwnd) != NULL) { return stdresult; } hwndParent = GetControlParent (hwnd); if (gInKey) { if (gCurChar == (int) wParam) SendKeyStillDownToClean (hwndParent, hwnd, gCurChar); else { SendKeyUpToClean (hwndParent, hwnd, gCurChar); gCurChar = wParam; SendKeyDownToClean (hwndParent, hwnd, gCurChar); } } else { gCurChar = wParam; SendKeyDownToClean (hwndParent, hwnd, gCurChar); gInKey = TRUE; } return stdresult; } break; case WM_SYSKEYUP: case WM_KEYUP: { /* First check if tab/escape key should be suppressed inside Dialog. */ if (((int)wParam == WinTabKey || (int)wParam == WinEscapeKey) && GetControlParentDialog (hwnd) != NULL) { return stdresult; } if (gInKey) SendKeyUpToClean (GetControlParent (hwnd), hwnd, gCurChar); gInKey = FALSE; gCurChar = 0; return stdresult; } break; case WM_KILLFOCUS: { HWND hwndParent = GetControlParent (hwnd); if (gInKey) SendKeyUpToClean (hwndParent, hwnd, gCurChar); gInKey = FALSE; gCurChar = 0; /* WM_KILLFOCUS now also sends the CcWmKILLFOCUS message to Clean (because of the ControlDeactivate attribute). */ SendMessage2ToClean (CcWmKILLFOCUS, hwndParent, hwnd); return stdresult; } break; case WM_SETFOCUS: { /* WM_SETFOCUS sends the CcWmSETFOCUS message to Clean because of the ControlActivate attribute. */ SendMessage2ToClean (CcWmSETFOCUS, GetControlParent (hwnd), hwnd); return stdresult; } break; } return stdresult; } /* End of EditControlProcedure callback routine. */ /* SimpleEditControlProcedure. This routine catches all keyboard input and handles it as a standard windows edit control would. The only exception are tab key presses. For this keyboard input SimpleEditControlProcedure first checks if it is inside a Dialog. If so, then the keyfocus is advanced to the next control. SetFocus/KillFocus events are passed to Clean as Activate and Deactivate events. All other events are handled as a standard windows edit control. */ static LRESULT CALLBACK SimpleEditControlProcedure (HWND hwnd,UINT uMess,WPARAM wParam,LPARAM lParam) { LRESULT stdresult; printMessage ("Clean Simple Edit Control", hwnd, uMess, wParam, lParam); /* First preprocess all messages as if you are a standard Windows edit control. */ stdresult = CallWindowProc ((WNDPROC) stdEditCallback, hwnd, uMess, wParam, lParam); switch (uMess) { case WM_SYSKEYDOWN: case WM_KEYDOWN: { int c = 0; HWND hwndParent; c = CheckVirtualKeyCode ((int) wParam); /* Check if the keyboard input is a tab key. If we're in a Dialog then move focus to next control. */ if (c==WinTabKey) { hwndParent = GetControlParentDialog (hwnd); if (hwndParent!=NULL) /* The EditControl is in a Dialog */ { int modifiers; BOOL bPrevious; HWND hwndNextCtrl; modifiers = GetModifiers (); bPrevious = (BOOL) modifiers & SHIFTBIT; hwndNextCtrl = GetNextDlgTabItem (hwndParent,hwnd,bPrevious); if (hwndNextCtrl != hwnd) /* You're not the only focusable item. */ { SetFocus (hwndNextCtrl); /* Advance key focus to next control. */ } } } return stdresult; } break; case WM_KILLFOCUS: { HWND hwndParent = GetControlParent (hwnd); if (gInKey) SendKeyUpToClean (hwndParent, hwnd, gCurChar); gInKey = FALSE; gCurChar = 0; /* WM_KILLFOCUS now also sends the CcWmKILLFOCUS message to Clean (because of the ControlDeactivate attribute). */ SendMessage2ToClean (CcWmKILLFOCUS, hwndParent, hwnd); return stdresult; } break; case WM_SETFOCUS: { /* WM_SETFOCUS sends the CcWmSETFOCUS message to Clean because of the ControlActivate attribute. */ SendMessage2ToClean (CcWmSETFOCUS, GetControlParent (hwnd), hwnd); return stdresult; } break; } return stdresult; } /* End of SimpleEditControlProcedure callback routine. */ /* Event handler for subclassing editable pop up controls. This routine catches all keyboard input and handles it as a standard windows pop up control would, but in addition it also sends each keyboard input to Clean. All other events are handled as a standard windows pop up control. */ static LRESULT CALLBACK PopUpControlProcedure (HWND hwnd,UINT uMess,WPARAM wParam,LPARAM lParam) { LRESULT stdresult; printMessage ("Clean PopUp Control", hwnd, uMess, wParam, lParam); /* First preprocess all messages as if you are a standard Windows edit control of a combobox. */ stdresult = CallWindowProc ((WNDPROC) stdPopUpCallback, hwnd, uMess, wParam, lParam); switch (uMess) { case WM_SYSKEYDOWN: case WM_KEYDOWN: { int c = 0; HWND hwndParent; HWND hwndCombo; c = CheckVirtualKeyCode ((int) wParam); if (!c) /* Ignore non-virtual keys, because they arrive as WM_SYSCHAR and WM_CHAR. */ { return stdresult; } /* Handle virtual keys analogously to keys received as WM_SYSCHAR and WM_CHAR. */ hwndCombo = GetParent (hwnd); hwndParent = GetControlParent (hwndCombo); if (gInKey) { if (gCurChar == c) SendKeyStillDownToClean (hwndParent, hwndCombo, gCurChar); else { SendKeyUpToClean (hwndParent, hwndCombo, gCurChar); gCurChar = c; SendKeyDownToClean (hwndParent, hwndCombo, gCurChar); } } else { gCurChar = c; SendKeyDownToClean (hwndParent, hwndCombo, gCurChar); gInKey = TRUE; } return stdresult; } break; case WM_SYSCHAR: case WM_CHAR: { HWND hwndCombo = GetParent (hwnd); HWND hwndParent = GetControlParent (hwndCombo); if (gInKey) { if (gCurChar == (int) wParam) SendKeyStillDownToClean (hwndParent, hwndCombo, gCurChar); else { SendKeyUpToClean (hwndParent, hwndCombo, gCurChar); gCurChar = wParam; SendKeyDownToClean (hwndParent, hwndCombo, gCurChar); } } else { gCurChar = wParam; SendKeyDownToClean (hwndParent, hwndCombo, gCurChar); gInKey = TRUE; } return stdresult; } break; case WM_SYSKEYUP: case WM_KEYUP: { HWND hwndCombo = GetParent (hwnd); HWND hwndParent = GetControlParent (hwndCombo); if (gInKey) SendKeyUpToClean (hwndParent, hwndCombo, gCurChar); gInKey = FALSE; gCurChar = 0; return stdresult; } break; case WM_KILLFOCUS: { HWND hwndCombo = GetParent (hwnd); HWND hwndParent = GetControlParent (hwndCombo); if (gInKey) SendKeyUpToClean (hwndParent, hwndCombo, gCurChar); gInKey = FALSE; gCurChar = 0; /* WM_KILLFOCUS now also sends the CcWmKILLFOCUS message to Clean (because of the ControlDeactivate attribute). */ SendMessage2ToClean (CcWmKILLFOCUS, hwndParent, hwndCombo); return stdresult; } break; /* Send CcWmGETFOCUS message to Clean because of the ControlActivate attribute. */ case WM_SETFOCUS: { HWND hwndCombo = GetParent (hwnd); HWND hwndParent = GetControlParent (hwndCombo); SendMessage2ToClean (CcWmSETFOCUS, hwndParent, hwndCombo); return stdresult; } break; } return stdresult; } /* End of PopUpControlProcedure callback routine. */ /* Callback routine for SDI client windows. The callback routine handles all events for the client window of a SDI window. The accelerator table is now managed by its parent SDI frame window callback routine. */ static LRESULT CALLBACK SDIWindowProcedure (HWND hWin,UINT uMess,WPARAM wPara,LPARAM lPara) { printMessage ("Clean SDI Window", hWin, uMess, wPara, lPara); switch (uMess) { case WM_COMMAND: { switch (HIWORD (wPara)) { case 0: /* 0: message originates from a menu or equals BN_CLICKED */ { if (lPara != 0) /* It was BN_CLICKED. */ { /* Send also modifiers to Clean */ SendMessage4ToClean (CcWmBUTTONCLICKED, hWin, lPara, GetModifiers (), LOWORD (wPara)); } else /* It was from a menu. */ { SendMessage2ToClean (CcWmCOMMAND, LOWORD (wPara), GetModifiers ()); } } break; case 1: /* 1: message originates from an accelerator */ { SendMessage2ToClean (CcWmCOMMAND, LOWORD (wPara), GetModifiers ()); } break; case CBN_SETFOCUS: { gComboSelection = SendMessage ((HWND) lPara, CB_GETCURSEL, 0, 0); } break; case CBN_KILLFOCUS: { gComboSelection = -1; } break; case CBN_SELENDOK: { char text[256]; int newsel; HWND combo; combo = (HWND) lPara; newsel = SendMessage (combo, CB_GETCURSEL, 0, 0); SendMessage (combo, CB_GETLBTEXT, newsel, (LPARAM) text); if (!SendMessage (combo, CB_GETITEMDATA, newsel, 0)) { SendMessage (combo, CB_SETCURSEL, gComboSelection, (LPARAM) text); MessageBeep (0xFFFFFFFF); return 0; } else { gComboSelection = newsel; if (newsel!=CB_ERR) SendMessage3ToClean (CcWmCOMBOSELECT, hWin, combo, newsel); return 1; } } break; } } break; case WM_PAINT: { RECT updaterect; HDC hdc; PAINTSTRUCT ps; if (GetUpdateRect (hWin, &updaterect, FALSE)) { hdc = BeginPaint (hWin, &ps); if (updaterect.left != updaterect.right && updaterect.top != updaterect.bottom) SendMessage6ToClean (CcWmPAINT, hWin, updaterect.left,updaterect.top,updaterect.right,updaterect.bottom,hdc); EndPaint (hWin, &ps); } else { GetClientRect (hWin, &updaterect); SendMessage6ToClean (CcWmPAINT, hWin, updaterect.left, updaterect.top, updaterect.right, updaterect.bottom,wPara); } return 0; //PAPAPA } break; case WM_SETCURSOR: { int cursorcode; LocalWindowData wdata; if (gGlobalCursorCode == -1) { if ((HWND) wPara != hWin || LOWORD (lPara) != HTCLIENT) { return DefWindowProc (hWin, uMess, wPara, lPara); } wdata = (LocalWindowData) GetWindowLong (hWin,0); cursorcode = wdata->lwd_cursorcode; } else { cursorcode = gGlobalCursorCode; } SetCursorFromCode (cursorcode); } break; case WM_SYSCHAR: case WM_CHAR: { if (gInKey) { if (gCurChar == (int) wPara) SendKeyStillDownToClean (hWin, hWin, gCurChar); else { SendKeyUpToClean (hWin, hWin, gCurChar); gCurChar = wPara; SendKeyDownToClean (hWin, hWin, gCurChar); } } else { gCurChar = wPara; SendKeyDownToClean (hWin, hWin, gCurChar); gInKey = TRUE; } } break; case WM_SYSKEYUP: case WM_KEYUP: { if (gInKey) SendKeyUpToClean (hWin, hWin, gCurChar); gInKey = FALSE; gCurChar = 0; return (DefWindowProc (hWin, uMess, wPara, lPara)); } break; case WM_KILLFOCUS: { if (gInKey) SendKeyUpToClean (hWin, hWin, gCurChar); gInKey = FALSE; gCurChar = 0; } break; case WM_LBUTTONDOWN: { SendMouseDownToClean (hWin, hWin, SIGNEDLOWORD (lPara), SIGNEDHIWORD (lPara)); } break; case WM_MOUSEMOVE: { if (gInMouseDown) { SendMouseStillDownToClean (hWin, hWin, SIGNEDLOWORD (lPara), SIGNEDHIWORD (lPara)); } else { SendMouseStillUpToClean (hWin, hWin, SIGNEDLOWORD (lPara), SIGNEDHIWORD (lPara)); } } break; case WM_LBUTTONUP: { if (gInMouseDown) { ReleaseCapture (); /* rely on WM_CAPTURECHANGED to send the mouseUp event */ } } break; case WM_CANCELMODE: { if (gInMouseDown) { ReleaseCapture (); /* rely on WM_CAPTURECHANGED to send the mouseUp event */ } return DefWindowProc (hWin, uMess, wPara, lPara); } break; case WM_CAPTURECHANGED: { if (gInMouseDown) { POINT p; GetCursorPos (&p); ScreenToClient (hWin, &p); SendMouseUpToClean (hWin, hWin, p.x, p.y); } } break; case WM_TIMER: { if ((int) wPara == -1) { POINT p; GetCursorPos (&p); ScreenToClient (hWin, &p); SendMouseStillDownToClean (hWin, hWin, p.x, p.y); } else { rprintf ("Clean Window did not expect normal WM_TIMER message with id = %d.\n", wPara); } } break; /* The WM_CREATE message should cause the SDI client window to notify Clean that its controls can be built. The accelerator table is maintained by the SDI frame window. In addition, the LocalWindowData is created and stored in the local memory of the SDI window. */ case WM_CREATE: { LocalWindowData wdata; wdata = AllocateLocalWindowData (); // create the LocalWindowData struct SetWindowLong (hWin, 0, (long) wdata); // and store it in the local memory of the window SendMessage1ToClean (CcWmCREATE, hWin); /* After creation of the window controls, their HFONT should be set to 8pt "MS Sans Serif" */ EnumChildWindows (hWin, SetControlFontProc, (LPARAM) gControlFont); } break; /* The WM_DESTROY message should free the local SDI window memory. */ case WM_DESTROY: { LocalWindowData wdata; wdata = (LocalWindowData) GetWindowLong (hWin,0); // get the local SDI window data DestroyLocalWindowData (wdata); // and destroy it. return 0; } break; /* The cases WM_ENTERSIZEMOVE and WM_EXITSIZEMOVE flag the lwd_usersizemove field of the LocalWindowData of the window. This is used to determine whether the window should be redrawn in case of resizing. */ case WM_ENTERSIZEMOVE: { LocalWindowData wdata; wdata = (LocalWindowData) GetWindowLong (hWin,0); wdata->lwd_usersizemoving = (BOOL)TRUE; SetWindowLong (hWin, 0, (long)wdata); } break; case WM_EXITSIZEMOVE: { LocalWindowData wdata; wdata = (LocalWindowData) GetWindowLong (hWin,0); wdata->lwd_usersizemoving = (BOOL)FALSE; SetWindowLong (hWin, 0, (long)wdata); } break; /* The WM_SIZE message informs Clean about the new size. */ case WM_SIZE: { if (wPara != SIZE_MAXHIDE && wPara != SIZE_MAXSHOW) { int width,height; LocalWindowData wdata; width = LOWORD (lPara); // Width of window excluding vertical scrollbar height = HIWORD (lPara); // Height of window excluding horizontal scrollbar wdata = (LocalWindowData) GetWindowLong (hWin,0); UpdateWindow (hWin); // But first update the window SendMessage4ToClean (CcWmSIZE, hWin, width, height, (int)wdata->lwd_usersizemoving); } } break; case WM_HSCROLL: { int nPos,nScrollCode,controlkind; HWND hwndScrollBar; nScrollCode = LOWORD (wPara); if (nScrollCode != SB_ENDSCROLL) /* Do not send the SB_ENDSCROLL to Clean. */ { nPos = (short int) HIWORD (wPara); hwndScrollBar = (HWND) lPara; if (hwndScrollBar==0) { controlkind = SB_HORZ; /* lPara==0 in case of Window scrollbars. */ hwndScrollBar = hWin; /* pass the compound control handle to Clean. */ UpdateWindow (hWin); /* but first ensure that window is updated. */ } else { controlkind = SB_CTL; /* lPara!=0 in case of SliderControls. */ } SendMessage5ToClean (CcWmSCROLLBARACTION, hWin, hwndScrollBar, controlkind, nScrollCode, nPos); } } break; case WM_VSCROLL: { int nPos,nScrollCode,controlkind; HWND hwndScrollBar; nScrollCode = LOWORD (wPara); if (nScrollCode != SB_ENDSCROLL) /* Do not send the SB_ENDSCROLL to Clean. */ { nPos = (short int) HIWORD (wPara); hwndScrollBar = (HWND) lPara; if (hwndScrollBar==0) { controlkind = SB_VERT; /* lPara==0 in case of Window scrollbars. */ hwndScrollBar = hWin; /* pass the window handle to Clean. */ UpdateWindow (hWin); /* but first ensure that window is updated. */ } else { controlkind = SB_CTL; /* lPara!=0 in case of SliderControls. */ } SendMessage5ToClean (CcWmSCROLLBARACTION, hWin, hwndScrollBar, controlkind, nScrollCode, nPos); } } break; case WM_DRAWITEM: { LPDRAWITEMSTRUCT lpdis; lpdis = (LPDRAWITEMSTRUCT) lPara; switch (lpdis->CtlType) { case ODT_COMBOBOX: { char text[256]; COLORREF forecolor, bkcolor; SendMessage (lpdis->hwndItem, CB_GETLBTEXT, lpdis->itemID, (LPARAM) text); if (lpdis->itemState & ODS_DISABLED) { forecolor = SetTextColor (lpdis->hDC, GetSysColor (COLOR_GRAYTEXT)); bkcolor = SetBkColor (lpdis->hDC, GetSysColor (COLOR_3DFACE)); } else if (lpdis->itemState & ODS_SELECTED) { if (lpdis->itemData) { forecolor = SetTextColor (lpdis->hDC, GetSysColor (COLOR_HIGHLIGHTTEXT)); bkcolor = SetBkColor (lpdis->hDC, GetSysColor (COLOR_HIGHLIGHT)); } else { forecolor = SetTextColor (lpdis->hDC, GetSysColor (COLOR_GRAYTEXT)); bkcolor = SetBkColor (lpdis->hDC, GetSysColor (COLOR_WINDOW)); } } else { if (lpdis->itemData) forecolor = SetTextColor (lpdis->hDC, GetSysColor (COLOR_WINDOWTEXT)); else forecolor = SetTextColor (lpdis->hDC, GetSysColor (COLOR_GRAYTEXT)); bkcolor = SetBkColor (lpdis->hDC, GetSysColor (COLOR_WINDOW)); } ExtTextOut (lpdis->hDC, /* device context */ lpdis->rcItem.left + 2, /* ref point x */ lpdis->rcItem.top + 1, /* ref point y */ ETO_CLIPPED | ETO_OPAQUE, /* options */ &lpdis->rcItem, /* clipping rect */ text, /* text to draw */ lstrlen (text), /* length of text to draw */ NULL /* no kerning array */ ); SetTextColor (lpdis->hDC, forecolor); SetBkColor (lpdis->hDC, bkcolor); if (lpdis->itemState & ODS_FOCUS) DrawFocusRect (lpdis->hDC, &lpdis->rcItem); } break; case ODT_BUTTON: { { SendMessage3ToClean (CcWmDRAWCONTROL, hWin, lpdis->hwndItem, lpdis->hDC); if (lpdis->itemState & ODS_SELECTED) InvertRect (lpdis->hDC, &lpdis->rcItem); if (lpdis->itemState & ODS_FOCUS) DrawFocusRect (lpdis->hDC, &lpdis->rcItem); }; return TRUE; } break; } } break; } return DefWindowProc (hWin,uMess,wPara,lPara); } /* End of SDIWindowProcedure callback routine. */ /* Callback routine for SDI frame window procedure. This routine handles the SDI frame events. These concern menus, toolbar, resizes. Also the accelerator table is kept at the frame window (analogous to MDI frame window). When resized, also the SDI client window (see previous callback routine) is notified. Note that whenever Clean is informed about an event, the GetSDIClientWindow(hWin) value should be passed to Clean which identifies the Clean SDI client window! The only exception is the CcWmPROCESSCLOSE message. */ static LRESULT CALLBACK SDIFrameProcedure (HWND hWin,UINT uMess,WPARAM wPara,LPARAM lPara) { printMessage ("Clean SDIFrameWindow",hWin,uMess,wPara,lPara); switch (uMess) { case WM_COMMAND: { switch (HIWORD (wPara)) { case 0: /* 0: message originates from a menu or equals BN_CLICKED */ { if (lPara != 0) /* PA: it was BN_CLICKED. */ { /* hwndClient can't be NULL, because a button has been pressed. */ HWND hwndClient = GetSDIClientWindow (hWin); /* Send also modifiers to Clean */ SendMessage4ToClean (CcWmBUTTONCLICKED, hwndClient, lPara, GetModifiers (), LOWORD (wPara)); } else /* It was from a menu. */ { SendMessage2ToClean (CcWmCOMMAND, LOWORD (wPara), GetModifiers ()); } } break; case 1: /* 1: message originates from an accelerator */ { SendMessage2ToClean (CcWmCOMMAND, LOWORD (wPara), GetModifiers ()); } break; case CBN_SETFOCUS: { gComboSelection = SendMessage ((HWND) lPara, CB_GETCURSEL, 0, 0); } break; case CBN_KILLFOCUS: { gComboSelection = -1; } break; case CBN_SELENDOK: { char text[256]; int newsel; HWND combo; combo = (HWND) lPara; newsel = SendMessage (combo, CB_GETCURSEL, 0, 0); SendMessage (combo, CB_GETLBTEXT, newsel, (LPARAM) text); if (!SendMessage (combo, CB_GETITEMDATA, newsel, 0)) { SendMessage (combo, CB_SETCURSEL, gComboSelection, (LPARAM) text); MessageBeep (0xFFFFFFFF); return 0; } else { gComboSelection = newsel; if (newsel!=CB_ERR) { HWND hwndClient = GetSDIClientWindow (hWin); SendMessage3ToClean (CcWmCOMBOSELECT, hwndClient, combo, newsel); } return 1; } } break; } } break; /* WM_NOTIFY is handled identically as for MDI client windows (see MDIClientProcedure). */ case WM_NOTIFY: { LPNMHDR pnmh = (LPNMHDR) lPara; LPTOOLTIPTEXT lpttt = (LPTOOLTIPTEXT) lPara; UINT from, flags; from = lpttt->hdr.idFrom; flags= lpttt->uFlags; if (pnmh->code == TTN_NEEDTEXT && from != 0 && flags != TTF_IDISHWND) { HWND hwndToolbar; hwndToolbar = (HWND)GetGWL_USERDATA (hWin); // get tooltip text from Clean SendMessage2ToClean (CcWmGETTOOLBARTIPTEXT, hwndToolbar, from); lstrcpy (lpttt->szText,(LPSTR)gCci.p1); if (gCci.p1 != 0) rfree ((HGLOBAL) gCci.p1); return 0; } return (DefWindowProc (hWin, uMess, wPara, lPara)); } break; case WM_CLOSE: /* The SDI frame window is requested to be closed. */ { SendMessage1ToClean (CcWmPROCESSCLOSE, hWin); return 0; } break; case WM_DESTROY: /* The SDI frame window is in the act of being closed. */ { ProcessShortcutTable shortcuts; ghTopDocWindow=NULL; AdjustMenuBarName (); shortcuts = (ProcessShortcutTable) GetWindowLong (hWin, 0); // get the local shortcut table DestroyProcessShortcutTable (shortcuts); // and destroy it. gAcceleratorTableIsUpToDate = FALSE; // The active global accelerator table is not up to date DragAcceptFiles (hWin,FALSE); /* Unregister for WM_DROPFILES events. */ return 0; } break; /* WM_ENTERIDLE message is used to let Clean evaluate the initialisation action of a modal dialog by sending the CcWmIDLEDIALOG message. */ case WM_ENTERIDLE: { HWND hwndModalDialog; hwndModalDialog = (HWND)lPara; if (wPara == MSGF_DIALOGBOX && hwndModalDialog != ghwndLastModalDialog) { SendMessage1ToClean (CcWmIDLEDIALOG,(int)hwndModalDialog); ghwndLastModalDialog = hwndModalDialog; } else { SendMessage0ToClean (CcWmIDLETIMER); } return 0; } break; case WM_ENTERMENULOOP: { gProhibitWindowActivation++; } break; case WM_EXITMENULOOP: { gProhibitWindowActivation--; } break; case WM_SYSCHAR: case WM_CHAR: { HWND hwndClient = GetSDIClientWindow (hWin); if (hwndClient != NULL) { if (gInKey) { if (gCurChar == (int) wPara) SendKeyStillDownToClean (hwndClient, hwndClient, gCurChar); else { SendKeyUpToClean (hwndClient, hwndClient, gCurChar); gCurChar = wPara; SendKeyDownToClean (hwndClient, hwndClient, gCurChar); } } else { gCurChar = wPara; SendKeyDownToClean (hwndClient, hwndClient, gCurChar); gInKey = TRUE; } } } break; case WM_SYSKEYUP: case WM_KEYUP: { HWND hwndClient = GetSDIClientWindow (hWin); if (hwndClient != NULL && gInKey) { SendKeyUpToClean (hwndClient, hwndClient, gCurChar); } gInKey = FALSE; gCurChar = 0; return (DefWindowProc (hWin, uMess, wPara, lPara)); } break; case WM_KILLFOCUS: { HWND hwndClient = GetSDIClientWindow (hWin); if (hwndClient != NULL && gInKey) { SendKeyUpToClean (hwndClient, hwndClient, gCurChar); } gInKey = FALSE; gCurChar = 0; } break; case WM_LBUTTONDOWN: { HWND hwndClient = GetSDIClientWindow (hWin); if (hwndClient != NULL) { SendMouseDownToClean (hwndClient, hwndClient, SIGNEDLOWORD (lPara), SIGNEDHIWORD (lPara)); } } break; case WM_MOUSEMOVE: { HWND hwndClient = GetSDIClientWindow (hWin); if (hwndClient != NULL) { if (gInMouseDown) { SendMouseStillDownToClean (hwndClient, hwndClient, SIGNEDLOWORD (lPara), SIGNEDHIWORD (lPara)); } else { SendMouseStillUpToClean (hwndClient, hwndClient, SIGNEDLOWORD (lPara), SIGNEDHIWORD (lPara)); } } } break; case WM_LBUTTONUP: { if (gInMouseDown) { ReleaseCapture (); /* rely on WM_CAPTURECHANGED to send the mouseUp event */ } } break; case WM_CANCELMODE: { if (gInMouseDown) { ReleaseCapture (); /* rely on WM_CAPTURECHANGED to send the mouseUp event */ } return DefWindowProc (hWin, uMess, wPara, lPara); } break; case WM_CAPTURECHANGED: { HWND hwndClient = GetSDIClientWindow (hWin); if (hwndClient != NULL && gInMouseDown) { POINT p; GetCursorPos (&p); ScreenToClient (hwndClient, &p); SendMouseUpToClean (hwndClient, hwndClient, p.x, p.y); } } break; case WM_TIMER: { HWND hwndClient = GetSDIClientWindow (hWin); if (hwndClient != NULL && (int) wPara == -1) { POINT p; GetCursorPos (&p); ScreenToClient (hwndClient, &p); SendMouseStillDownToClean (hwndClient, hwndClient, p.x, p.y); } else { rprintf ("Clean Window did not expect normal WM_TIMER message with id = %d.\n", wPara); } } break; case WM_ACTIVATE: { HWND hwndClient = GetSDIClientWindow (hWin); if (LOWORD (wPara) != WA_INACTIVE) { if (hwndClient != NULL) SendMessage1ToClean (CcWmACTIVATE, hwndClient); ghTopDocWindow = hWin; // PA: shouldn't this be hwndClient? ghActiveFrameWindow = hWin; ghActiveClientWindow = NULL; // PA: shouldn't this be hwndClient? } else if (LOWORD (wPara) == WA_INACTIVE) { if (hwndClient != NULL) SendMessage1ToClean (CcWmDEACTIVATE, hwndClient); ghTopDocWindow = NULL; ghActiveFrameWindow = NULL; ghActiveClientWindow = NULL; gAcceleratorTableIsUpToDate = FALSE; // The active global accelerator table is not up to date } AdjustMenuBarName (); return DefWindowProc (hWin, uMess, wPara, lPara); } break; /* The WM_CREATE message should cause the SDI frame window only to create the accelerator table. The crosscall request from Clean to create the SDI window will create the SDI client. The SDI client will notify Clean that the controls can be created. */ case WM_CREATE: { ProcessShortcutTable shortcuts; shortcuts = AllocateProcessShortcutTable (MINSIZEPROCESSSHORTCUTTABLE); // create a new shortcut table SetWindowLong (hWin, 0, (long) shortcuts); // and store it in the local memory of the window gAcceleratorTableIsUpToDate = FALSE; // The active global accelerator table is not up to date ghActiveFrameWindow = hWin; // Keep track of the active frame window ghActiveClientWindow = NULL; // and client window } break; /* The WM_SIZE message resizes the toolbar if present and makes sure that the SDI client window is also resized by sending it the same size message, but with the toolbar height subtracted. */ case WM_SIZE: { HWND hwndToolbar,hwndClient; RECT toolbarRect; int toolbarHeight = 0; /* Also resize the toolbar if present. */ hwndToolbar = (HWND)GetGWL_USERDATA (hWin); if (hwndToolbar != NULL) { SendMessage (hwndToolbar, TB_AUTOSIZE, (WPARAM)0, (LPARAM)0); UpdateWindow (hwndToolbar); if (!GetWindowRect(hwndToolbar,&toolbarRect)) rMessageBox (NULL,MB_APPLMODAL,"SDIFrameProcedure","GetWindowRect (hwndToolbar,_) failed"); toolbarHeight = toolbarRect.bottom - toolbarRect.top; } hwndClient = GetSDIClientWindow (hWin); if (hwndClient != NULL) { SetWindowPos (hwndClient, /* the SDI client */ HWND_BOTTOM, /* this value is ignored (SWP_NOZORDER) */ 0,0, /* these values are ignored (SWP_NOMOVE) */ (int)LOWORD (lPara),(int)HIWORD (lPara)-toolbarHeight, /* new width and height */ SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOREDRAW ); } } break; /* Accept the user dropping file(s) in the frame window. */ case WM_DROPFILES: { SendDropFilesToClean (hWin,wPara); } return 0; break; } return DefWindowProc (hWin,uMess,wPara,lPara); } /* End of SDIFrameProcedure callback routine. */ /* Callback routine for MDI document window procedure. Copied almost straight from SDIWindowProcedure. Differences are: - WM_COMMAND can not originate from menu selections (handled by MDIFrameProcedure); - DefWindowProc must be DefMDIChildProc; - Instead of WM_ACTIVATE, a MDI document window receives WM_MDIACTIVATE messages. However, these do not work well when dialogs are involved. Instead WM_NCACTIVATE messages are checked. */ static LRESULT CALLBACK MDIWindowProcedure (HWND hWin,UINT uMess,WPARAM wPara,LPARAM lPara) { printMessage ("Clean MDI Doc Window",hWin,uMess,wPara,lPara); switch (uMess) { case WM_COMMAND: { switch (HIWORD (wPara)) { case BN_CLICKED: { if (lPara != 0) { /* Send modifiers also to Clean */ SendMessage4ToClean (CcWmBUTTONCLICKED, hWin, lPara, GetModifiers (), LOWORD (wPara)); } } break; case 1: /* 1: message originates from an accelerator */ { SendMessage2ToClean (CcWmCOMMAND, LOWORD (wPara), GetModifiers ()); } break; case CBN_SETFOCUS: { gComboSelection = SendMessage ((HWND) lPara, CB_GETCURSEL, 0, 0); } break; case CBN_KILLFOCUS: { gComboSelection = -1; } break; case CBN_SELENDOK: { char text[256]; int newsel; HWND combo; combo = (HWND) lPara; newsel = SendMessage (combo, CB_GETCURSEL, 0, 0); SendMessage (combo, CB_GETLBTEXT, newsel, (LPARAM) text); if (!SendMessage (combo, CB_GETITEMDATA, newsel, 0)) { SendMessage (combo, CB_SETCURSEL, gComboSelection, (LPARAM) text); MessageBeep (0xFFFFFFFF); return 0; } else { gComboSelection = newsel; if (newsel!=CB_ERR) SendMessage3ToClean (CcWmCOMBOSELECT, hWin, combo, newsel); return 1; } } break; } } break; case WM_PAINT: { RECT updaterect; HDC hdc; PAINTSTRUCT ps; if (GetUpdateRect (hWin, &updaterect, FALSE)) { hdc = BeginPaint (hWin, &ps); if (updaterect.left != updaterect.right && updaterect.top != updaterect.bottom) SendMessage6ToClean (CcWmPAINT, hWin, updaterect.left,updaterect.top,updaterect.right,updaterect.bottom,hdc); EndPaint (hWin, &ps); } else { GetClientRect (hWin, &updaterect); SendMessage6ToClean (CcWmPAINT, hWin, updaterect.left,updaterect.top,updaterect.right,updaterect.bottom,wPara); } return 0; } case WM_CLOSE: /* The window is requested to be closed. */ { SendMessage1ToClean (CcWmCLOSE, hWin); return 0; } case WM_DESTROY: /* The window is in the act of being closed. */ { LocalWindowData wdata; wdata = (LocalWindowData) GetWindowLong (hWin,0); // Get the local MDI window data DestroyLocalWindowData (wdata); // and destroy it. ghTopDocWindow=NULL; AdjustMenuBarName (); return 0; } case WM_ENTERMENULOOP: { gProhibitWindowActivation++; } break; case WM_EXITMENULOOP: { gProhibitWindowActivation--; } break; case WM_SETCURSOR: { int cursorcode; LocalWindowData wdata; if (gGlobalCursorCode == -1) { if ((HWND) wPara != hWin || LOWORD (lPara) != HTCLIENT) { return DefMDIChildProc (hWin, uMess, wPara, lPara); } wdata = (LocalWindowData) GetWindowLong (hWin,0); cursorcode = wdata->lwd_cursorcode; } else { cursorcode = gGlobalCursorCode; } SetCursorFromCode (cursorcode); } break; case WM_SYSCHAR: case WM_CHAR: { if (gInKey) { if (gCurChar == (int) wPara) SendKeyStillDownToClean (hWin, hWin, gCurChar); else { SendKeyUpToClean (hWin, hWin, gCurChar); gCurChar = wPara; SendKeyDownToClean (hWin, hWin, gCurChar); } } else { gCurChar = wPara; SendKeyDownToClean (hWin, hWin, gCurChar); gInKey = TRUE; } return 0; } break; case WM_SYSKEYUP: case WM_KEYUP: { if (gInKey) SendKeyUpToClean (hWin, hWin, gCurChar); gInKey = FALSE; gCurChar = 0; return (DefMDIChildProc (hWin, uMess, wPara, lPara)); } break; case WM_KILLFOCUS: { if (gInKey) SendKeyUpToClean (hWin, hWin, gCurChar); gInKey = FALSE; gCurChar = 0; } break; case WM_LBUTTONDOWN: { SendMouseDownToClean (hWin, hWin, SIGNEDLOWORD (lPara), SIGNEDHIWORD (lPara)); return 0; } break; case WM_MOUSEMOVE: { if (gInMouseDown) { SendMouseStillDownToClean (hWin, hWin, SIGNEDLOWORD (lPara), SIGNEDHIWORD (lPara)); } else { SendMouseStillUpToClean (hWin, hWin, SIGNEDLOWORD (lPara), SIGNEDHIWORD (lPara)); } return 0; } break; case WM_LBUTTONUP: { if (gInMouseDown) { ReleaseCapture (); /* rely on WM_CAPTURECHANGED to send the mouseUp event */ } } break; case WM_CANCELMODE: { if (gInMouseDown) { ReleaseCapture (); /* rely on WM_CAPTURECHANGED to send the mouseUp event */ } return DefMDIChildProc (hWin, uMess, wPara, lPara); } break; case WM_CAPTURECHANGED: { if (gInMouseDown) { POINT p; GetCursorPos (&p); ScreenToClient (hWin, &p); SendMouseUpToClean (hWin, hWin, p.x, p.y); } } break; case WM_TIMER: { if ((int) wPara == -1) { POINT p; GetCursorPos (&p); ScreenToClient (hWin, &p); SendMouseStillDownToClean (hWin, hWin, p.x, p.y); } else { rprintf ("Clean Window did not expect normal WM_TIMER message with id = %d.\n", wPara); } } break; /* Instead of using WM_MDIACTIVATE to know the activation state of a MDI document window, we use WM_NCACTIVATE. This is because WM_MDIACTIVATE events are not generated when dialogs are involved. The WM_NCACTIVATE is more robust because it is used by the system to change the active state of the window title bar. Incidentally to many WM_NCACTIVATE message can be generated. This has to be dealt with on the Clean side. */ case WM_NCACTIVATE: { BOOL fActive = (BOOL)wPara; if (fActive) { SendMessage1ToClean (CcWmACTIVATE, hWin); ghTopDocWindow = hWin; ghActiveClientWindow = GetParent (hWin); ghActiveFrameWindow = GetParent (ghActiveClientWindow); UpdateWindow (hWin); // enforce update at Clean side (necessary for setActiveWindow) } else { SendMessage1ToClean (CcWmDEACTIVATE, hWin); ghTopDocWindow = NULL; ghActiveFrameWindow = NULL; ghActiveClientWindow = NULL; } AdjustMenuBarName (); return DefMDIChildProc (hWin, uMess, wPara, lPara); } break; /* The WM_CREATE message notifies Clean that its controls can be built. In addition, the LocalWindowData is created and stored in the local memory of the MDI window. */ case WM_CREATE: { LocalWindowData wdata; wdata = AllocateLocalWindowData (); // create the LocalWindowData struct SetWindowLong (hWin, 0, (long) wdata); // and store it in the local memory of the window SendMessage1ToClean (CcWmCREATE, hWin); /* After creation of the window controls, their HFONT should be set to 8pt "MS Sans Serif" */ EnumChildWindows (hWin, SetControlFontProc, (LPARAM) gControlFont); } break; /* The cases WM_ENTERSIZEMOVE and WM_EXITSIZEMOVE flag the lwd_usersizemove field of the LocalWindowData of the window. This is used to determine whether the window should be redrawn in case of resizing. */ case WM_ENTERSIZEMOVE: { LocalWindowData wdata; wdata = (LocalWindowData) GetWindowLong (hWin,0); wdata->lwd_usersizemoving = (BOOL)TRUE; SetWindowLong (hWin, 0, (long)wdata); } break; case WM_EXITSIZEMOVE: { LocalWindowData wdata; wdata = (LocalWindowData) GetWindowLong (hWin,0); wdata->lwd_usersizemoving = (BOOL)FALSE; SetWindowLong (hWin, 0, (long)wdata); } break; case WM_SIZE: { HWND hwndToolbar; hwndToolbar = (HWND) GetGWL_USERDATA (hWin); // First resize the toolbar if present if (hwndToolbar!=NULL) SendMessage (hwndToolbar, TB_AUTOSIZE, (WPARAM)0, (LPARAM)0); if (wPara != SIZE_MAXHIDE && wPara != SIZE_MAXSHOW) { int width,height; LocalWindowData wdata; width = LOWORD (lPara); // Width of window excluding vertical scrollbar height = HIWORD (lPara); // Height of window excluding horizontal scrollbar wdata = (LocalWindowData) GetWindowLong (hWin,0); UpdateWindow (hWin); // But first update the window SendMessage4ToClean (CcWmSIZE, hWin, width, height, (int)wdata->lwd_usersizemoving); } } break; case WM_HSCROLL: { int nPos,nScrollCode,controlkind; HWND hwndScrollBar; nScrollCode = LOWORD (wPara); if (nScrollCode != SB_ENDSCROLL) /* Do not send the SB_ENDSCROLL to Clean. */ { nPos = (short int) HIWORD (wPara); hwndScrollBar = (HWND) lPara; if (hwndScrollBar==0) { controlkind = SB_HORZ; /* lPara==0 in case of Window scrollbars. */ hwndScrollBar = hWin; /* pass the window handle to Clean. */ UpdateWindow (hWin); /* but first ensure that window is updated. */ } else { controlkind = SB_CTL; /* lPara!=0 in case of SliderControls. */ } SendMessage5ToClean (CcWmSCROLLBARACTION, hWin, hwndScrollBar, controlkind, nScrollCode, nPos); } } break; case WM_VSCROLL: { int nPos,nScrollCode,controlkind; HWND hwndScrollBar; nScrollCode = LOWORD (wPara); if (nScrollCode != SB_ENDSCROLL) /* Do not send the SB_ENDSCROLL to Clean. */ { nPos = (short int) HIWORD (wPara); hwndScrollBar = (HWND) lPara; if (hwndScrollBar==0) { controlkind = SB_VERT; /* lPara==0 in case of Window scrollbars. */ hwndScrollBar = hWin; /* pass the window handle to Clean. */ UpdateWindow (hWin); /* but first ensure that window is updated. */ } else { controlkind = SB_CTL; /* lPara!=0 in case of SliderControls. */ } SendMessage5ToClean (CcWmSCROLLBARACTION, hWin, hwndScrollBar, controlkind, nScrollCode, nPos); } } break; case WM_DRAWITEM: { LPDRAWITEMSTRUCT lpdis; lpdis = (LPDRAWITEMSTRUCT) lPara; switch (lpdis->CtlType) { case ODT_COMBOBOX: { char text[256]; COLORREF forecolor, bkcolor; SendMessage (lpdis->hwndItem, CB_GETLBTEXT, lpdis->itemID, (LPARAM) text); if (lpdis->itemState & ODS_DISABLED) { forecolor = SetTextColor (lpdis->hDC, GetSysColor (COLOR_GRAYTEXT)); bkcolor = SetBkColor (lpdis->hDC, GetSysColor (COLOR_3DFACE)); } else if (lpdis->itemState & ODS_SELECTED) { if (lpdis->itemData) { forecolor = SetTextColor (lpdis->hDC, GetSysColor (COLOR_HIGHLIGHTTEXT)); bkcolor = SetBkColor (lpdis->hDC, GetSysColor (COLOR_HIGHLIGHT)); } else { forecolor = SetTextColor (lpdis->hDC, GetSysColor (COLOR_GRAYTEXT)); bkcolor = SetBkColor (lpdis->hDC, GetSysColor (COLOR_WINDOW)); } } else { if (lpdis->itemData) forecolor = SetTextColor (lpdis->hDC, GetSysColor (COLOR_WINDOWTEXT)); else forecolor = SetTextColor (lpdis->hDC, GetSysColor (COLOR_GRAYTEXT)); bkcolor = SetBkColor (lpdis->hDC, GetSysColor (COLOR_WINDOW)); } ExtTextOut (lpdis->hDC, /* device context */ lpdis->rcItem.left + 2, /* ref point x */ lpdis->rcItem.top + 1, /* ref point y */ ETO_CLIPPED | ETO_OPAQUE, /* options */ &lpdis->rcItem, /* clipping rect */ text, /* text to draw */ lstrlen (text), /* length of text to draw */ NULL /* no kerning array */ ); SetTextColor (lpdis->hDC, forecolor); SetBkColor (lpdis->hDC, bkcolor); if (lpdis->itemState & ODS_FOCUS) DrawFocusRect (lpdis->hDC, &lpdis->rcItem); } break; case ODT_BUTTON: { { SendMessage3ToClean (CcWmDRAWCONTROL, hWin, lpdis->hwndItem, lpdis->hDC); if (lpdis->itemState & ODS_SELECTED) InvertRect (lpdis->hDC, &lpdis->rcItem); if (lpdis->itemState & ODS_FOCUS) DrawFocusRect (lpdis->hDC, &lpdis->rcItem); }; return TRUE; } break; } } break; } return DefMDIChildProc (hWin,uMess,wPara,lPara); } /* End of MDIWindowProcedure callback routine. */ /* Callback routine for MDI frame window procedure. */ static LRESULT CALLBACK MDIFrameProcedure (HWND hWin,UINT uMess,WPARAM wPara,LPARAM lPara) { printMessage ("Clean MDIFrameWindow",hWin,uMess,wPara,lPara); switch (uMess) { /* WM_ENTERIDLE message is used to let Clean evaluate the initialisation action of a modal dialog by sending the CcWmIDLEDIALOG message. */ case WM_ENTERIDLE: { HWND hwndModalDialog; hwndModalDialog = (HWND)lPara; if (wPara == MSGF_DIALOGBOX && hwndModalDialog != ghwndLastModalDialog) { SendMessage1ToClean (CcWmIDLEDIALOG,(int)hwndModalDialog); ghwndLastModalDialog = hwndModalDialog; } else { SendMessage0ToClean (CcWmIDLETIMER); } return 0; } break; case WM_ENTERMENULOOP: { gProhibitWindowActivation++; } break; case WM_EXITMENULOOP: { gProhibitWindowActivation--; } break; case WM_COMMAND: { if (HIWORD (wPara)==0 && lPara!=0) { HWND hwndToolbar; hwndToolbar = (HWND)GetGWL_USERDATA (hWin); // Obtain the toolbar handle if (hwndToolbar != 0) SendMessage4ToClean (CcWmBUTTONCLICKED, hWin, lPara, GetModifiers (), LOWORD (wPara)); } else { switch (wPara) { case (OSMenuIDEnd+1): { SendMessage (GetWindow (hWin,GW_CHILD),WM_MDIICONARRANGE,0,0); } break; case (OSMenuIDEnd+2): { SendMessage (GetWindow (hWin,GW_CHILD),WM_MDITILE,(WPARAM) (UINT) MDITILE_VERTICAL,0); } break; case (OSMenuIDEnd+3): { SendMessage (GetWindow (hWin,GW_CHILD),WM_MDITILE,(WPARAM) (UINT) MDITILE_HORIZONTAL,0); } break; case (OSMenuIDEnd+4): { SendMessage (GetWindow (hWin,GW_CHILD),WM_MDICASCADE,0,0); } break; default: SendMessage2ToClean (CcWmCOMMAND, LOWORD (wPara), GetModifiers ()); } } } break; /* WM_CREATE should create the client window, the menu bar, and the "Window" menu. */ case WM_CREATE: { CLIENTCREATESTRUCT clientcreate; HMENU menuBar, windowMenu; // The handle to the menu bar and the "Window" menu ProcessShortcutTable shortcuts; // New HWND hwndClient; // New menuBar = CreateMenu (); // Create the menu bar SetMenu (hWin,menuBar); // and associate it with the frame window windowMenu = CreatePopupMenu (); // Create the "Window" menu InsertMenu (menuBar, // add it to the menuBar 0xFFFFFFFF, // at the end MF_BYPOSITION | MF_POPUP, // Flags (UINT) windowMenu, // the "Window" menu "&Window" // and set its title ); InsertMenu (windowMenu,0,MF_BYPOSITION | MF_STRING,OSMenuIDEnd+1,"Arrange &Icons"); // Add "Arrange Icons" command InsertMenu (windowMenu,0,MF_BYPOSITION | MF_STRING,OSMenuIDEnd+2,"&Tile Vertically"); // Add "Tile Vertically" command InsertMenu (windowMenu,0,MF_BYPOSITION | MF_STRING,OSMenuIDEnd+3,"Tile &Horizontally"); // Add "Tile Horizontally" command InsertMenu (windowMenu,0,MF_BYPOSITION | MF_STRING,OSMenuIDEnd+4,"&Cascade"); // Add "Cascade" command clientcreate.hWindowMenu = windowMenu; clientcreate.idFirstChild = OSMenuIDEnd+5; // Window ids must be generated from OSMenuIDEnd+5 hwndClient = CreateWindow ( "MDICLIENT", // The MDICLIENT window class NULL, // The window name WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE, // Style parameters 0,0, // position (x,y) 0,0, // size (w,h) hWin, // The frame window is the parent NULL, // The menu (none at the moment) (HANDLE) ghInst, // Instance that owns the window (LPSTR) &clientcreate // The CLIENTCREATESTRUCT ); shortcuts = AllocateProcessShortcutTable (MINSIZEPROCESSSHORTCUTTABLE); // create a new shortcut table SetWindowLong (hWin, 0, (long) shortcuts); // and store it in the local memory of the window gAcceleratorTableIsUpToDate = FALSE; // The active global accelerator table is not up to date ghActiveFrameWindow = hWin; // Keep track of the active frame window ghActiveClientWindow = hwndClient; // and client window } return 0; case WM_CLOSE: { SendMessage1ToClean (CcWmPROCESSCLOSE, hWin); return 0; } break; case WM_DESTROY: /* The frame is in the act of being closed. */ { ProcessShortcutTable shortcuts; shortcuts = (ProcessShortcutTable) GetWindowLong (hWin, 0); // get the local shortcut table DestroyProcessShortcutTable (shortcuts); // and destroy it. gAcceleratorTableIsUpToDate = FALSE; // The active global accelerator table is not up to date DragAcceptFiles (hWin,FALSE); /* Unregister for WM_DROPFILES events. */ } break; /* case WM_ACTIVATE: // This alternative should only administer the current active frame/client window. { if (LOWORD (wPara)!=WA_INACTIVE) { ghActiveFrameWindow = hWin; ghActiveClientWindow = GetWindow (ghActiveFrameWindow,GW_CHILD); ghTopDocWindow = GetWindow (ghActiveClientWindow,GW_CHILD); } else { ghTopDocWindow = NULL; ghActiveFrameWindow = NULL; ghActiveClientWindow = NULL; gAcceleratorTableIsUpToDate = FALSE; // The active global accelerator table is not up to date } } break; */ case WM_NOTIFY: { LPNMHDR pnmh = (LPNMHDR) lPara; LPTOOLTIPTEXT lpttt = (LPTOOLTIPTEXT) lPara; UINT from, flags; from = lpttt->hdr.idFrom; flags= lpttt->uFlags; if (pnmh->code == TTN_NEEDTEXT && from != 0 && flags != TTF_IDISHWND) { HWND hwndToolbar; hwndToolbar = (HWND)GetGWL_USERDATA (hWin); // get tooltip text from Clean SendMessage2ToClean (CcWmGETTOOLBARTIPTEXT, hwndToolbar, from); lstrcpy (lpttt->szText,(LPSTR)gCci.p1); if (gCci.p1 != 0) rfree ((HGLOBAL) gCci.p1); } } break; case WM_SIZE: { HWND hwndToolbar; hwndToolbar = (HWND)GetGWL_USERDATA (hWin); if (hwndToolbar != NULL) SendMessage ((HWND)GetGWL_USERDATA (hWin), TB_AUTOSIZE, (WPARAM)0, (LPARAM)0); } break; /* Accept the user dropping file(s) in the frame window. */ case WM_DROPFILES: { SendDropFilesToClean (hWin,wPara); } break; default: return DefFrameProc (hWin, GetWindow (hWin,GW_CHILD), uMess, wPara, lPara); break; } return DefFrameProc (hWin, GetWindow (hWin,GW_CHILD), uMess, wPara, lPara); } /* End of MDIFrameProcedure callback routine. */ static BOOL RbrtTranslateMessage (MSG * pmsg) { int c; UINT msg; c = 0; msg = pmsg->message; if (msg==WM_SYSKEYDOWN || msg==WM_KEYDOWN) { c = CheckVirtualKeyCode ((int) pmsg->wParam); } if (c) { gStoredMess = *pmsg; gStoredMess.wParam = (WPARAM) c; if (pmsg->message == WM_SYSKEYDOWN) gStoredMess.message = WM_SYSCHAR; else gStoredMess.message = WM_CHAR; gMessStored = TRUE; return TRUE; } else return TranslateMessage (pmsg); } /* EndSuspendTimerProc is the parameter of the SetTimer procedure used in RbrtGetMessage to set a positive timer interval (gSleepTime). The WaitMessage routine suspends the OS thread until an interesting event has occurred or the timer has been triggered. In that case EndSuspendTimerProc is called, which kills the timer and informs Clean about the timer event. */ static VOID CALLBACK EndSuspendTimerProc (HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime ) { KillTimer (ghMainWindow, (UINT) -2); SendMessage0ToClean (CcWmIDLETIMER); }; static int RbrtGetMessage (MSG * pmsg) { if (gMessStored) { *pmsg = gStoredMess; gMessStored = FALSE; return TRUE; } if (gSleeptime==0 && !PeekMessage (pmsg, NULL, 0, 0, PM_NOREMOVE)) { POINT p; GetCursorPos (&p); pmsg->hwnd = ghMainWindow; pmsg->message = WM_ENTERIDLE; pmsg->wParam = MSGF_USER; pmsg->lParam = (LPARAM) ghMainWindow; pmsg->time = GetTickCount (); pmsg->pt = p; return TRUE; } if (!gIdleTimerOn) { return GetMessage (pmsg, NULL, 0, 0); } else { if (PeekMessage (pmsg, NULL, 0, 0, PM_REMOVE)) return (pmsg->message != WM_QUIT); else { POINT p; /* The following code has been inserted to reduce the crosscall traffic. A timer is set to suspend this thread until atleast the timer interval has elapsed. */ if (SetTimer (ghMainWindow, (UINT) -2, (UINT)gSleeptime, &EndSuspendTimerProc)) { WaitMessage (); } else { rMessageBox (NULL,MB_APPLMODAL,"RbrtGetMessage","SetTimer failed to create timer"); } /* End of insertion. */ GetCursorPos (&p); pmsg->hwnd = ghMainWindow; pmsg->message = WM_ENTERIDLE; pmsg->wParam = MSGF_USER; pmsg->lParam = (LPARAM) ghMainWindow; pmsg->time = GetTickCount (); pmsg->pt = p; return TRUE; } } } static UINT APIENTRY FileSelectorHook (HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam) { if (uiMsg == WM_INITDIALOG) { // HWND window_handle; RECT rect; int x, y; // window_handle = GetParent (hdlg); // GetWindowRect (window_handle, &rect); GetWindowRect (hdlg, &rect); x = (GetSystemMetrics (SM_CXSCREEN)>>1) - ((rect.right-rect.left)>>1); y = (GetSystemMetrics (SM_CYSCREEN)>>1) - ((rect.bottom-rect.top)>>1); // x = GetSystemMetrics (SM_CXSCREEN)>>1; // y = GetSystemMetrics (SM_CYSCREEN)>>1; // SetWindowPos (window_handle, NULL, x, y, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER); SetWindowPos (hdlg, NULL, x, y, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER); } return 0; } /* UpdateWindowScrollbars updates any window scrollbars and non-client area if present. */ static void UpdateWindowScrollbars (HWND hwnd) { int w,h; RECT rect; GetWindowRect (hwnd, &rect); w = rect.right -rect.left; h = rect.bottom-rect.top; if (WindowHasHScroll (hwnd)) { rect.left = 0; rect.top = h-GetSystemMetrics (SM_CYHSCROLL); rect.right = w; rect.bottom = h; InvalidateRect (hwnd,&rect,FALSE); RedrawWindow (hwnd,&rect,NULL,RDW_FRAME | RDW_VALIDATE | RDW_UPDATENOW | RDW_NOCHILDREN); ValidateRect (hwnd,&rect); } if (WindowHasVScroll (hwnd)) { rect.left = w-GetSystemMetrics (SM_CXVSCROLL); rect.top = 0; rect.right = w; rect.bottom = h; InvalidateRect (hwnd,&rect,FALSE); RedrawWindow (hwnd,&rect,NULL,RDW_FRAME | RDW_VALIDATE | RDW_UPDATENOW | RDW_NOCHILDREN); ValidateRect (hwnd,&rect); } } void HandleCleanRequest (CrossCallInfo * pcci) { switch (pcci->mess) { /* Mike... */ case CcRqRUNGAME: /* int int int (obsolete) no result. */ { RunGame (); MakeReturn0Cci (pcci); } break; case CcRqPLAYSOUNDSAMPLE: // id, vol, pan, freq, delay // no result { int id = pcci->p1; int vol = pcci->p2; int pan = pcci->p3; int freq = pcci->p4; int delay = pcci->p5; PlaySoundSample (id, vol, pan, freq, delay); MakeReturn0Cci (pcci); } break; case CcRqCREATEGAMEOBJECT: /* mapval, above, x, y no result */ { int mapval = pcci->p1; int above = pcci->p2; int x = pcci->p3; int y = pcci->p4; int result = 0; CreateGameObject (mapval, above, x, y, &result); MakeReturn0Cci (pcci); } break; case CcRqUSERGAMEEVENT: /* event, par1, par2, target, subtarget, time no result */ { int event = pcci->p1; int par1 = pcci->p2; int par2 = pcci->p3; int target = pcci->p4; /* added 01/11/99... */ int subtarget = pcci->p5; int time = pcci->p6; ScheduleUserGameEvent (event, par1, par2, target, subtarget, time); /* ...added 01/11/99 */ MakeReturn0Cci (pcci); } break; case CcRqCREATEGAMEWINDOW: /* width, height, bpp, fullscreen HWND result. */ { int w = pcci->p1; int h = pcci->p2; int bpp = pcci->p3; int fs = (BOOL) pcci->p4; int result; result = CreateGameWindow (w, h, bpp, fs); MakeReturn1Cci (pcci, result); } break; /* ...Mike */ case CcRqBEGINPAINT: /* hwnd; HDC result. */ { HDC hdc; hdc = BeginPaint ((HWND) pcci->p1, &gPaintStruct); MakeReturn1Cci (pcci, (int) hdc); } break; case CcRqENDPAINT: /* hwnd; no result. */ { EndPaint ((HWND) pcci->p1, &gPaintStruct); MakeReturn0Cci (pcci); } break; case CcRqINVALIDATEWINDOW: /* hwnd; no result. */ { InvalidateRect ((HWND) pcci->p1, NULL, FALSE); MakeReturn0Cci (pcci); } break; /* Invalidate part of window/control. */ case CcRqINVALIDATERECT: /* hwnd, left,top,right,bottom; no result. */ { RECT rect; rect.left = pcci->p2; rect.top = pcci->p3; rect.right = pcci->p4; rect.bottom = pcci->p5; InvalidateRect ((HWND) pcci->p1, &rect, FALSE); MakeReturn0Cci (pcci); } break; /* Validate rect part of window/control. */ case CcRqVALIDATERECT: /* hwnd, left,top,right,bottom; no result. */ { RECT rect; rect.left = pcci->p2; rect.top = pcci->p3; rect.right = pcci->p4; rect.bottom = pcci->p5; ValidateRect ((HWND) pcci->p1, &rect); MakeReturn0Cci (pcci); } break; /* Validate region part of window/control. */ case CcRqVALIDATERGN: /* hwnd, rgn; no result. */ { ValidateRgn ((HWND) pcci->p1, (HRGN) pcci->p2); MakeReturn0Cci (pcci); } break; case CcRqDOMESSAGE: // idleTimerOn, sleeptime; no result. { MSG ms; int msgresult; gIdleTimerOn = (BOOL) pcci->p1; gSleeptime = (int) pcci->p2; msgresult = RbrtGetMessage (&ms); if (msgresult == -1) ErrorExit ("Fatal error: CcRqDoMessage, GetMessage result is -1"); else if (msgresult == FALSE) ErrorExit ("Fatal error: CcRqDoMessage, GetMessage result is FALSE (WM_QUIT)"); else { LONG msgtime = GetMessageTime (); gPrevMsgTime = msgtime; if (!gActiveDialog || !IsDialogMessage (gActiveDialog, &ms)) { if (ghActiveClientWindow==NULL || !TranslateMDISysAccel (ghActiveClientWindow, &ms)) { UpdateAcceleratorTable (); // Verify the correctness of gAcceleratorTable if (gAcceleratorTable==NULL || !TranslateAccelerator (ghActiveFrameWindow, gAcceleratorTable, &ms)) { #ifdef HILT if (!htmlHelpInitialized || !HtmlHelp (NULL,NULL,HH_PRETRANSLATEMESSAGE,(DWORD)&ms)) #endif { RbrtTranslateMessage (&ms); DispatchMessage (&ms); } } } } MakeReturn0Cci (pcci); } } break; /* Add a shortkey to a framewindow shortkey table. */ case CcRqADDMENUSHORTKEY: /* frameptr, cmd, key; no result. */ { ProcessShortcutTable table; HWND frameptr; int cmd, key; frameptr = (HWND) pcci->p1; cmd = pcci->p2; key = pcci->p3; table = (ProcessShortcutTable) GetWindowLong (frameptr,0); table = AddProcessShortcut (key, cmd, table); SetWindowLong (frameptr, 0, (long)table); if (gAcceleratorTableIsUpToDate) { gAcceleratorTableIsUpToDate == !(ghActiveFrameWindow==frameptr); } MakeReturn0Cci (pcci); } break; /* Remove a shortkey from a framewindow shortkey table. */ case CcRqREMOVEMENUSHORTKEY: /* frameptr, cmd; no result. */ { ProcessShortcutTable table; HWND frameptr; int cmd; frameptr = (HWND) pcci->p1; cmd = pcci->p2; table = (ProcessShortcutTable) GetWindowLong (frameptr,0); table = RemoveProcessShortcut (cmd, table); SetWindowLong (frameptr, 0, (long)table); if (gAcceleratorTableIsUpToDate) { gAcceleratorTableIsUpToDate == !(ghActiveFrameWindow==frameptr); } MakeReturn0Cci (pcci); } break; case CcRqMODIFYMENUITEM: /* hitem, hmenu, textptr; no result. */ { MENUITEMINFO info; info.cbSize = (UINT) sizeof (MENUITEMINFO); info.fMask = MIIM_TYPE; info.fType = MFT_STRING; info.fState = (UINT) 0; info.wID = (UINT) pcci->p1; info.hSubMenu = (HMENU) NULL; info.hbmpChecked = NULL; info.hbmpUnchecked = NULL; info.dwItemData = (DWORD) 0; info.dwTypeData = (LPTSTR) pcci->p3;//correcttext; info.cch = rstrlen ((LPTSTR)pcci->p3);//(correcttext); SetMenuItemInfo ((HMENU) pcci->p2, (UINT) pcci->p1, FALSE, &info); MakeReturn0Cci (pcci); } break; case CcRqINSERTMENUITEM: /* on/off, hmenu, textptr, marked, pos; HITEM result. */ { UINT graystate, checkstate; HITEM hitem; if (pcci->p1) { graystate = MF_ENABLED; } else { graystate = MF_GRAYED; } if (pcci->p4) { checkstate = MF_CHECKED; } else { checkstate = MF_UNCHECKED; } hitem = NextMenuItemID (); /* PA: replaced NextItemHandle by NextMenuItemID. */ InsertMenu ((HMENU) pcci->p2, /* hMenu */ (UINT) pcci->p5, /* position */ MF_BYPOSITION | MF_STRING | graystate | checkstate, /* Flags */ (UINT) hitem, /* id */ (LPCTSTR) pcci->p3 ); MakeReturn1Cci (pcci, hitem); } break; case CcRqITEMENABLE: /* parent, HITEM, onoff; no result. */ { UINT greystate; if (pcci->p3) { greystate = MF_ENABLED; } else { greystate = MF_GRAYED; } EnableMenuItem ((HMENU) pcci->p1, /* parent menu */ (UINT) pcci->p2, /* menu item id */ MF_BYCOMMAND | greystate); /* flags */ MakeReturn0Cci (pcci); } break; /* Destroy a menu 'physically' */ case CcRqDESTROYMENU: /* HMENU; no result. */ { DestroyMenu ((HMENU) pcci->p1); MakeReturn0Cci (pcci); } break; /* Remove a menu logically */ case CcRqDELETEMENU: /* HMENU, HITEM; no result. */ { DeleteMenu ((HMENU) pcci->p1, /* parent menu */ (UINT) pcci->p2, /* menu item id */ MF_BYCOMMAND); MakeReturn0Cci (pcci); } break; case CcRqREMOVEMENUITEM: /* menu, HITEM; no result. */ { RemoveMenu ((HMENU) pcci->p1, (UINT) pcci->p2, MF_BYCOMMAND); MakeReturn0Cci (pcci); } break; case CcRqINSERTSEPARATOR: /* hmenu, pos no result. */ { InsertMenu ((HMENU) pcci->p1, /* hMenu */ (UINT) pcci->p2, /* position */ MF_BYPOSITION | MF_SEPARATOR, /* Flags */ 0, /* no id for separator */ NULL); /* no text for separator */ MakeReturn0Cci (pcci); } break; case CcRqMODIFYMENU: /* hitem, hmenu, textptr; no result. */ { MENUITEMINFO info; info.cbSize = (UINT) sizeof (MENUITEMINFO); info.fMask = MIIM_TYPE; info.fType = MFT_STRING; info.fState = (UINT) 0; info.wID = (UINT) pcci->p1; info.hSubMenu = (HMENU) pcci->p2; info.hbmpChecked = NULL; info.hbmpUnchecked = NULL; info.dwItemData = (DWORD) 0; info.dwTypeData = (LPTSTR) pcci->p3; info.cch = rstrlen ((LPTSTR)pcci->p3); SetMenuItemInfo ((HMENU) pcci->p2, (UINT) pcci->p1, FALSE, &info); MakeReturn0Cci (pcci); } break; /* Insert a menu into the menu bar. */ case CcRqINSERTMENU: /* on/off, hmenu, textptr, hsubmenu, pos; no result */ { UINT graystate; graystate = 0; if (pcci->p1) { graystate = MF_ENABLED; } else { graystate = MF_GRAYED; } InsertMenu ((HMENU) pcci->p2, /* hMenu */ (UINT) pcci->p5, /* position */ MF_BYPOSITION | MF_POPUP | graystate, /* flags */ (UINT) pcci->p4, /* hSubMenu */ (LPCTSTR) pcci->p3 ); MakeReturn0Cci (pcci); } break; case CcRqMENUENABLE: /* parent, zero based position of menu, onoff; no result. */ { UINT greystate; if (pcci->p3) { greystate = MF_ENABLED; } else { greystate = MF_GRAYED; } EnableMenuItem ((HMENU) pcci->p1, /* parent menu */ (UINT) pcci->p2, /* submenu */ MF_BYPOSITION | greystate); /* flags */ MakeReturn0Cci (pcci); } break; case CcRqDRAWMBAR: /* framePtr, clientPtr; no result. */ { HWND framePtr = (HWND) pcci->p1; HWND clientPtr = (HWND) pcci->p2; if (clientPtr != 0) SendMessage (clientPtr,WM_MDIREFRESHMENU,(WPARAM)0,(LPARAM)0); DrawMenuBar (framePtr); MakeReturn0Cci (pcci); } break; /* Track pop up menu. */ case CcRqTRACKPOPMENU: /* popupmenu,framePtr; BOOL result. */ { HMENU popupmenu; HWND framePtr; UINT flags; POINT mousePos; BOOL ok; popupmenu = (HMENU) pcci->p1; framePtr = (HWND) pcci->p2; flags = TPM_CENTERALIGN | TPM_RIGHTBUTTON; GetCursorPos (&mousePos); ok = TrackPopupMenu (popupmenu,flags,mousePos.x,mousePos.y,0,framePtr,NULL); MakeReturn1Cci (pcci,(int)ok); } break; case CcRqCREATEPOPMENU: /* no params; MENU result. */ { MakeReturn1Cci (pcci, (int) CreatePopupMenu ()); } break; case CcRqCHECKMENUITEM: /* menu, HITEM, on/off; no result. */ { UINT check; if (pcci->p3) { check = MF_CHECKED; } else { check = MF_UNCHECKED; } CheckMenuItem ((HMENU) pcci->p1, (UINT) pcci->p2, MF_BYCOMMAND | check); MakeReturn0Cci (pcci); } break; case CcRqDESTROYMODALDIALOG: /* hwnd; no result. */ { EndDialog ((HWND)pcci->p1,0); ghwndLastModalDialog = NULL; /* Create only one zero timer for modal dialog stack. */ MakeReturn0Cci (pcci); } break; case CcRqDESTROYWINDOW: /* hwnd; no result. */ { BOOL noError; noError = DestroyWindow ((HWND) pcci->p1); if (!noError) { rMessageBox (NULL,MB_APPLMODAL,"CcRqDESTROYWINDOW","DestroyWindow failed"); } MakeReturn0Cci (pcci); } break; case CcRqDESTROYMDIDOCWINDOW: /* hwndFrame, hwndClient, wPtr; no result. */ { HWND hwndFrame, hwndClient, hwndDocWindow, newActiveDocWindow; hwndFrame = (HWND) pcci->p1; hwndClient = (HWND) pcci->p2; hwndDocWindow = (HWND) pcci->p3; // First destroy the given MDI document window. SendMessage (hwndClient, WM_MDIDESTROY, (WPARAM) hwndDocWindow, 0); // Obtain the new active MDI document window. newActiveDocWindow = (HWND) SendMessage (hwndClient, WM_MDIGETACTIVE, (WPARAM) 0, (LPARAM) NULL); if (newActiveDocWindow==NULL) // If all document windows have been closed { ghActiveFrameWindow = hwndFrame; // then keep track of the MDI frame window ghActiveClientWindow = hwndClient; // and client window } MakeReturn0Cci (pcci); } break; /* Create a SDI frame window. */ case CcRqCREATESDIFRAMEWINDOW: /* accept file open; frame ptr, menubar results. */ { HWND hwndFrame; BOOL acceptFileOpen; DWORD styleFlags; HMENU menuBar; acceptFileOpen = (BOOL) pcci->p1; /* respond to file open events. */ /* The frame style flags equal the styleFlags with the scrollbar flags masked out. */ styleFlags = WS_SYSMENU | WS_OVERLAPPED | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_THICKFRAME; /* Create the menubar. */ menuBar = CreateMenu (); /* Create the window. */ hwndFrame = CreateWindow ( SDIFrameClassName, /* Class name */ NULL, /* No title yet */ styleFlags, /* SDI frame style flags */ CW_USEDEFAULT,CW_USEDEFAULT, /* No position yet */ CW_USEDEFAULT,CW_USEDEFAULT, /* no size yet */ NULL, /* Parent window */ menuBar, /* menu handle */ (HANDLE) ghInst, /* Instance that owns the window */ 0); ShowWindow (hwndFrame, SW_SHOWNORMAL); UpdateWindow (hwndFrame); if (acceptFileOpen) DragAcceptFiles (hwndFrame,TRUE); /* register for WM_DROPFILES events. */ MakeReturn2Cci (pcci, (int) hwndFrame, (int) menuBar); } break; /* Create a SDI document window. */ case CcRqCREATESDIDOCWINDOW: /* not used, frameptr, packed pos, w,h, flags; client ptr result. */ { HWND hwndFrame, hwndClient, hwndToolbar; POINT clientDims, frameDims, winpos; DWORD styleFlags; RECT tbRect; int tbHeight; hwndFrame = (HWND) pcci->p2; winpos.x = pcci->p3>>16; winpos.y = (pcci->p3<<16)>>16; clientDims.x = pcci->p4; clientDims.y = pcci->p5; styleFlags = (DWORD) pcci->p6; hwndToolbar = (HWND)GetGWL_USERDATA (hwndFrame); if (hwndToolbar == NULL || !GetWindowRect (hwndToolbar,&tbRect)) { tbHeight = 0; } else { tbHeight = tbRect.bottom - tbRect.top; } frameDims.x = clientDims.x; frameDims.y = clientDims.y + tbHeight; W95AdjustCleanSDIWindowDimensions (styleFlags, &frameDims); /* Adjust the pos and size of the frame window. */ SetWindowPos (hwndFrame,NULL,winpos.x,winpos.y,frameDims.x,frameDims.y,SWP_NOZORDER); UpdateWindow (hwndFrame); /* The client style flags are WS_CHILD and styleFlags. */ styleFlags |= WS_CHILD; /* Create the new client window of the frame window. */ hwndClient = CreateWindow (SDIWindowClassName, /* Class name */ NULL, /* No title */ styleFlags, /* SDI client style flags */ 0, tbHeight, /* x, y */ clientDims.x,clientDims.y, /* width, height */ hwndFrame, /* Parent window */ (HMENU) NULL, /* no menu handle */ (HANDLE) ghInst, /* Instance that owns the window */ 0); SetWindowPos (hwndClient,HWND_TOP,0,0,0,0,SWP_NOMOVE | SWP_NOSIZE); ShowWindow (hwndClient,SW_SHOWNORMAL); UpdateWindow (hwndClient); UpdateWindowScrollbars (hwndClient); MakeReturn1Cci (pcci, (int) hwndClient); } break; /* Create MDI frame window. */ case CcRqCREATEMDIFRAMEWINDOW: /* show, accept file open; frame ptr, client ptr, menubar, windowmenu results. */ { BOOL show, acceptFileOpen; DWORD styleFlags; HWND hwndFrame, hwndClient; HMENU menuBar, windowMenu; show = (BOOL) pcci->p1; acceptFileOpen = (BOOL) pcci->p2; /* respond to file open events. */ styleFlags = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN; if (show) styleFlags |= WS_MAXIMIZE; else styleFlags |= WS_MINIMIZE; hwndFrame = CreateWindow ( MDIFrameClassName // Class name , NULL // No title yet , styleFlags // Style parameters , 0,0 // Default position (x,y) , CW_USEDEFAULT,CW_USEDEFAULT // Default size (w,h) , NULL // Every window should be top-level , NULL , (HANDLE) ghInst // Instance that owns the window , NULL ); hwndClient = GetWindow (hwndFrame,GW_CHILD); // retrieve the "MDICLIENT" window menuBar = GetMenu (hwndFrame); // retrieve the menu bar of the frame window windowMenu = GetSubMenu (menuBar,0); // retrieve the "Window" menu of the menu bar if (show) { ShowWindow (hwndFrame,SW_MAXIMIZE); // show the frame window (SW_MAXIMIZE gives best result) UpdateWindow (hwndFrame); // update the frame window } DrawMenuBar (hwndFrame); // update the menu bar if (acceptFileOpen) DragAcceptFiles (hwndFrame,TRUE); /* register for WM_DROPFILES events. */ /* Store the standard Windows callback routine adress in stdMDIClientCallback and subclass the MDI client window with MDIClientProcedure. */ stdMDIClientCallback = SetWindowLong (hwndClient, GWL_WNDPROC, (LONG) MDIClientProcedure); MakeReturn4Cci (pcci,(int) hwndFrame,(int) hwndClient,(int) menuBar,(int) windowMenu); } break; /* Create MDI child window. */ case CcRqCREATEMDIDOCWINDOW: /* textptr, clientPtr, behindPtr, packed pos, packed size, flags; HWND result. */ { HWND whandle,hwndClient,hwndBehind; POINT dims, winpos; LPCTSTR pwintitle; DWORD styleFlags, exStyleFlags; MDICREATESTRUCT mdicreate; // The structure sent to the client window pwintitle = (LPCTSTR) pcci->p1; hwndClient = (HWND) pcci->p2; hwndBehind = (HWND) pcci->p3; winpos.x = pcci->p4>>16; winpos.y = (pcci->p4<<16)>>16; dims.x = pcci->p5>>16; dims.y = (pcci->p5<<16)>>16; styleFlags = (DWORD) pcci->p6; exStyleFlags = (DWORD) 0; W95AdjustCleanMDIWindowDimensions (styleFlags, &dims); if (styleFlags&WS_THICKFRAME != 0) /* If resizable*/ { exStyleFlags |= WS_EX_CLIENTEDGE; /* then provide a 3D look to the window. */ } /* fill the MDICREATESTRUCT record */ mdicreate.szClass = MDIWindowClassName; mdicreate.szTitle = pwintitle; mdicreate.hOwner = (HANDLE) ghInst; mdicreate.x = winpos.x; mdicreate.y = winpos.y; mdicreate.cx = dims.x; mdicreate.cy = dims.y; mdicreate.style = styleFlags; mdicreate.lParam = 0; /* create the window */ whandle = (HWND) SendMessage (hwndClient,WM_MDICREATE,0,(LPARAM)(LPMDICREATESTRUCT) &mdicreate); /* take care of window stacking */ if (hwndBehind!=0) { SetWindowPos (whandle, hwndBehind, 0, 0, 0, 0, SWP_NOMOVE + SWP_NOSIZE); } MakeReturn1Cci (pcci, (int) whandle); } break; case CcRqSETWINDOWTITLE: /* hwnd, textptr no result. */ { rprintf ("SWT: handle = %d, text = \"%s\"\n", (HWND) pcci->p1, (char *) pcci->p2); SetWindowText ((HWND) pcci->p1, (char *) pcci->p2); AdjustMenuBarName (); MakeReturn0Cci (pcci); } break; case CcRqGETWINDOWTEXT: /* hwnd; textptr result. */ { char *textptr; HWND hwnd; int length; hwnd = (HWND) pcci->p1; length = GetWindowTextLength (hwnd); textptr = (char *) rmalloc (length + 1); GetWindowText (hwnd, textptr, length + 1); textptr[length] = 0; MakeReturn1Cci (pcci, (int) textptr); } break; case CcRqGETFONTNAMES: /* no params; no result. */ { HDC hdc; hdc = GetDC (ghMainWindow); EnumFontFamilies (hdc, NULL, (FONTENUMPROC) EnumFontNameProc, 0); ReleaseDC (ghMainWindow, hdc); MakeReturn0Cci (pcci); } break; case CcRqGETFONTSIZES: /* textptr; no result. */ { HDC hdc; hdc = GetDC (ghMainWindow); EnumFontFamilies (hdc, (char *) pcci->p1, (FONTENUMPROC) EnumFontSizeProc, 0); ReleaseDC (ghMainWindow, hdc); rfree ((char *) pcci->p1); MakeReturn0Cci (pcci); } break; /* Update rect part of a window. */ case CcRqUPDATEWINDOWRECT: /* hwnd, left,top,right,bottom; no result. */ { RECT rect; HWND hwnd; hwnd = (HWND) pcci->p1; rect.left = pcci->p2; rect.top = pcci->p3; rect.right = pcci->p4; rect.bottom= pcci->p5; InvalidateRect (hwnd,&rect,FALSE); UpdateWindow (hwnd); RedrawWindow (hwnd,&rect,NULL,RDW_FRAME | RDW_VALIDATE | RDW_UPDATENOW | RDW_NOCHILDREN); MakeReturn0Cci (pcci); } break; case CcRqGETCLIENTSIZE: /* hwnd; width, height result. */ { RECT rect; GetClientRect ((HWND) pcci->p1, &rect); MakeReturn2Cci (pcci, rect.right - rect.left, rect.bottom - rect.top); } break; /* Set the ClientRect. */ case CcRqSETCLIENTSIZE: /* hwnd, width, height; no result. */ { HWND hwnd; int w,h,curw,curh,clientw,clienth; UINT flags; RECT clientRect,windowRect; hwnd = (HWND) pcci->p1; w = pcci->p2; h = pcci->p3; flags = SWP_NOMOVE /* retain position */ | SWP_NOZORDER; /* retain Z order */ GetClientRect (hwnd, &clientRect); GetWindowRect (hwnd, &windowRect); clientw = clientRect.right - clientRect.left; clienth = clientRect.bottom- clientRect.top; curw = windowRect.right - windowRect.left; curh = windowRect.bottom- windowRect.top; SetWindowPos (hwnd, HWND_TOP, 0,0, curw+w-clientw,curh+h-clienth, flags); MakeReturn0Cci (pcci); } break; /* (En/Dis)able windows/dialogues. */ case CcRqSETSELECTWINDOW: /* hwnd, hasHScroll, hasVScroll, toAble, modalContext; no result. */ { HWND window; BOOL hasHScroll, hasVScroll, toAble, modalContext; window = (HWND) pcci->p1; hasHScroll = (BOOL) pcci->p2; hasVScroll = (BOOL) pcci->p3; toAble = (BOOL) pcci->p4; modalContext = (BOOL) pcci->p5; if (modalContext) /* if not a modal context, then do not disable window */ EnableWindow (window,toAble); /* because it can't be moved, or closed. */ if (hasHScroll) EnableScrollBar (window,SB_HORZ,toAble ? ESB_ENABLE_BOTH : ESB_DISABLE_BOTH); if (hasVScroll) EnableScrollBar (window,SB_VERT,toAble ? ESB_ENABLE_BOTH : ESB_DISABLE_BOTH); MakeReturn0Cci (pcci); } break; case CcRqGETWINDOWPOS: /* hwnd; width, heigth result */ { RECT rect; GetWindowRect ((HWND) pcci->p1, &rect); MakeReturn2Cci (pcci, rect.left, rect.top); } break; /* Set the position of windows/controls. */ case CcRqSETWINDOWPOS: /* hwnd, x,y, update, include scrollbars ; no result. */ { HWND hwnd; int x,y; BOOL update,inclScrollbars; UINT flags; hwnd = (HWND)pcci->p1; x = pcci->p2; y = pcci->p3; update = pcci->p4; inclScrollbars = pcci->p5; flags = SWP_NOSIZE /* retain size */ | SWP_NOZORDER; /* retain Z order */ SetWindowPos (hwnd, HWND_TOP, x,y, 0,0, flags); if (IsWindowVisible (hwnd) && update!=0) { /* only if window is visible and update is requested, proceed to enforce update. */ if (inclScrollbars) UpdateWindowScrollbars (hwnd); else { InvalidateRect (hwnd,NULL,TRUE); UpdateWindow (hwnd); RedrawWindow (hwnd,NULL,NULL,RDW_FRAME | RDW_VALIDATE | RDW_UPDATENOW | RDW_NOCHILDREN); } } MakeReturn0Cci (pcci); } break; /* Get the size of the bounding rectangle of windows/controls. */ case CcRqGETWINDOWSIZE: /* hwnd; width,height result. */ { RECT rect; GetWindowRect ((HWND) pcci->p1, &rect); MakeReturn2Cci (pcci, rect.right-rect.left, rect.bottom-rect.top); } break; /* Set the size of windows/controls. */ case CcRqSETWINDOWSIZE: /* hwnd, w,h, update; no result. */ { HWND hwnd; int w,h; BOOL update; UINT flags; hwnd = (HWND)pcci->p1; w = pcci->p2; h = pcci->p3; update = pcci->p4; flags = SWP_NOMOVE /* retain position */ | SWP_NOZORDER; /* retain Z order */ /* flags do not contain SWP_NOREDRAW because otherwise not all windows get updated properly. */ SetWindowPos (hwnd, HWND_TOP, 0,0, w,h, flags); if (update!=0) /* still, updates are not sufficient using SetWindowPos only. */ UpdateWindowScrollbars (hwnd); MakeReturn0Cci (pcci); } break; /* Activate control. */ case CcRqACTIVATECONTROL: /* controlPtr; no result. */ { SetFocus ((HWND) pcci->p1); MakeReturn0Cci (pcci); } break; /* Activate window. */ case CcRqACTIVATEWINDOW: /* isMDI, clientPtr, thisWindow; no result. */ { BOOL isMDI; HWND clientPtr, thisWindow; isMDI = (BOOL) pcci->p1; clientPtr = (HWND) pcci->p2; thisWindow = (HWND) pcci->p3; if (isMDI) { SendMessage (clientPtr,WM_MDIACTIVATE,(WPARAM)thisWindow,(LPARAM)0); } else { SetActiveWindow (thisWindow); } MakeReturn0Cci (pcci); } break; case CcRqCHANGEWINDOWCURSOR: /* hwnd, cursor code; no result. It is assumed that the hwnd argument */ /* corresponds to either a SDI/MDI window (and not frame). */ { HWND hwnd; POINT p; int cursorcode; LocalWindowData wdata; hwnd = (HWND) pcci->p1; cursorcode = pcci->p2; GetCursorPos (&p); if (hwnd == WindowFromPoint (p) && SendMessage (hwnd, WM_NCHITTEST, 0, MAKELPARAM (p.x, p.y)) == HTCLIENT) { SetCursorFromCode (cursorcode); } wdata = (LocalWindowData) GetWindowLong (hwnd,0); wdata->lwd_cursorcode = cursorcode; SetWindowLong (hwnd, 0, (long)wdata); MakeReturn0Cci (pcci); } break; case CcRqOBSCURECURSOR: /* no params; no result. */ { SetCursor (GetHiddenCursor ()); MakeReturn0Cci (pcci); } break; case CcRqSETGLOBALCURSOR: /* cursorcode; no result. */ { HWND hwnd; gGlobalCursorCode = pcci->p1; hwnd = ApplicationWindowUnderCursor (); if (hwnd != NULL) SetCursorFromCode (gGlobalCursorCode); MakeReturn0Cci (pcci); } break; case CcRqRESETCURSOR: /* no params, no result. */ { HWND hwnd; gGlobalCursorCode = -1; hwnd = ApplicationWindowUnderCursor (); if (hwnd != NULL) { int hittestvalue; POINT p; GetCursorPos (&p); hittestvalue = SendMessage (hwnd, WM_NCHITTEST, 0, MAKELPARAM (p.x, p.y)); SendMessage (hwnd, WM_SETCURSOR, (WPARAM) hwnd, MAKELPARAM (hittestvalue, WM_MOUSEMOVE)); } MakeReturn0Cci (pcci); } break; /* Set range of scrollbars. */ case CcRqSETSCROLLRANGE: /* hwnd, iBar, min, max, redraw, no result */ { HWND hwnd; int min, max, iBar; BOOL redraw; hwnd = (HWND) pcci->p1; iBar = pcci->p2; min = pcci->p3; max = pcci->p4; redraw = (BOOL) pcci->p5; SetScrollRange (hwnd, iBar, min, max, redraw); MakeReturn0Cci (pcci); } break; /* Set pos of scrollbars. */ case CcRqSETSCROLLPOS: /* hwnd, iBar, thumb, maxx, maxy, extent, no result */ { HWND hwnd; int thumb, iBar, maxx, maxy, extent; SCROLLINFO sif; RECT scrollBarRect; BOOL noredraw; hwnd = (HWND) pcci->p1; iBar = pcci->p2; thumb = pcci->p3; maxx = pcci->p4; // maxx is the right-most x coordinate of the enclosing rectangle of the scrollbar maxy = pcci->p5; // maxy is the bottom-most y coordinate of the enclosing rectangle of the scrollbar extent = pcci->p6; // extent is the width (height) of the vertical (horizontal) scrollbar sif.cbSize = sizeof (SCROLLINFO); sif.fMask = SIF_POS; sif.nPos = thumb; SetScrollInfo (hwnd, iBar, &sif, TRUE); // Setting TRUE here to force redraw is not sufficient. noredraw = maxx==0 && maxy==0 && extent==0; if (!noredraw) // if the scrollbar does not need to be updated then all values must be zero { if (iBar==SB_HORZ) { scrollBarRect.left = 0; scrollBarRect.top = maxy-extent; scrollBarRect.right = maxx; scrollBarRect.bottom = maxy; } else { scrollBarRect.left = maxx-extent; scrollBarRect.top = 0; scrollBarRect.right = maxx; scrollBarRect.bottom = maxy; } InvalidateRect (hwnd, &scrollBarRect, FALSE); // UpdateWindow (hwnd); // PA: use RedrawWindow to immediately redraw the indicated scrollbar instead of update mechanism. if (!RedrawWindow (hwnd,&scrollBarRect,NULL,RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW | RDW_NOCHILDREN)) rMessageBox (NULL,MB_APPLMODAL,"CcRqSETSCROLLPOS","RedrawWindow failed"); ValidateRect (hwnd, &scrollBarRect); } MakeReturn0Cci (pcci); } break; /* Set thumb size of scrollbars. */ case CcRqSETSCROLLSIZE: /* hwnd, iBar, size, maxx, maxy, extent, no result */ { HWND hwnd; int size, iBar, maxx, maxy, extent; SCROLLINFO sif; RECT scrollBarRect; BOOL noredraw; hwnd = (HWND) pcci->p1; iBar = pcci->p2; size = pcci->p3; maxx = pcci->p4; // maxx is the right-most x coordinate of the enclosing rectangle of the scrollbar maxy = pcci->p5; // maxy is the bottom-most y coordinate of the enclosing rectangle of the scrollbar extent = pcci->p6; // extent is the width (height) of the vertical (horizontal) scrollbar sif.cbSize = sizeof (SCROLLINFO); sif.fMask = SIF_PAGE; sif.nPage = size; SetScrollInfo (hwnd, iBar, &sif, TRUE); // Setting TRUE here to force redraw is not sufficient. noredraw = maxx==0 && maxy==0 && extent==0; if (!noredraw) // if the scrollbar does not need to be updated then all values must be zero { if (iBar==SB_HORZ) { scrollBarRect.left = 0; scrollBarRect.top = maxy-extent; scrollBarRect.right = maxx; scrollBarRect.bottom = maxy; } else { scrollBarRect.left = maxx-extent; scrollBarRect.top = 0; scrollBarRect.right = maxx; scrollBarRect.bottom = maxy; } InvalidateRect (hwnd, &scrollBarRect, FALSE); // UpdateWindow (hwnd); // PA: use RedrawWindow to immediately redraw the indicated scrollbar instead of update mechanism. if (!RedrawWindow (hwnd,&scrollBarRect,NULL,RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW | RDW_NOCHILDREN)) rMessageBox (NULL,MB_APPLMODAL,"CcRqSETSCROLLSIZE","RedrawWindow failed"); ValidateRect (hwnd, &scrollBarRect); } MakeReturn0Cci (pcci); } break; /* Set selection of edit controls. */ case CcRqSETEDITSELECTION: /* hwnd, first, last, no result. */ { HWND hwnd; int first,last; hwnd = (HWND) pcci->p1; first = pcci->p2; last = pcci->p3; SendMessage (hwnd, EM_SETSEL, (WPARAM) first, (LPARAM) last); /* Set the selection of the edit control. */ SendMessage (hwnd, EM_SCROLLCARET, 0,0); /* Let the caret be displayed - (w/l)Param MUST be 0. */ MakeReturn0Cci (pcci); } break; /* Create a toolbar in a window. */ case CcRqCREATEMDITOOLBAR: /* hwnd, width, height; toolbarptr, full toolbar height result; */ { HWND hwndToolbar; HWND hwndParent; int bmpWidth, bmpHeight, tbHeight; RECT tbRect; hwndParent = (HWND) pcci->p1; // The parent is the frame window bmpWidth = pcci->p2; bmpHeight = pcci->p3; hwndToolbar = CreateWindow (TOOLBARCLASSNAME, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | CCS_TOP | TBSTYLE_TOOLTIPS, 0,0,0,0, hwndParent, (HMENU) NULL, (HANDLE) ghInst, 0 ); SetGWL_USERDATA ((LONG)hwndToolbar, hwndParent); // Administrate the toolbar handle in the MDI frame parent handle SendMessage (hwndToolbar, TB_SETBITMAPSIZE, (WPARAM)0, (LPARAM)MAKELONG(bmpWidth,bmpHeight)); SendMessage (hwndToolbar, TB_AUTOSIZE, (WPARAM)0, (LPARAM)0); SendMessage (hwndToolbar, TB_BUTTONSTRUCTSIZE, (WPARAM) sizeof (TBBUTTON), (LPARAM) 0); /* MDI windows that will get a toolbar are initially created with the WS_MINIMIZE flag (see CcRqCREATEMDIFRAMEWINDOW). This is needed to ensure that the toolbar, after creation, becomes visible. */ ShowWindow (hwndParent,SW_MAXIMIZE); if (!GetWindowRect (hwndToolbar,&tbRect)) rMessageBox (NULL,MB_APPLMODAL,"CcRqCREATEMDITOOLBAR","GetWindowRect failed"); tbHeight = tbRect.bottom - tbRect.top; MakeReturn2Cci (pcci,(int)hwndToolbar,tbHeight); } break; /* Create a toolbar in a SDI window. */ case CcRqCREATESDITOOLBAR: /* hwnd, width, height; toolbarptr, full toolbar height result; */ { HWND hwndParent,hwndClient,hwndToolbar; int bmpWidth, bmpHeight, tbHeight; RECT tbRect; hwndParent = (HWND) pcci->p1; bmpWidth = pcci->p2; bmpHeight = pcci->p3; hwndClient = GetSDIClientWindow (hwndParent); hwndToolbar = CreateWindow (TOOLBARCLASSNAME, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | CCS_TOP | TBSTYLE_TOOLTIPS, 0,0,0,0, hwndParent, (HMENU) NULL, (HANDLE) ghInst, 0 ); SetGWL_USERDATA ((LONG)hwndToolbar,hwndParent); // Administrate the toolbar handle in the SDI window handle SendMessage (hwndToolbar, TB_SETBITMAPSIZE, (WPARAM)0, (LPARAM)MAKELONG(bmpWidth,bmpHeight)); SendMessage (hwndToolbar, TB_AUTOSIZE, (WPARAM)0, (LPARAM)0); SendMessage (hwndToolbar, TB_BUTTONSTRUCTSIZE, (WPARAM) sizeof (TBBUTTON), (LPARAM) 0); if (!GetWindowRect (hwndToolbar,&tbRect)) rMessageBox (NULL,MB_APPLMODAL,"CcRqCREATESDITOOLBAR","GetWindowRect failed"); tbHeight = tbRect.bottom - tbRect.top; /* Before showing the new toolbar, move the client window down and update its scrollbars. */ if (hwndClient != NULL) { SetWindowPos (hwndClient,HWND_TOP,0,tbHeight,0,0,SWP_NOSIZE | SWP_NOZORDER); UpdateWindowScrollbars (hwndClient); } ShowWindow (hwndToolbar,SW_SHOWNORMAL); UpdateWindow (hwndToolbar); MakeReturn2Cci (pcci, (int) hwndToolbar, tbHeight); } break; /* Create a bitmap toolbar item. */ case CcRqCREATETOOLBARITEM: // hwnd, hbmp, index; no results; { HWND hwndToolbar; HBITMAP hbmp; int index; TBADDBITMAP tbab; TBBUTTON tbb; hwndToolbar= (HWND) pcci->p1; hbmp = (HBITMAP) pcci->p2; index = pcci->p3; tbab.hInst = NULL; tbab.nID = (UINT) hbmp; tbb.iBitmap = index-1; tbb.idCommand = index; tbb.fsState = (BYTE)TBSTATE_ENABLED; tbb.fsStyle = (BYTE)TBSTYLE_BUTTON; tbb.dwData = (DWORD)0; tbb.iString = 0; SendMessage (hwndToolbar, TB_BUTTONSTRUCTSIZE, (WPARAM) sizeof (TBBUTTON), (LPARAM) 0); SendMessage (hwndToolbar, TB_ADDBITMAP, (WPARAM)1, (LPARAM)(LPTBADDBITMAP)&tbab); SendMessage (hwndToolbar, TB_ADDBUTTONS,(WPARAM)(UINT)1, (LPARAM)(LPTBBUTTON)&tbb); MakeReturn0Cci (pcci); } break; /* Create a separator toolbar item. */ case CcRqCREATETOOLBARSEPARATOR: // hwnd; no results; { HWND hwndToolbar; TBBUTTON tbb; hwndToolbar = (HWND) pcci->p1; tbb.iBitmap = 0; tbb.idCommand = 0; tbb.fsState = (BYTE)TBSTATE_ENABLED; tbb.fsStyle = (BYTE)TBSTYLE_SEP; tbb.dwData = (DWORD)0; tbb.iString = 0; SendMessage (hwndToolbar, TB_BUTTONSTRUCTSIZE, (WPARAM) sizeof (TBBUTTON), (LPARAM) 0); SendMessage (hwndToolbar, TB_ADDBUTTONS,(WPARAM)(UINT)1, (LPARAM)(LPTBBUTTON)&tbb); MakeReturn0Cci (pcci); } break; /* CcRqUPDATEDESKTOP forces an update of the desktop and its applications. */ case CcRqUPDATEDESKTOP: /* no params; no result; */ { OSVERSIONINFO osVersionInfo; DWORD osPlatformID; osVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); /* Set size BEFORE calling GetVersionEx. */ if (GetVersionEx (&osVersionInfo)) { osPlatformID = osVersionInfo.dwPlatformId; if (osPlatformID==VER_PLATFORM_WIN32_WINDOWS) /* We're in Windows95. */ { char szParam[13] = "WindowMetrics"; SendMessage (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)SPI_SETICONMETRICS, (LPARAM)(LPCTSTR)szParam); } if (osPlatformID==VER_PLATFORM_WIN32_NT) /* We're in WindowsNT. */ { SendMessage (HWND_BROADCAST, WM_WININICHANGE, (WPARAM)SPI_SETICONMETRICS, (LPARAM)(LPCTSTR)NULL); } } /* if either GetVersionEx fails, or platform is different, skip refresh action altogether. */ MakeReturn0Cci (pcci); } break; /* Create the specialised directory selector dialog from Windows. By courtesy of Martijn Vervoort. */ case CcRqDIRECTORYDIALOG: /* no params; bool, textptr result; */ { char buffer[MAX_PATH]; LPITEMIDLIST pidlReturn; BROWSEINFO bi; char *s; char title[17] = "Select Directory\0"; bi.hwndOwner = GetActiveWindow (); bi.pidlRoot = NULL; bi.pszDisplayName = buffer; bi.lpszTitle = title; bi.ulFlags = BIF_RETURNONLYFSDIRS; bi.lpfn = NULL; bi.lParam = 0; CoInitialize (NULL); // Initialise the COM library; must be balanced by CoUninitialize() pidlReturn = SHBrowseForFolder (&bi); if (pidlReturn) { s = (char *) rmalloc (MAX_PATH+1); SHGetPathFromIDList (pidlReturn,s); CoTaskMemFree (pidlReturn); CoUninitialize (); // Uninitialise the COM library MakeReturn2Cci (pcci, (int)TRUE, (int)s); /* and have the calling Clean function deallocate the directory name buffer. */ } else { CoUninitialize (); // Uninitialise the COM library MakeReturn2Cci (pcci, (int)FALSE, (int)NULL); } } break; case CcRqFILEOPENDIALOG: /* no params; bool, textptr result; */ { OPENFILENAME ofn; BOOL success; ofn.lStructSize = sizeof (OPENFILENAME); ofn.hwndOwner = GetActiveWindow (); ofn.hInstance = NULL; ofn.lpstrFilter = NULL; ofn.lpstrCustomFilter = NULL; ofn.nMaxCustFilter = 0; ofn.nFilterIndex = 0; ofn.lpstrFile = (LPSTR) rmalloc (MAX_PATH); ofn.lpstrFile[0] = '\0'; ofn.nMaxFile = MAX_PATH; ofn.lpstrFileTitle = NULL; ofn.nMaxFileTitle = 0; ofn.lpstrInitialDir = NULL; ofn.lpstrTitle = NULL; ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_PATHMUSTEXIST | OFN_ENABLEHOOK; // PA: OFN_ENABLEHOOK added from Ronny ofn.lpstrDefExt = NULL; ofn.lCustData = 0; ofn.lpfnHook = &FileSelectorHook; // PA: &FileSelectorHook instead of NULL from Ronny ofn.lpTemplateName = NULL; gProhibitWindowActivation++; success = GetOpenFileName (&ofn); gProhibitWindowActivation--; if (success) { MakeReturn2Cci (pcci, success, (int) ofn.lpstrFile); /* and have the calling clean function deallocate the filename buffer */ } else { MakeReturn2Cci (pcci, success, (int) NULL); rfree (ofn.lpstrFile); } } break; case CcRqFILESAVEDIALOG: /* promptptr, nameptr; bool, textptr result; */ { OPENFILENAME ofn; BOOL success; char *promptptr; char *nameptr; promptptr = (char *) pcci->p1; nameptr = (char *) pcci->p2; if (rstrlen (promptptr) == 0) promptptr = NULL; /* the calling clean function will deallocate the memory allocated for this empty string */ ofn.lStructSize = sizeof (OPENFILENAME); // if (IsWindowEnabled (ghMainWindow)) // { // ofn.hwndOwner = ghMainWindow; // } // else // { ofn.hwndOwner = GetActiveWindow (); // } ofn.lpstrFilter = NULL; ofn.lpstrCustomFilter = NULL; ofn.nMaxCustFilter = 0; ofn.nFilterIndex = 0; ofn.lpstrFile = (LPSTR) rmalloc (MAX_PATH); if (rstrlen (nameptr) < MAX_PATH) { rscopy (ofn.lpstrFile, nameptr); } else { rsncopy (ofn.lpstrFile, nameptr, MAX_PATH - 1); ofn.lpstrFile[MAX_PATH - 1] = '\0'; } ofn.nMaxFile = MAX_PATH; ofn.lpstrFileTitle = NULL; ofn.nMaxFileTitle = 0; ofn.lpstrInitialDir = NULL; ofn.lpstrTitle = promptptr; ofn.Flags = OFN_EXPLORER | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY | OFN_ENABLEHOOK; // PA: OFN_ENABLEHOOK added from Ronny ofn.lpstrDefExt = NULL; ofn.lCustData = 0; ofn.lpfnHook = &FileSelectorHook; // PA: &FileSelectorHook instead of NULL from Ronny ofn.lpTemplateName = NULL; gProhibitWindowActivation++; success = GetSaveFileName (&ofn); gProhibitWindowActivation--; if (success) { MakeReturn2Cci (pcci, success, (int) ofn.lpstrFile); /* and have the calling clean function deallocate the filename buffer */ } else { MakeReturn2Cci (pcci, success, (int) NULL); rfree (ofn.lpstrFile); } } break; /* CcRqCREATEDIALOG is now restricted to modeless dialogues only. */ case CcRqCREATEDIALOG: // textptr,parentptr,behindPtr; HWND result. { WORD *p, *pdlgtemplate; int nchar; DWORD lStyle; HWND hwnd,hwndParent,hwndBehind; hwndParent = (HWND) pcci->p2; // The owner window hwndBehind = (HWND) pcci->p3; // The stacking window // allocate some memory to play with pdlgtemplate = p = (PWORD) rmalloc (1000); // start to fill in the dlgtemplate information. Addressing by WORDs lStyle = WS_CAPTION | DS_SETFONT | DS_MODALFRAME | WS_SYSMENU | WS_OVERLAPPED; *p++ = LOWORD (lStyle); *p++ = HIWORD (lStyle); *p++ = 0; // LOWORD (lExtendedStyle) *p++ = 0; // HIWORD (lExtendedStyle) *p++ = 0; // NumberOfItems *p++ = 0; // x (dummy value) *p++ = 0; // y (dummy value) *p++ = 1000; // cx (dummy value) *p++ = 1000; // cy (dummy value) *p++ = 0; // Menu *p++ = 0; // Class // copy the title of the dialog nchar = nCopyAnsiToWideChar (p, (char *) pcci->p1); p += nchar; // Font information because of DS_SETFONT *p++ = 8; // point size nchar = nCopyAnsiToWideChar (p, "MS Sans Serif"); // Face name p += nchar; // make sure the first item starts on a DWORD boundary hwnd = CreateDialogIndirectParam (ghInst, (LPDLGTEMPLATE) pdlgtemplate, hwndParent, (DLGPROC) DialogProcedure, (LPARAM) 0); LocalFree (LocalHandle (pdlgtemplate)); if (hwndBehind!=NULL) // In case the dialog should not be opened top-most: { UINT uflags = SWP_NOMOVE + SWP_NOSIZE; // then restack the dialog. SetWindowPos (hwnd,hwndBehind, 0,0,0,0, uflags); } ShowWindow (hwnd, SW_SHOWNORMAL); // Only now the dialog should be made visible. UpdateWindow (hwnd); MakeReturn1Cci (pcci, (int) hwnd); } break; /* Create modal dialogues. */ case CcRqCREATEMODALDIALOG: /* textptr,parentptr; error code result. */ { WORD *p, *pdlgtemplate; int nchar, errorcode; DWORD lStyle; HWND hwndParent; UINT zeroTimer; hwndParent = (HWND) pcci->p2; /* The owner window */ if (hwndParent == 0) hwndParent = ghMainWindow; /* If no parent is passed (NDI) then ghMainWindow should be the parent. */ /* allocate some memory to play with */ pdlgtemplate = p = (PWORD) rmalloc (1000); /* start to fill in the dlgtemplate information. Addressing by WORDs */ lStyle = WS_CAPTION | DS_SETFONT | DS_MODALFRAME | WS_SYSMENU | DS_SYSMODAL | WS_VISIBLE; *p++ = LOWORD (lStyle); *p++ = HIWORD (lStyle); *p++ = 0; /* LOWORD (lExtendedStyle) */ *p++ = 0; /* HIWORD (lExtendedStyle) */ *p++ = 0; /* NumberOfItems */ *p++ = 0; /* x (dummy value) */ *p++ = 0; /* y (dummy value) */ *p++ = 1000; /* cx (dummy value) */ *p++ = 1000; /* cy (dummy value) */ *p++ = 0; /* Menu */ *p++ = 0; /* Class */ /* copy the title of the dialog */ nchar = nCopyAnsiToWideChar (p, (char *) pcci->p1); p += nchar; /* Font information because of DS_SETFONT */ *p++ = 8; /* point size */ nchar = nCopyAnsiToWideChar (p, "MS Sans Serif"); /* Face name */ p += nchar; /* make sure the first item starts on a DWORD boundary */ /* Before the modal dialog enters its event loop we create a timer to generate timer events. This is done only once per modal dialog stack. */ if (ghwndLastModalDialog == NULL) // The first modal dialog. { zeroTimer = SetTimer (NULL, (UINT) 0, (UINT) 0, NULL); if (zeroTimer==0) // Creation of zero timer failed. { LocalFree (LocalHandle (pdlgtemplate)); errorcode = 1; // Report error to Clean side } else { DialogBoxIndirectParam (ghInst, (LPDLGTEMPLATE) pdlgtemplate, hwndParent, (DLGPROC) DialogProcedure, (LPARAM) 0); LocalFree (LocalHandle (pdlgtemplate)); KillTimer (NULL, (UINT) zeroTimer); errorcode = 0; // Report no error to Clean side } } else // a zero timer has already been created. { DialogBoxIndirectParam (ghInst, (LPDLGTEMPLATE) pdlgtemplate, hwndParent, (DLGPROC) DialogProcedure, (LPARAM) 0); LocalFree (LocalHandle (pdlgtemplate)); errorcode = 0; // Report no error to Clean side } MakeReturn1Cci (pcci,errorcode); } break; /* Create compound controls (window in window) */ case CcRqCREATECOMPOUND: /* hwnd, packed pos,w,h, scrollbars, transparent; HWND result. */ { HWND parentwindow, compoundhandle; int left,top, width,height; int compoundstyle; BOOL transparent; DWORD compoundExStyle; parentwindow = (HWND) pcci->p1; left = pcci->p2>>16; top = (pcci->p2<<16)>>16; width = pcci->p3; height = pcci->p4; compoundstyle = pcci->p5; transparent = (BOOL) pcci->p6; compoundExStyle = WS_EX_CONTROLPARENT; if (transparent) compoundExStyle |= WS_EX_TRANSPARENT; compoundstyle |= WS_CHILD;// | WS_CLIPSIBLINGS; /* create the compound window */ compoundhandle = CreateWindowEx (compoundExStyle, /* Extended style */ CompoundControlClassName, /* Class name */ "", /* Window title */ compoundstyle, /* style flags */ left, top, /* x, y */ width, height, /* width, height */ parentwindow, /* Parent window */ NULL, /* menu handle */ (HANDLE) ghInst, /* Instance that owns the window */ 0); SendMessage (compoundhandle, WM_SETFONT, (WPARAM)gControlFont, MAKELPARAM (TRUE,0)); SetWindowPos (compoundhandle, HWND_BOTTOM, 0,0,0,0, SWP_NOMOVE+SWP_NOSIZE); // This should implement control stack MakeReturn1Cci (pcci, (int) compoundhandle); } break; /* Create scrollbars. */ case CcRqCREATESCROLLBAR: /* hwnd, x,y,w,h bool; HWND result. */ { HWND scroll; int style; int x, y, w, h; HWND parent; BOOL ishorizontal; parent = (HWND) pcci->p1; x = pcci->p2; y = pcci->p3; w = pcci->p4; h = pcci->p5; ishorizontal = pcci->p6; style = WS_CHILD | WS_GROUP | WS_CLIPSIBLINGS; if (ishorizontal) style |= SBS_HORZ; else style |= SBS_VERT; scroll = CreateWindow ( "scrollbar", "", style, x, y, w, h, parent, 0, ghInst, 0); SendMessage (scroll, WM_SETFONT, (WPARAM)gControlFont, MAKELPARAM (TRUE,0)); SetWindowPos (scroll, HWND_BOTTOM, 0,0,0,0, SWP_NOMOVE+SWP_NOSIZE); // This should implement control stack MakeReturn1Cci (pcci, (int) scroll); } break; case CcRqCREATEBUTTON: /* hwnd, x,y,w,h, kind; HWND result. */ { HWND but, parent; int style, id; int x, y, w, h, kind; parent = (HWND) pcci->p1; x = pcci->p2; y = pcci->p3; w = pcci->p4; h = pcci->p5; kind = pcci->p6; style = WS_CHILD | WS_GROUP | WS_TABSTOP | WS_CLIPSIBLINGS; if (kind==ISOKBUTTON) { style |= BS_DEFPUSHBUTTON; id = IDOK; } else { style |= BS_PUSHBUTTON; if (kind==ISCANCELBUTTON) { id = IDCANCEL; } else { id = 0; } } but = CreateWindow ("button", "", style, x, y, w, h, parent, (HMENU) id, ghInst, 0); SendMessage (but, WM_SETFONT, (WPARAM)gControlFont, MAKELPARAM (TRUE,0)); SetWindowPos (but, HWND_BOTTOM, 0,0,0,0, SWP_NOMOVE+SWP_NOSIZE); // This should implement control stack MakeReturn1Cci (pcci, (int) but); } break; case CcRqCREATEICONBUT: /* hwnd, x,y,w,h,kind; HWND result. */ { HWND but, parent; int style, id, x, y, w, h, kind; parent = (HWND) pcci->p1; x = pcci->p2; y = pcci->p3; w = pcci->p4; h = pcci->p5; kind = pcci->p6; style = WS_CHILD | WS_GROUP | WS_TABSTOP | BS_OWNERDRAW | WS_CLIPSIBLINGS; switch (kind) { case ISOKBUTTON: id = IDOK; break; case ISCANCELBUTTON: id = IDCANCEL; break; default: id = 0; } but = CreateWindow ("button", "", style, x, y, w, h, parent, (HMENU) id, ghInst, 0); SendMessage (but, WM_SETFONT, (WPARAM)gControlFont, MAKELPARAM (TRUE,0)); SetWindowPos (but, HWND_BOTTOM, 0,0,0,0, SWP_NOMOVE+SWP_NOSIZE); // This should implement control stack MakeReturn1Cci (pcci, (int) but); } break; case CcRqCREATECUSTOM: /* hwnd, x,y,w,h; HWND result. */ { HWND ctrl, parent; int style, x, y, w, h; parent = (HWND) pcci->p1; x = pcci->p2; y = pcci->p3; w = pcci->p4; h = pcci->p5; style = WS_CHILD | WS_GROUP | WS_TABSTOP | WS_CLIPSIBLINGS; // Necessary to enforce proper control stack ctrl = CreateWindow (CustomControlClassName, "", style, x, y, w, h, parent, (HMENU) 0, ghInst, 0); SendMessage (ctrl, WM_SETFONT, (WPARAM)gControlFont, MAKELPARAM (TRUE,0)); SetWindowPos (ctrl, HWND_BOTTOM, 0,0,0,0, SWP_NOMOVE+SWP_NOSIZE); // This should implement control stack MakeReturn1Cci (pcci, (int) ctrl); } break; case CcRqCREATESTATICTXT: /* hwnd, x,y,w,h; HWND result. */ { HWND handle; int x, y, w, h, style; HWND parent; parent = (HWND) pcci->p1; x = pcci->p2; y = pcci->p3; w = pcci->p4; h = pcci->p5; style = WS_CHILD | WS_GROUP | SS_LEFTNOWORDWRAP // PA: SS_LEFT replaced by SS_LEFTNOWORDWRAP because text wrapping is not intended for text controls | WS_CLIPSIBLINGS; handle = CreateWindow ( "static", "", style, x, y, w, h, parent, 0, ghInst, 0); SendMessage (handle, WM_SETFONT, (WPARAM)gControlFont, MAKELPARAM (TRUE,0)); SetWindowPos (handle, HWND_BOTTOM, 0,0,0,0, SWP_NOMOVE+SWP_NOSIZE); // This should implement control stack MakeReturn1Cci (pcci, (int) handle); } break; case CcRqCREATEEDITTXT: /* hwnd, x,y,w,h, flags; HWND result. */ { HWND handle; int x, y, w, h, style, flags; HWND parent; BOOL isml,isKeySensitive; parent = (HWND) pcci->p1; x = pcci->p2; y = pcci->p3; w = pcci->p4; h = pcci->p5; flags = pcci->p6; isml = flags & EDITISMULTILINE; isKeySensitive = flags & EDITISKEYSENSITIVE; style = WS_CHILD | WS_GROUP | WS_TABSTOP | ES_LEFT | WS_CLIPSIBLINGS; if (isml) style |= ES_AUTOVSCROLL | ES_MULTILINE | ES_WANTRETURN; else style |= ES_AUTOHSCROLL | ES_MULTILINE; handle = CreateWindowEx (WS_EX_CLIENTEDGE, "edit", "", style, x, y, w, h, parent, 0, ghInst, 0); SendMessage (handle, WM_SETFONT, (WPARAM)gControlFont, MAKELPARAM (TRUE,0)); SetWindowPos (handle, HWND_BOTTOM, 0,0,0,0, SWP_NOMOVE+SWP_NOSIZE); // This should implement control stack /* Store the standard Windows callback routine adress in stdEditCallback and subclass the edit control with EditControlProcedure if isKeySensitive and SimpleEditControlProcedure otherwise. */ if (isKeySensitive) { stdEditCallback = SetWindowLong (handle, GWL_WNDPROC, (LONG) EditControlProcedure); } else { stdEditCallback = SetWindowLong (handle, GWL_WNDPROC, (LONG) SimpleEditControlProcedure); } MakeReturn1Cci (pcci, (int) handle); } break; case CcRqCREATERADIOBUT: /* hwnd, x,y,w,h, isfirst; HWND result. */ { HWND handle; int x, y, w, h, style; HWND parent; BOOL first; parent = (HWND) pcci->p1; x = pcci->p2; y = pcci->p3; w = pcci->p4; h = pcci->p5; first = pcci->p6; style = WS_CHILD | BS_AUTORADIOBUTTON | WS_CLIPSIBLINGS; if (first) style |= WS_GROUP | WS_TABSTOP; handle = CreateWindow ( "button", "", style, x, y, w, h, parent, 0, ghInst, 0); SendMessage (handle, WM_SETFONT, (WPARAM)gControlFont, MAKELPARAM (TRUE,0)); SetWindowPos (handle, HWND_BOTTOM, 0,0,0,0, SWP_NOMOVE+SWP_NOSIZE); // This should implement control stack MakeReturn1Cci (pcci, (int) handle); } break; case CcRqCREATECHECKBOX: /* hwnd, x,y,w,h, isfirst; HWND result. */ { HWND handle; int x, y, w, h, style; HWND parent; BOOL first; parent = (HWND) pcci->p1; x = pcci->p2; y = pcci->p3; w = pcci->p4; h = pcci->p5; first = pcci->p6; style = WS_CHILD | BS_AUTOCHECKBOX | WS_CLIPSIBLINGS; if (first) style |= WS_GROUP | WS_TABSTOP; handle = CreateWindow ( "button", "", style, x, y, w, h, parent, 0, ghInst, 0); SendMessage (handle, WM_SETFONT, (WPARAM)gControlFont, MAKELPARAM (TRUE,0)); SetWindowPos (handle, HWND_BOTTOM, 0,0,0,0, SWP_NOMOVE+SWP_NOSIZE); // This should implement control stack MakeReturn1Cci (pcci, (int) handle); } break; case CcRqSETITEMCHECK: /* hwnd, bool; no result. */ { HWND hwnd; BOOL on; int check; hwnd = (HWND) pcci->p1; on = pcci->p2; if (on) check = 1; else check = 0; SendMessage (hwnd, BM_SETCHECK, (WPARAM) check, 0); MakeReturn0Cci (pcci); } break; case CcRqENABLECONTROL: /* hwnd, bool; no result. */ { HWND window; BOOL wasUnable, newSelect; window = (HWND) pcci->p1; newSelect = (BOOL) pcci->p2; wasUnable = EnableWindow (window, newSelect); if (wasUnable != newSelect) InvalidateRect (window, NULL, FALSE); MakeReturn0Cci (pcci); } break; case CcRqSHOWCONTROL: // hwnd, bool; no result. { int nCmdShow; if (pcci->p2) nCmdShow = SW_SHOWNA; else nCmdShow = SW_HIDE; ShowWindow ((HWND) pcci->p1, nCmdShow); MakeReturn0Cci (pcci); } break; /* Hide/show windows. */ case CcRqSHOWWINDOW: /* hwnd, show, activate; no result. */ { int nCmdShow; BOOL show, activate; HWND wPtr; wPtr = (HWND) pcci->p1; show = (BOOL) pcci->p2; activate = (BOOL) pcci->p3; if (!show) nCmdShow = SW_HIDE; else if (activate) nCmdShow = SW_SHOW; else nCmdShow = SW_SHOWNOACTIVATE; ShowWindow (wPtr, nCmdShow); MakeReturn0Cci (pcci); } break; case CcRqCREATEPOPUP: /* hwnd, x,y,w,h,isEditable; HWND hwndPopUp,hwndEdit (if isEditable). */ { HWND parent, hwndPopUp, hwndEdit; int x, y, w, h; int style; BOOL isEditable; parent = (HWND) pcci->p1; x = pcci->p2; y = pcci->p3; w = pcci->p4; h = pcci->p5; isEditable = (BOOL) pcci->p6; style = WS_CHILD | WS_GROUP | WS_TABSTOP | WS_VSCROLL | CBS_AUTOHSCROLL // | CBS_OWNERDRAWFIXED // PA: removed, otherwise garbage strings appear for empty popups. | CBS_HASSTRINGS | WS_CLIPSIBLINGS; if (isEditable) style |= CBS_DROPDOWN; else style |= CBS_DROPDOWNLIST; hwndPopUp = CreateWindowEx (0, "COMBOBOX", "", style, x, y, w, h, parent, (HMENU) 0, ghInst, 0); SendMessage (hwndPopUp, CB_SETEXTENDEDUI, (WPARAM) TRUE, 0); SendMessage (hwndPopUp, WM_SETFONT, (WPARAM)gControlFont, MAKELPARAM (TRUE,0)); SetWindowPos (hwndPopUp, HWND_BOTTOM, 0,0,0,0, SWP_NOMOVE+SWP_NOSIZE); // This should implement control stack /* Store the standard Windows callback routine adress in stdPopUpCallback and subclass the combobox's edit control with PopUpControlProcedure. */ if (isEditable) { hwndEdit = GetWindow (hwndPopUp,GW_CHILD); stdPopUpCallback = SetWindowLong (hwndEdit, GWL_WNDPROC, (LONG) PopUpControlProcedure); } else { hwndEdit = 0; } MakeReturn2Cci (pcci, (int) hwndPopUp, (int) hwndEdit); } break; case CcRqADDTOPOPUP: /* hwnd, textptr, enabled, selected, index; Pos result. */ { int index, pos; HWND hpopup; char *text; BOOL enabled, selected; hpopup = (HWND) pcci->p1; text = (char *) pcci->p2; enabled = (BOOL) pcci->p3; selected = (BOOL) pcci->p4; index = (int) pcci->p5; pos = SendMessage (hpopup, CB_ADDSTRING, 0, (LPARAM) text); //pos = SendMessage (hpopup, CB_INSERTSTRING, (WPARAM) index, (LPARAM) text); SendMessage (hpopup, CB_SETITEMDATA, (WPARAM) pos, (LPARAM) enabled); if (selected) SendMessage (hpopup, CB_SETCURSEL, (WPARAM) pos, 0); MakeReturn1Cci (pcci, pos); } break; case CcRqSELECTPOPUPITEM: /* hwnd, pos; no result */ { HWND hpopup; int pos; hpopup = (HWND) pcci->p1; pos = pcci->p2; SendMessage (hpopup, CB_SETCURSEL, (WPARAM) pos, 0); MakeReturn0Cci (pcci); } break; case CcRqENABLEPOPUPITEM: /* hwnd, pos, enabled; no result */ { HWND hpopup; int pos; LPARAM enabled; hpopup = (HWND) pcci->p1; pos = pcci->p2; enabled = (LPARAM) pcci->p3; SendMessage (hpopup, CB_SETITEMDATA, (WPARAM) pos, enabled); if (SendMessage (hpopup, CB_GETCURSEL, 0, 0) == pos) { InvalidateRect (hpopup, NULL, TRUE); } MakeReturn0Cci (pcci); } break; /* CcRqCLIPBOARDHASTEXT had no implementation. It checks if the clipboard has a CF_TEXT item. */ case CcRqCLIPBOARDHASTEXT: /* no arguments; bool result. */ { BOOL ok = IsClipboardFormatAvailable (CF_TEXT); MakeReturn1Cci (pcci,(int) ok); } break; case CcRqSETCLIPBOARDTEXT: /* textptr; no result. */ { HANDLE hClipText; char *pClipText; int len; char *txt; txt = (char *) pcci->p1; len = lstrlen (txt); hClipText = GlobalAlloc (GMEM_MOVEABLE | GMEM_DDESHARE, len + 1); if (hClipText != NULL) { pClipText = GlobalLock (hClipText); lstrcpyn (pClipText, txt, len + 1); GlobalUnlock (hClipText); OpenClipboard (ghMainWindow); EmptyClipboard (); SetClipboardData (CF_TEXT, hClipText); CloseClipboard (); } MakeReturn0Cci (pcci); } break; case CcRqGETCLIPBOARDTEXT: /* no params; string result. */ { HANDLE hClipText; char *pClipText; char *result; int len; OpenClipboard (ghMainWindow); hClipText = GetClipboardData (CF_TEXT); if (hClipText == NULL) { result = rmalloc (1); result[0] = '\0'; } else { len = GlobalSize (hClipText) - 1; result = rmalloc (len + 1); pClipText = GlobalLock (hClipText); len = lstrlen (pClipText); lstrcpyn (result, pClipText, len + 1); GlobalUnlock (hClipText); } CloseClipboard (); MakeReturn1Cci (pcci, (int) result); } break; /* CcRqGETCLIPBOARDCOUNT is used by Clean to retrieve current clipboard count. */ case CcRqGETCLIPBOARDCOUNT: /* no arguments; gClipboardCount result. */ { MakeReturn1Cci (pcci, gClipboardCount); } break; /* Implement WinRestackWindow as a crosscall operation. */ case CcRqRESTACKWINDOW: /* thewindow,behind; no result. */ { HWND thePtr, behindPtr; UINT uflags = SWP_NOMOVE + SWP_NOSIZE; /* Do not change current size or location */ thePtr = (HWND) pcci->p1; behindPtr = (HWND) pcci->p2; SetWindowPos (thePtr, behindPtr, 0, 0, 0, 0, uflags); MakeReturn0Cci (pcci); } break; /* Add controls to tooltip area. */ case CcRqADDCONTROLTIP: /* parentPtr, controlPtr, textPtr; no result. */ { HWND hwndParent,hwndControl; /* The handle to the window and control. */ TOOLINFO ti; /* The tool information that is sent to the tooltip control. */ char *text; hwndParent = (HWND) pcci->p1; hwndControl = (HWND) pcci->p2; text = (char *)pcci->p3; /* Fill the tooltip info with the appropriate information. */ ti.cbSize = sizeof(TOOLINFO); ti.uFlags = TTF_IDISHWND | TTF_SUBCLASS; ti.hwnd = hwndParent; ti.uId = (UINT) hwndControl; ti.rect.left = 0; ti.rect.top = 0; ti.rect.right = 0; ti.rect.bottom= 0; ti.hinst = ghInst; ti.lpszText = (LPSTR) text; SendMessage (ghwndTT, TTM_ADDTOOL, 0, (LPARAM) (LPTOOLINFO)&ti); MakeReturn0Cci (pcci); } break; /* Remove controls from tooltip area. */ case CcRqDELCONTROLTIP: /* parentPtr, controlPtr; no result. */ { HWND hwndParent,hwndControl; /* The handle to the window and control. */ TOOLINFO ti; /* The tool information that is sent to the tooltip control. */ hwndParent = (HWND) pcci->p1; hwndControl = (HWND) pcci->p2; /* Fill the tooltip info with the appropriate information. */ ti.cbSize = sizeof(TOOLINFO); ti.uFlags = TTF_IDISHWND; ti.hwnd = hwndParent; ti.uId = (UINT) hwndControl; SendMessage (ghwndTT, TTM_DELTOOL, 0, (LPARAM) (LPTOOLINFO)&ti); MakeReturn0Cci (pcci); } break; // MW... case CcRqDO_PRINT_SETUP: { int ok; PRINTDLG *pdPtr; printSetup(0, pcci->p1, (char*) pcci->p2, (char*) pcci->p3, (char*) pcci->p4, (char*) pcci->p5, &ok, &pdPtr); MakeReturn2Cci (pcci, ok, (int) pdPtr); } break; case CcRqGET_PRINTER_DC: { int doDialog,emulateScreenRes, err,first,last,copies,pPrintDlg,deviceContext; // unpack doDialog and emulateScreenRes doDialog = (pcci->p1) & 1; emulateScreenRes = (pcci->p1) & 2; getDC( doDialog,emulateScreenRes,FALSE,pcci->p2, (char*) pcci->p3,(char*) pcci->p4,(char*) pcci->p5,(char*) pcci->p6, &err,&first,&last,&copies,(PRINTDLG**)&pPrintDlg,&deviceContext); MakeReturn6Cci (pcci,err,first,last,copies,pPrintDlg,deviceContext); } break; case CcRqSTARTDOC: { HDC hdc = (HDC) pcci->p1; int err; EnableWindow (ghMainWindow, FALSE) ; hDlgPrint = CreateCancelDialog (); SetAbortProc (hdc, AbortProc) ; err = startDoc((int) hdc); if (err<=0 && ghMainWindow!=NULL && !bUserAbort) { EnableWindow (ghMainWindow, TRUE) ; DestroyWindow (hDlgPrint) ; }; MakeReturn1Cci (pcci,err); } break; case CcRqENDDOC: { HDC hdc = (HDC) pcci->p1; endDoc((int) hdc); if (ghMainWindow!=NULL && !bUserAbort) { EnableWindow (ghMainWindow, TRUE) ; DestroyWindow (hDlgPrint) ; }; MakeReturn0Cci (pcci); } break; case CcRqDISPATCH_MESSAGES_WHILE_PRINTING: { MSG msg ; char *pageMessage= (char*) (pcci->p1); SetWindowText(hwndText,pageMessage); while (!bUserAbort && PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) { if (!hDlgPrint || !IsDialogMessage (hDlgPrint, &msg)) { TranslateMessage (&msg) ; DispatchMessage (&msg) ; } } MakeReturn0Cci (pcci); } break; #ifdef HILT case CcRqDO_HTML_HELP: { char *chmFileAndWType; HWND hwnd,hwndHelp; int command; chmFileAndWType = (char*) (pcci->p1); hwnd = (HWND) (pcci->p2); command = pcci->p3; if (!htmlHelpInitialized) { HtmlHelp(hwnd, NULL, HH_INITIALIZE, (DWORD)&htmlHelpCookie); htmlHelpInitialized = TRUE; }; hwndHelp = HtmlHelp(hwnd,chmFileAndWType,command,(DWORD)NULL); if (hwndHelp==0) rMessageBox(hwnd, MB_APPLMODAL, "Error", "htmlHelp called with wrong parameters"); MakeReturn0Cci (pcci); } break; #endif // ... MW default: { rprintf ("\'HandleCleanRequest\' got unkown request from Clean: "); printCCI (pcci); ErrorExit ("\'HandleCleanRequest\' got unkown request from Clean: %d\n", pcci->mess); } } KickCleanThread (pcci); } OS WinDestroyMenu (HMENU menu, OS os) { rprintf ("DestroyMenu: menu = %d\n", (int) menu); DestroyMenu (menu); return (os); } BOOL CleanThreadRunning (void) { return GetCurrentThreadId () == gCleanThreadId; } BOOL OsThreadRunning (void) { return GetCurrentThreadId () == gOsThreadId; } extern EXPORT_TO_CLEAN void WinInitOs (Bool * ok, OS * os) { if (gEventsInited) { *ok = FALSE; rprintf ("WIO: *ok = FALSE\n"); } else { *ok = TRUE; gEventsInited = TRUE; rprintf ("WIO: *ok = TRUE\n"); } *os = 54321; } extern EXPORT_TO_CLEAN Bool WinCloseOs (OS os) { if (gEventsInited) { rprintf ("WCO: return TRUE\n"); gEventsInited = FALSE; return TRUE; } else { rprintf ("WCO: return FALSE\n"); return FALSE; } } extern EXPORT_TO_CLEAN OS WinStartOsThread (OS os) { rprintf ("WSOT: Started\n"); InitGlobals (); rprintf ("WSOT: Globals Inited\n"); gCLEAN_DONE = CreateEvent (NULL, /* Default security attributes */ FALSE, /* Not a manual-reset event */ FALSE, /* Initial state nonsignalled */ NULL); /* No name */ Check ((BOOL) gCLEAN_DONE, "\'InitOs\' could not create first event object"); rprintf ("WSOT: CLEANDONE event created\n"); gOS_DONE = CreateEvent (NULL, FALSE, FALSE, NULL); Check ((BOOL) gOS_DONE, "\'InitOs\' could not create second event object"); rprintf ("WSOT: OS_DONE event created\n"); gCleanThreadId = GetCurrentThreadId (); rprintf ("WSOT: gor current thread id\n"); ghOSThreadHandle = CreateThread (NULL, /* Default security attributes */ 0, /* Default stacksize */ (LPTHREAD_START_ROUTINE) OsThreadFunction, 0, /* parameter to thread function */ 0, /* Not initially suspended */ &(gOsThreadId)); /* store threadId here */ Check ((BOOL) ghOSThreadHandle, "\'InitOs\' could not create second thread"); // PA!!! test fails rprintf ("WSOT: new thread created\n"); WaitForSingleObject (gOS_DONE, INFINITE); rprintf ("WSOT: wait done\n"); return os; } extern EXPORT_TO_CLEAN OS WinKillOsThread (OS os) { rprintf ("OS WinKillOsThread (OS os)\n"); #ifdef HILT if (htmlHelpInitialized) { HtmlHelp(NULL, NULL, HH_UNINITIALIZE, htmlHelpCookie); htmlHelpInitialized = FALSE; }; #endif if (ghOSThreadHandle != NULL) { rprintf ("ghOSThreadHandle != NULL\n"); TerminateThread (ghOSThreadHandle, 0); rprintf (" TerminateThread(ghOSThreadHandle, 0);\n"); ghOSThreadHandle = NULL; rprintf (" ghOSThreadHandle = NULL;\n"); /* CleanUp */ if (gAcceleratorTable) DestroyAcceleratorTable (gAcceleratorTable); rprintf (" if (gAcceleratorTable) \n"); rprintf (" DestroyAcceleratorTable( gAcceleratorTable );\n"); DeleteCursors (); rprintf (" DeleteCursors();\n"); CloseHandle (gOS_DONE); gOS_DONE = NULL; rprintf (" CloseHandle(gOS_DONE); gOS_DONE = NULL;\n"); CloseHandle (gCLEAN_DONE); gCLEAN_DONE = NULL; rprintf (" CloseHandle(gCLEAN_DONE); gCLEAN_DONE = NULL;\n"); if (gDlogFont != NULL) DeleteObject (gDlogFont); rprintf (" if(gDlogFont != NULL)\n"); rprintf (" DeleteObject(gDlogFont);\n"); if (gWinFont != NULL) DeleteObject (gWinFont); rprintf (" if(gWinFont != NULL)\n"); rprintf (" DeleteObject(gWinFont);\n"); DeleteObject (gControlFont); // The global logical font must be deleted. }; // MW... ghMainWindow = NULL; // ... MW return os; } extern EXPORT_TO_CLEAN void WinKickOsThread (int imess, int ip1, int ip2, int ip3, int ip4, int ip5, int ip6, OS ios, int *omess, int *op1, int *op2, int *op3, int *op4, int *op5, int *op6, OS * oos) { /* rprintf("KOT: filling in Cci\n"); */ rprintf ("WinKickOsThread ("); printCCI (&gCci); rprintf (")\n"); gCci.mess = imess; gCci.p1 = ip1; gCci.p2 = ip2; gCci.p3 = ip3; gCci.p4 = ip4; gCci.p5 = ip5; gCci.p6 = ip6; if (ghOSThreadHandle != NULL) { rprintf ("KOT: Cci filled in, setting event\n"); SetEvent (gCLEAN_DONE); rprintf ("KOT: Event set, start wait.\n"); WaitForSingleObject (gOS_DONE, INFINITE); rprintf ("KOT: wait done, reading out Cci.\n"); *omess = gCci.mess; *op1 = gCci.p1; *op2 = gCci.p2; *op3 = gCci.p3; *op4 = gCci.p4; *op5 = gCci.p5; *op6 = gCci.p6; *oos = ios; rprintf ("KOT: Cci read: {"); printCCI (&gCci); rprintf ("}\n"); } else { rprintf ("KOT: no thread existed, returning CcWASQUIT for <"); printCCI (&gCci); rprintf (">\n"); *omess = CcWASQUIT; *op1 = 0; *op2 = 0; *op3 = 0; *op4 = 0; *op5 = 0; *op6 = 0; *oos = ios; } rprintf ("KOT: done.\n"); } #define PRINTCROSSCALLS #ifdef PRINTCROSSCALLS static CrossCallInfo osstack[10]; static CrossCallInfo clstack[10]; static int ossp = -1; static int clsp = -1; #endif void KickCleanThread (CrossCallInfo * pcci) { #ifdef PRINTCROSSCALLS if (ossp == -1) { for (ossp = 0; ossp < 10; ossp++) { osstack[ossp].mess = -1; } ossp = 1; osstack[ossp].mess = -2; } if (clsp == -1) { for (clsp = 0; clsp < 10; clsp++) { clstack[clsp].mess = -1; } clsp = 1; clstack[clsp].mess = -2; } #endif if (pcci != &gCci) gCci = *pcci; rprintf ("KCT: started\n"); #ifdef PRINTCROSSCALLS if (gCci.mess < 20) { rprintf (" -- %d --> OS returning <", clsp + ossp - 2); printCCI (&gCci); rprintf ("> from <"); printCCI (&(clstack[clsp])); rprintf (">\n"); clsp--; } else { ossp++; osstack[ossp] = gCci; rprintf (" -- %d --> OS calling with <", clsp + ossp - 2); printCCI (&gCci); rprintf (">\n"); } #endif rprintf ("KCT: setting event\n"); SetEvent (gOS_DONE); rprintf ("KCT: starting wait\n"); WaitForSingleObject (gCLEAN_DONE, INFINITE); rprintf ("KCT: wait done.\n"); if (pcci != &gCci) *pcci = gCci; #ifdef PRINTCROSSCALLS if (gCci.mess < 20) { rprintf (" <-- %d -- Clean returning <", clsp + ossp - 2); printCCI (&gCci); rprintf ("> from <"); printCCI (&(osstack[ossp])); rprintf (">\n"); ossp--; } else { clsp++; clstack[clsp] = gCci; rprintf (" <-- %d -- Clean calling with <", clsp + ossp - 2); printCCI (&gCci); rprintf (">\n"); } #endif } void SendMessageToClean (int mess, int p1, int p2, int p3, int p4, int p5, int p6) { gCci.mess = mess; gCci.p1 = p1; gCci.p2 = p2; gCci.p3 = p3; gCci.p4 = p4; gCci.p5 = p5; gCci.p6 = p6; KickCleanThread (&gCci); while (!IsReturnCci (&gCci)) { HandleCleanRequest (&gCci); } } extern double c_div_real (double n, double d); extern int c_ftoi (double d); DWORD OsThreadFunction (DWORD param) { WNDCLASS wclass; int width, height; HMENU mainSystemMenu; /* register custom control class */ wclass.style = CS_NOCLOSE | CS_PARENTDC; wclass.lpfnWndProc = (WNDPROC) CustomControlProcedure; wclass.cbClsExtra = 0; wclass.cbWndExtra = 0; wclass.hInstance = ghInst; wclass.hIcon = NULL; wclass.hCursor = LoadCursor (ghInst, IDC_ARROW); wclass.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1); wclass.lpszMenuName = NULL; wclass.lpszClassName = CustomControlClassName; RegisterClass (&wclass); /* register clean compound control class */ wclass.style = CS_PARENTDC; wclass.lpfnWndProc = (WNDPROC) CompoundControlProcedure; wclass.cbClsExtra = 0; wclass.cbWndExtra = 0; wclass.hInstance = ghInst; wclass.hIcon = NULL; wclass.hCursor = LoadCursor (ghInst, IDC_ARROW); wclass.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1);//(NULL_BRUSH); wclass.lpszMenuName = NULL; wclass.lpszClassName = CompoundControlClassName; RegisterClass (&wclass); /* register main window class */ wclass.style = CS_NOCLOSE; wclass.lpfnWndProc = (WNDPROC) MainWindowProcedure; wclass.cbClsExtra = 0; wclass.cbWndExtra = 0; wclass.hInstance = ghInst; wclass.hIcon = LoadIcon (ghInst, IDI_APPLICATION); wclass.hCursor = LoadCursor (ghInst, IDC_ARROW); wclass.hbrBackground = NULL; wclass.lpszMenuName = NULL; wclass.lpszClassName = MainWindowClassName; RegisterClass (&wclass); /* register clean SDI window class */ wclass.style = 0; wclass.lpfnWndProc = (WNDPROC) SDIWindowProcedure; wclass.cbClsExtra = 0; wclass.cbWndExtra = sizeof (HANDLE); // Allocate local memory for LocalWindowData wclass.hInstance = ghInst; wclass.hIcon = NULL; wclass.hCursor = NULL; // Must be NULL, otherwise SetCursor won't have effect. wclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH); wclass.lpszMenuName = NULL; wclass.lpszClassName = SDIWindowClassName; RegisterClass (&wclass); /* register clean SDI frame class */ wclass.style = 0; wclass.lpfnWndProc = (WNDPROC) SDIFrameProcedure; wclass.cbClsExtra = 0; wclass.cbWndExtra = sizeof (HANDLE); // Allocate local memory for shortcut table pointer wclass.hInstance = ghInst; wclass.hIcon = LoadIcon (ghInst, IDI_APPLICATION); wclass.hCursor = LoadCursor (ghInst, IDC_ARROW); wclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH); wclass.lpszMenuName = NULL; wclass.lpszClassName = SDIFrameClassName; RegisterClass (&wclass); /* register clean MDI window class */ wclass.style = 0; wclass.lpfnWndProc = (WNDPROC) MDIWindowProcedure; wclass.cbClsExtra = 0; wclass.cbWndExtra = sizeof (HANDLE); // Allocate local memory for LocalWindowData wclass.hInstance = ghInst; wclass.hIcon = LoadIcon (ghInst, IDI_APPLICATION); wclass.hCursor = NULL; // Must be NULL, otherwise SetCursor won't have effect. wclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH); wclass.lpszMenuName = NULL; wclass.lpszClassName = MDIWindowClassName; RegisterClass (&wclass); /* register clean MDI frame class */ wclass.style = 0; wclass.lpfnWndProc = (WNDPROC) MDIFrameProcedure; wclass.cbClsExtra = 0; wclass.cbWndExtra = sizeof (HANDLE); // Allocate local memory for shortcut table pointer wclass.hInstance = ghInst; wclass.hIcon = LoadIcon (ghInst, IDI_APPLICATION); wclass.hCursor = LoadCursor (ghInst, IDC_ARROW); wclass.hbrBackground = (HBRUSH) (COLOR_APPWORKSPACE+1); // For best results (Petzold) wclass.lpszMenuName = NULL; wclass.lpszClassName = MDIFrameClassName; RegisterClass (&wclass); /* Mike... */ RegisterGameWindowClass (); /* ...Mike */ /* initialise the common control library. */ InitCommonControls (); GetAppFileName (); width = GetSystemMetrics (SM_CXMAXIMIZED) - 2 * GetSystemMetrics (SM_CXSIZEFRAME); height = 2 * GetSystemMetrics (SM_CYSIZEFRAME) + GetSystemMetrics (SM_CYCAPTION) + GetSystemMetrics (SM_CYMENU); ghMainWindow = CreateWindow (MainWindowClassName, /* Class name */ (LPCTSTR) gAppName, /* Window title */ WS_OVERLAPPEDWINDOW, /* style flags */ 0, -5 - height, /* x, y */ width, height, /* width, height */ NULL, /* Parent window */ NULL, /* menu handle */ (HANDLE) ghInst, /* Instance that owns the window */ 0); /* Don't show the main window. This will result in one button less in the taskbar. ShowWindow (ghMainWindow, SW_SHOWNORMAL); */ /* Before creating Clean controls, the tooltip control is created as the topmost child of this window. */ ghwndTT = CreateWindowEx ( WS_EX_TOPMOST, // Apply the topmost style for this window TOOLTIPS_CLASS, // Class name NULL, // Title (NULL) WS_POPUP | TTS_ALWAYSTIP, // Style *must* be WS_POPUP CW_USEDEFAULT, // Default position (x,y) CW_USEDEFAULT, CW_USEDEFAULT, // Default size (w,h) CW_USEDEFAULT, ghMainWindow, // Parent is the ghMainWindow (HMENU) NULL, // No menu (HANDLE) ghInst, // The instance NULL // No window creation data ); mainSystemMenu = GetSystemMenu (ghMainWindow,FALSE); RemoveMenu (mainSystemMenu, SC_RESTORE, MF_BYCOMMAND); RemoveMenu (mainSystemMenu, SC_MOVE, MF_BYCOMMAND); RemoveMenu (mainSystemMenu, SC_SIZE, MF_BYCOMMAND); RemoveMenu (mainSystemMenu, SC_MINIMIZE, MF_BYCOMMAND); RemoveMenu (mainSystemMenu, SC_MAXIMIZE, MF_BYCOMMAND); DrawMenuBar (ghMainWindow); KickCleanThread (MakeReturn0Cci (&gCci)); while (1) { HandleCleanRequest (&gCci); } MakeReturn0Cci (&gCci); SetEvent (gOS_DONE); return 0; } CrossCallInfo * MakeReturn0Cci (CrossCallInfo * pcci) { pcci->mess = CcRETURN0; return pcci; } CrossCallInfo * MakeReturn1Cci (CrossCallInfo * pcci, int v) { pcci->mess = CcRETURN1; pcci->p1 = v; return pcci; } CrossCallInfo * MakeReturn2Cci (CrossCallInfo * pcci, int v1, int v2) { pcci->mess = CcRETURN2; pcci->p1 = v1; pcci->p2 = v2; return pcci; } CrossCallInfo * MakeReturn3Cci (CrossCallInfo * pcci, int v1, int v2, int v3) { pcci->mess = CcRETURN3; pcci->p1 = v1; pcci->p2 = v2; pcci->p3 = v3; return pcci; } CrossCallInfo * MakeReturn4Cci (CrossCallInfo * pcci, int v1, int v2, int v3, int v4) { pcci->mess = CcRETURN4; pcci->p1 = v1; pcci->p2 = v2; pcci->p3 = v3; pcci->p4 = v4; return pcci; } CrossCallInfo * MakeReturn5Cci (CrossCallInfo * pcci, int v1, int v2, int v3, int v4, int v5) { pcci->mess = CcRETURN5; pcci->p1 = v1; pcci->p2 = v2; pcci->p3 = v3; pcci->p4 = v4; pcci->p5 = v5; return pcci; } CrossCallInfo * MakeReturn6Cci (CrossCallInfo * pcci, int v1, int v2, int v3, int v4, int v5, int v6) { pcci->mess = CcRETURN6; pcci->p1 = v1; pcci->p2 = v2; pcci->p3 = v3; pcci->p4 = v4; pcci->p5 = v5; pcci->p6 = v6; return pcci; } BOOL IsReturnCci (CrossCallInfo * pcci) { if (pcci->mess >= CcRETURNmin && pcci->mess <= CcRETURNmax) return TRUE; return FALSE; } extern EXPORT_TO_CLEAN void WinScreenYSize (OS ios, int *py, OS * oos) { *py = GetSystemMetrics (SM_CYSCREEN); *oos = ios; } extern EXPORT_TO_CLEAN void WinScreenXSize (OS ios, int *px, OS * oos) { *px = GetSystemMetrics (SM_CXSCREEN); *oos = ios; } extern EXPORT_TO_CLEAN void WinMinimumWinSize (int *mx, int *my) { *mx = 48; *my = 0; } /* WinScrollbarSize determines system metrics of width and height of scrollbars. */ extern EXPORT_TO_CLEAN void WinScrollbarSize (OS ios, int *width, int *height, OS * oos) { *width = GetSystemMetrics (SM_CXVSCROLL); *height = GetSystemMetrics (SM_CYHSCROLL); *oos = ios; } extern EXPORT_TO_CLEAN void WinMaxFixedWindowSize (int *mx, int *my) { *mx = GetSystemMetrics (SM_CXMAXIMIZED) - /* MAXIMIZED size */ 4 * GetSystemMetrics (SM_CXFIXEDFRAME); /* window borders */ *my = GetSystemMetrics (SM_CYMAXIMIZED) - /* MAXIMIZED size */ 4 * GetSystemMetrics (SM_CYFIXEDFRAME) - /* window borders */ GetSystemMetrics (SM_CYCAPTION); /* title bar */ } extern EXPORT_TO_CLEAN void WinMaxScrollWindowSize (int *mx, int *my) { *mx = GetSystemMetrics (SM_CXMAXIMIZED) - // MAXIMIZED size 4 * GetSystemMetrics (SM_CXSIZEFRAME) - // window borders 4; // 2 * client edge *my = GetSystemMetrics (SM_CYMAXIMIZED) - // MAXIMIZED size 4 * GetSystemMetrics (SM_CYSIZEFRAME) - // window borders 4 - // 2 * clientedge GetSystemMetrics (SM_CYCAPTION); // title bar } extern EXPORT_TO_CLEAN CLEAN_STRING WinGetModulePath (void) { char path[MAX_PATH + 1]; GetModuleFileName (NULL, path, MAX_PATH); return cleanstring (path); } extern EXPORT_TO_CLEAN void WinFileModifiedDate (CLEAN_STRING name, Bool * exists, int *yy, int *mm, int *dd, int *h, int *m, int *s) { char *file_name; HANDLE handle; WIN32_FIND_DATA find_data; file_name = cstring (name); handle = FindFirstFile (file_name, &find_data); if (handle != INVALID_HANDLE_VALUE) { SYSTEMTIME system_time; FindClose (handle); if (FileTimeToSystemTime (&find_data.ftLastWriteTime, &system_time)) { *exists = TRUE; *yy = system_time.wYear; *mm = system_time.wMonth; *dd = system_time.wDay; *h = system_time.wHour; *m = system_time.wMinute; *s = system_time.wSecond; return; } } *exists = FALSE; *yy = 0; *mm = 0; *dd = 0; *h = 0; *m = 0; *s = 0; } extern EXPORT_TO_CLEAN Bool WinFileExists (CLEAN_STRING name) { char *file_name; HANDLE handle; WIN32_FIND_DATA find_data; file_name = cstring (name); handle = FindFirstFile (file_name, &find_data); if (handle != INVALID_HANDLE_VALUE) { FindClose (handle); return TRUE; } else return FALSE; } extern EXPORT_TO_CLEAN void WinCallProcess (PSTR commandline, PSTR env, PSTR dir, PSTR in, PSTR out, PSTR err, OS ios, Bool * success, int *exitcode, OS * oos) { SECURITY_ATTRIBUTES sa; STARTUPINFO si; PROCESS_INFORMATION pi; BOOL fsuccess; char *ep; HANDLE saveStdin, infile; HANDLE saveStdout, outfile; HANDLE saveStderr, errfile; rprintf ("WCP: starting...\n"); rprintf ("success = %d, value = %d\n", success, *success); *success = FALSE; rprintf ("exitcode = %d; value = %d\n", exitcode, *exitcode); *exitcode = -1; rprintf ("oos = %d; value = %d\n", oos, *oos); *oos = ios; rprintf ("commandline = %d; value = %s\n", commandline, commandline); if (commandline != NULL) rprintf ("WCP: commandline = \"%s\"\n", commandline); else rprintf ("WCP: commandline empty\n"); if (env != NULL) { ep = env; while (rstrlen (ep) != 0) { rprintf ("WCP: env = \"%s\"\n", ep); ep += rstrlen (ep) + 1; } } else rprintf ("WCP: env empty\n"); if (dir != NULL) rprintf ("WCP: dir = \"%s\"\n", dir); else rprintf ("WCP: dir empty\n"); if (in != NULL) rprintf ("WCP: in = \"%s\"\n", in); else rprintf ("WCP: in empty\n"); if (out != NULL) rprintf ("WCP: out = \"%s\"\n", out); else rprintf ("WCP: out empty\n"); if (err != NULL) rprintf ("WCP: err = \"%s\"\n", err); else rprintf ("WCP: err empty\n"); sa.nLength = sizeof (SECURITY_ATTRIBUTES); sa.bInheritHandle = TRUE; sa.lpSecurityDescriptor = NULL; if (in != NULL) { infile = CreateFile (in, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if (infile == INVALID_HANDLE_VALUE) { rprintf ("infile creation failed\n"); return; } saveStdin = GetStdHandle (STD_INPUT_HANDLE); if (!SetStdHandle (STD_INPUT_HANDLE, infile)) { rprintf ("could not redirect input\n"); return; } rprintf ("redirection of input ok\n"); } else { rprintf ("in == NULL\n"); infile = NULL; } if (out != NULL) { outfile = CreateFile (out, GENERIC_WRITE, 0, &sa, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); if (outfile == INVALID_HANDLE_VALUE) { rprintf ("outfile creation failed\n"); return; } saveStdout = GetStdHandle (STD_OUTPUT_HANDLE); if (!SetStdHandle (STD_OUTPUT_HANDLE, outfile)) { rprintf ("could not redirect output\n"); return; } rprintf ("redirection of output ok\n"); } else { rprintf ("out == NULL\n"); outfile = NULL; } if (err != NULL) { errfile = CreateFile (err, GENERIC_WRITE, 0, &sa, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); if (errfile == INVALID_HANDLE_VALUE) { rprintf ("errfile creation failed\n"); return; } saveStderr = GetStdHandle (STD_ERROR_HANDLE); if (!SetStdHandle (STD_ERROR_HANDLE, errfile)) { rprintf ("could not redirect errput\n"); return; } rprintf ("redirection of errors ok\n"); } else { rprintf ("err == NULL\n"); errfile = NULL; } si.cb = sizeof (STARTUPINFO); si.lpReserved = NULL; si.lpReserved2 = NULL; si.cbReserved2 = 0; si.lpDesktop = NULL; si.lpTitle = NULL; si.dwFlags = 0; fsuccess = CreateProcess (NULL, /* pointer to name of executable module */ commandline, /* pointer to command line string */ NULL, /* pointer to process security attributes */ NULL, /* pointer to thread security attributes */ TRUE, /* handle inheritance flag */ DETACHED_PROCESS, /* creation flags */ env, /* pointer to new environment block */ dir, /* pointer to current directory name */ &si, /* pointer to STARTUPINFO */ &pi /* pointer to PROCESS_INFORMATION */ ); if (fsuccess) { rprintf ("WCP: success\n"); WaitForSingleObject (pi.hProcess, INFINITE); GetExitCodeProcess (pi.hProcess, (unsigned long *) exitcode); rprintf ("WCP: exitcode = %d\n", *exitcode); *success = TRUE; } else { rprintf ("WCP: failure %d\n", (int) GetLastError ()); *success = FALSE; *exitcode = -1; } if (infile != NULL) { if (SetStdHandle (STD_INPUT_HANDLE, saveStdin)) rprintf ("resetting stdin ok\n"); else rprintf ("resetting stdin failed\n"); if (CloseHandle (infile)) rprintf ("closing infile ok\n"); else rprintf ("closing infile failed\n"); } else rprintf ("no need to close and reset input\n"); if (outfile != NULL) { if (SetStdHandle (STD_OUTPUT_HANDLE, saveStdout)) rprintf ("resetting stdout ok\n"); else rprintf ("resetting stdout failed\n"); if (CloseHandle (outfile)) rprintf ("closing outfile ok\n"); else rprintf ("closing outfile failed\n"); } else rprintf ("no need to close and reset output\n"); if (errfile != NULL) { if (SetStdHandle (STD_ERROR_HANDLE, saveStderr)) rprintf ("resetting stderr ok\n"); else rprintf ("resetting stderr failed\n"); if (CloseHandle (errfile)) rprintf ("closing errfile ok\n"); else rprintf ("closing errfile failed\n"); } else rprintf ("no need to close and reset errput\n"); rprintf ("WCP: returning\n"); /* *oos = ios; */ } extern EXPORT_TO_CLEAN void WinLaunchApp (CLEAN_STRING commandline, BOOL console, OS ios, Bool * success, OS * oos) { STARTUPINFO si; PROCESS_INFORMATION pi; BOOL fsuccess; char path[_MAX_PATH]; char *cl, *thepath; int i; DWORD error; rprintf ("WLA: starting...\n"); *success = FALSE; *oos = ios; si.lpTitle = NULL; rprintf ("WLA: step 2.\n"); cl = cstring (commandline); lstrcpy (path, cl); for (i = lstrlen (path); path[i] != '\\' && i >= 0; i--) path[i] = 0; if (i == 0) thepath = NULL; else { /* path[i] = '\"'; */ thepath = path + 1; } rprintf ("WLA: step 2a: directory = <%s>\n", thepath); rprintf ("WLA: step 3: filling in si.\n"); si.cb = sizeof (STARTUPINFO); si.lpReserved = NULL; si.lpReserved2 = NULL; si.cbReserved2 = 0; si.lpDesktop = NULL; si.dwFlags = 0; si.lpTitle = NULL; rprintf ("WLA: step 4: calling process \"%s\".\n", cl); fsuccess = CreateProcess (NULL, /* pointer to name of executable module */ cl, /* pointer to command line string */ NULL, /* pointer to process security attributes */ NULL, /* pointer to thread security attributes */ TRUE, /* handle inheritance flag */ 0, /* creation flags */ NULL, /* pointer to new environment block */ thepath, /* pointer to current directory name */ &si, /* pointer to STARTUPINFO */ &pi /* pointer to PROCESS_INFORMATION */ ); error = GetLastError (); if (fsuccess) { rprintf ("WLA: success\n"); } else { rprintf ("WLA: failure %d\n", error); } rprintf ("WLA: step 5: returning\n"); *success = fsuccess; *oos = ios; rprintf ("WLA: done...\n"); } /* New version of WinLaunchApp. In addition to the commandline, it gets a directory argument. */ extern EXPORT_TO_CLEAN void WinLaunchApp2 (CLEAN_STRING commandline, CLEAN_STRING pathname, BOOL console, OS ios, Bool * success, OS * oos) { STARTUPINFO si; PROCESS_INFORMATION pi; BOOL fsuccess; char commandline2[_MAX_PATH]; char *cl, *thepath; DWORD error; rprintf ("WLA2: starting...\n"); *success = FALSE; *oos = ios; si.lpTitle = NULL; rprintf ("WLA2: step 2.\n"); cl = cstring (commandline); lstrcpy (commandline2, cl); thepath = cstring (pathname); rprintf ("WLA2: step 3: filling in si.\n"); si.cb = sizeof (STARTUPINFO); si.lpReserved = NULL; si.lpReserved2 = NULL; si.cbReserved2 = 0; si.lpDesktop = NULL; si.dwFlags = 0; si.lpTitle = NULL; rprintf ("WLA2: step 4: calling process \"%s\".\n", cl); fsuccess = CreateProcess (NULL, /* pointer to name of executable module */ commandline2,/* pointer to command line string */ NULL, /* pointer to process security attributes */ NULL, /* pointer to thread security attributes */ TRUE, /* handle inheritance flag */ 0, /* creation flags */ NULL, /* pointer to new environment block */ thepath, /* pointer to current directory name */ &si, /* pointer to STARTUPINFO */ &pi /* pointer to PROCESS_INFORMATION */ ); error = GetLastError (); if (fsuccess) { rprintf ("WLA2: success\n"); } else { rprintf ("WLA2: failure %d\n", error); } rprintf ("WLA2: step 5: returning\n"); *success = fsuccess; *oos = ios; rprintf ("WLA2: done...\n"); } /* End of addition. */ extern EXPORT_TO_CLEAN void WinGetTickCount (OS ios, int *tickCount, OS * oos) { *tickCount = GetTickCount (); *oos = ios; } char * toCstring (CLEAN_STRING s) { char *cstr = (char *) NULL; cstr = (char *) rmalloc ((s->length) + 1); rsncopy (cstr, s->characters, s->length); cstr[s->length] = 0; return cstr; } extern EXPORT_TO_CLEAN void WinPlaySound (CLEAN_STRING clfilename, OS ios, Bool * ook, OS * oos) { char * cfilename; cfilename = toCstring (clfilename); if (PlaySound (cfilename, NULL, SND_FILENAME | SND_SYNC)) { *ook = TRUE; } else { *ook = FALSE; } rfree (cfilename); *oos = ios; }