summaryrefslogtreecommitdiffstats
path: root/win/tkWinMenu.c
diff options
context:
space:
mode:
Diffstat (limited to 'win/tkWinMenu.c')
-rw-r--r--win/tkWinMenu.c813
1 files changed, 478 insertions, 335 deletions
diff --git a/win/tkWinMenu.c b/win/tkWinMenu.c
index 734591d..b39d584 100644
--- a/win/tkWinMenu.c
+++ b/win/tkWinMenu.c
@@ -3,18 +3,20 @@
*
* This module implements the Windows platform-specific features of menus.
*
- * Copyright (c) 1996-1997 by Sun Microsystems, Inc.
+ * Copyright (c) 1996-1998 by Sun Microsystems, Inc.
+ * Copyright (c) 1998-1999 by Scriptics Corporation.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkWinMenu.c,v 1.4 1999/02/04 21:44:18 stanton Exp $
+ * RCS: @(#) $Id: tkWinMenu.c,v 1.5 1999/04/16 01:51:52 stanton Exp $
*/
#define OEMRESOURCE
-#include <string.h>
-#include "tkMenu.h"
#include "tkWinInt.h"
+#include "tkMenu.h"
+
+#include <string.h>
/*
* The class of the window for popup menus.
@@ -50,34 +52,40 @@ static int indicatorDimensions[2];
/* The dimensions of the indicator space
* in a menu entry. Calculated at init
* time to save time. */
-static Tcl_HashTable commandTable;
+
+typedef struct ThreadSpecificData {
+ Tcl_HashTable commandTable;
/* A map of command ids to menu entries */
-static int inPostMenu; /* We cannot be re-entrant like X Windows. */
-static WORD lastCommandID; /* The last command ID we allocated. */
-static HWND menuHWND; /* A window to service popup-menu messages
+ int inPostMenu; /* We cannot be re-entrant like X Windows. */
+ WORD lastCommandID; /* The last command ID we allocated. */
+ HWND menuHWND; /* A window to service popup-menu messages
* in. */
-static int oldServiceMode; /* Used while processing a menu; we need
+ int oldServiceMode; /* Used while processing a menu; we need
* to set the event mode specially when we
* enter the menu processing modal loop
* and reset it when menus go away. */
-static TkMenu *modalMenuPtr; /* The menu we are processing inside the modal
+ TkMenu *modalMenuPtr; /* The menu we are processing inside the modal
* loop. We need this to reset all of the
* active items when menus go away since
* Windows does not see fit to give this
* to us when it sends its WM_MENUSELECT. */
+ Tcl_HashTable winMenuTable;
+ /* Need this to map HMENUs back to menuPtrs */
+} ThreadSpecificData;
+static Tcl_ThreadDataKey dataKey;
+
static OSVERSIONINFO versionInfo;
/* So we don't have to keep doing this */
-static Tcl_HashTable winMenuTable;
- /* Need this to map HMENUs back to menuPtrs */
/*
* The following are default menu value strings.
*/
-static char borderString[5]; /* The string indicating how big the border is */
+static int defaultBorderWidth; /* The windows default border width. */
static Tcl_DString menuFontDString;
/* A buffer to store the default menu font
* string. */
+TCL_DECLARE_MUTEX(winMenuMutex)
/*
* Forward declarations for procedures defined later in this file:
@@ -122,7 +130,7 @@ static void DrawWindowsSystemBitmap _ANSI_ARGS_((
GC gc, CONST RECT *rectPtr, int bitmapID,
int alignFlags));
static void FreeID _ANSI_ARGS_((int commandID));
-static char * GetEntryText _ANSI_ARGS_((TkMenuEntry *mePtr));
+static TCHAR * GetEntryText _ANSI_ARGS_((TkMenuEntry *mePtr));
static void GetMenuAccelGeometry _ANSI_ARGS_((TkMenu *menuPtr,
TkMenuEntry *mePtr, Tk_Font tkfont,
CONST Tk_FontMetrics *fmPtr, int *widthPtr,
@@ -154,6 +162,7 @@ static void ReconfigureWindowsMenu _ANSI_ARGS_((
ClientData clientData));
static void RecursivelyClearActiveMenu _ANSI_ARGS_((
TkMenu *menuPtr));
+static void SetDefaults _ANSI_ARGS_((int firstTime));
static LRESULT CALLBACK TkWinMenuProc _ANSI_ARGS_((HWND hwnd,
UINT message, WPARAM wParam,
LPARAM lParam));
@@ -189,16 +198,18 @@ GetNewID(mePtr, menuIDPtr)
int newEntry;
Tcl_HashEntry *commandEntryPtr;
WORD returnID;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
- WORD curID = lastCommandID + 1;
+ WORD curID = tsdPtr->lastCommandID + 1;
/*
* The following code relies on WORD wrapping when the highest value is
* incremented.
*/
- while (curID != lastCommandID) {
- commandEntryPtr = Tcl_CreateHashEntry(&commandTable,
+ while (curID != tsdPtr->lastCommandID) {
+ commandEntryPtr = Tcl_CreateHashEntry(&tsdPtr->commandTable,
(char *) curID, &newEntry);
if (newEntry == 1) {
found = 1;
@@ -211,7 +222,7 @@ GetNewID(mePtr, menuIDPtr)
if (found) {
Tcl_SetHashValue(commandEntryPtr, (char *) mePtr);
*menuIDPtr = (int) returnID;
- lastCommandID = returnID;
+ tsdPtr->lastCommandID = returnID;
return TCL_OK;
} else {
return TCL_ERROR;
@@ -238,7 +249,10 @@ static void
FreeID(commandID)
int commandID;
{
- Tcl_HashEntry *entryPtr = Tcl_FindHashEntry(&commandTable,
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ Tcl_HashEntry *entryPtr = Tcl_FindHashEntry(&tsdPtr->commandTable,
(char *) commandID);
if (entryPtr != NULL) {
@@ -272,6 +286,8 @@ TkpNewMenu(menuPtr)
HMENU winMenuHdl;
Tcl_HashEntry *hashEntryPtr;
int newEntry;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
winMenuHdl = CreatePopupMenu();
@@ -286,7 +302,7 @@ TkpNewMenu(menuPtr)
* back when dispatch messages.
*/
- hashEntryPtr = Tcl_CreateHashEntry(&winMenuTable, (char *) winMenuHdl,
+ hashEntryPtr = Tcl_CreateHashEntry(&tsdPtr->winMenuTable, (char *) winMenuHdl,
&newEntry);
Tcl_SetHashValue(hashEntryPtr, (char *) menuPtr);
@@ -315,6 +331,9 @@ TkpDestroyMenu(menuPtr)
TkMenu *menuPtr; /* The common menu structure */
{
HMENU winMenuHdl = (HMENU) menuPtr->platformData;
+ char *searchName;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
if (menuPtr->menuFlags & MENU_RECONFIGURE_PENDING) {
Tcl_CancelIdleCall(ReconfigureWindowsMenu, (ClientData) menuPtr);
@@ -339,7 +358,8 @@ TkpDestroyMenu(menuPtr)
for (searchEntryPtr = menuPtr->menuRefPtr->parentEntryPtr;
searchEntryPtr != NULL;
searchEntryPtr = searchEntryPtr->nextCascadePtr) {
- if (strcmp(searchEntryPtr->name, menuName) == 0) {
+ searchName = Tcl_GetStringFromObj(searchEntryPtr->namePtr, NULL);
+ if (strcmp(searchName, menuName) == 0) {
Tk_Window parentTopLevelPtr = searchEntryPtr
->menuPtr->parentTopLevelPtr;
@@ -357,7 +377,8 @@ TkpDestroyMenu(menuPtr)
* Remove the menu from the menu hash table, then destroy the handle.
*/
- hashEntryPtr = Tcl_FindHashEntry(&winMenuTable, (char *) winMenuHdl);
+ hashEntryPtr = Tcl_FindHashEntry(&tsdPtr->winMenuTable,
+ (char *) winMenuHdl);
if (hashEntryPtr != NULL) {
Tcl_DeleteHashEntry(hashEntryPtr);
}
@@ -365,8 +386,8 @@ TkpDestroyMenu(menuPtr)
}
menuPtr->platformData = NULL;
- if (menuPtr == modalMenuPtr) {
- modalMenuPtr = NULL;
+ if (menuPtr == tsdPtr->modalMenuPtr) {
+ tsdPtr->modalMenuPtr = NULL;
}
}
@@ -431,18 +452,23 @@ GetEntryText(mePtr)
if (mePtr->type == TEAROFF_ENTRY) {
itemText = ckalloc(sizeof("(Tear-off)"));
strcpy(itemText, "(Tear-off)");
- } else if (mePtr->imageString != NULL) {
+ } else if (mePtr->imagePtr != NULL) {
itemText = ckalloc(sizeof("(Image)"));
strcpy(itemText, "(Image)");
- } else if (mePtr->bitmap != None) {
+ } else if (mePtr->bitmapPtr != NULL) {
itemText = ckalloc(sizeof("(Pixmap)"));
strcpy(itemText, "(Pixmap)");
- } else if (mePtr->label == NULL || mePtr->labelLength == 0) {
+ } else if (mePtr->labelPtr == NULL || mePtr->labelLength == 0) {
itemText = ckalloc(sizeof("( )"));
strcpy(itemText, "( )");
} else {
- int size = mePtr->labelLength + 1;
- int i, j;
+ int i;
+ char *label = (mePtr->labelPtr == NULL) ? ""
+ : Tcl_GetStringFromObj(mePtr->labelPtr, NULL);
+ char *accel = (mePtr->accelPtr == NULL) ? ""
+ : Tcl_GetStringFromObj(mePtr->accelPtr, NULL);
+ char *p, *next;
+ Tcl_DString itemString;
/*
* We have to construct the string with an ampersand
@@ -451,57 +477,32 @@ GetEntryText(mePtr)
* ampersands in the string.
*/
- for (i = 0; i < mePtr->labelLength; i++) {
- if (mePtr->label[i] == '&') {
- size++;
- }
- }
+ Tcl_DStringInit(&itemString);
- if (mePtr->underline >= 0) {
- size++;
- if (mePtr->label[mePtr->underline] == '&') {
- size++;
+ for (p = label, i = 0; *p != '\0'; i++, p = next) {
+ if (i == mePtr->underline) {
+ Tcl_DStringAppend(&itemString, "&", 1);
}
- }
-
- if (mePtr->accelLength > 0) {
- size += mePtr->accelLength + 1;
- }
-
- for (i = 0; i < mePtr->accelLength; i++) {
- if (mePtr->accel[i] == '&') {
- size++;
+ if (*p == '&') {
+ Tcl_DStringAppend(&itemString, "&", 1);
}
+ next = Tcl_UtfNext(p);
+ Tcl_DStringAppend(&itemString, p, next - p);
}
-
- itemText = ckalloc(size);
-
- if (mePtr->labelLength == 0) {
- itemText[0] = 0;
- } else {
- for (i = 0, j = 0; i < mePtr->labelLength; i++, j++) {
- if (mePtr->label[i] == '&') {
- itemText[j++] = '&';
- }
- if (i == mePtr->underline) {
- itemText[j++] = '&';
+ if (mePtr->accelLength > 0) {
+ Tcl_DStringAppend(&itemString, "\t", 1);
+ for (p = accel, i = 0; *p != '\0'; i++, p = next) {
+ if (*p == '&') {
+ Tcl_DStringAppend(&itemString, "&", 1);
}
- itemText[j] = mePtr->label[i];
+ next = Tcl_UtfNext(p);
+ Tcl_DStringAppend(&itemString, p, next - p);
}
- itemText[j] = '\0';
- }
+ }
- if (mePtr->accelLength > 0) {
- strcat(itemText, "\t");
- for (i = 0, j = strlen(itemText); i < mePtr->accelLength;
- i++, j++) {
- if (mePtr->accel[i] == '&') {
- itemText[j++] = '&';
- }
- itemText[j] = mePtr->accel[i];
- }
- itemText[j] = '\0';
- }
+ itemText = ckalloc(Tcl_DStringLength(&itemString) + 1);
+ strcpy(itemText, Tcl_DStringValue(&itemString));
+ Tcl_DStringFree(&itemString);
}
return itemText;
}
@@ -530,13 +531,14 @@ ReconfigureWindowsMenu(
TkMenu *menuPtr = (TkMenu *) clientData;
TkMenuEntry *mePtr;
HMENU winMenuHdl = (HMENU) menuPtr->platformData;
- char *itemText = NULL;
- LPCTSTR lpNewItem;
+ TCHAR *itemText = NULL;
+ const TCHAR *lpNewItem;
UINT flags;
UINT itemID;
int i, count, systemMenu = 0, base;
int width, height;
-
+ Tcl_DString translatedText;
+
if (NULL == winMenuHdl) {
return;
}
@@ -565,6 +567,7 @@ ReconfigureWindowsMenu(
lpNewItem = NULL;
flags = MF_BYPOSITION;
itemID = 0;
+ Tcl_DStringInit(&translatedText);
if ((menuPtr->menuType == MENUBAR) && (mePtr->type == TEAROFF_ENTRY)) {
continue;
@@ -576,7 +579,8 @@ ReconfigureWindowsMenu(
itemText = GetEntryText(mePtr);
if ((menuPtr->menuType == MENUBAR)
|| (menuPtr->menuFlags & MENU_SYSTEM_MENU)) {
- lpNewItem = itemText;
+ Tcl_UtfToExternalDString(NULL, itemText, -1, &translatedText);
+ lpNewItem = Tcl_DStringValue(&translatedText);
} else {
lpNewItem = (LPCTSTR) mePtr;
flags |= MF_OWNERDRAW;
@@ -586,7 +590,7 @@ ReconfigureWindowsMenu(
* Set enabling and disabling correctly.
*/
- if (mePtr->state == tkDisabledUid) {
+ if (mePtr->state == ENTRY_DISABLED) {
flags |= MF_DISABLED;
}
@@ -617,18 +621,21 @@ ReconfigureWindowsMenu(
if ((menuPtr->menuType == MENUBAR)
&& !(mePtr->childMenuRefPtr->menuPtr->menuFlags
& MENU_SYSTEM_MENU)) {
+ Tcl_DString ds;
TkMenuReferences *menuRefPtr;
TkMenu *systemMenuPtr = mePtr->childMenuRefPtr
->menuPtr;
- char *systemMenuName = ckalloc(strlen(
- Tk_PathName(menuPtr->masterMenuPtr->tkwin))
- + strlen(".system") + 1);
- strcpy(systemMenuName,
- Tk_PathName(menuPtr->masterMenuPtr->tkwin));
- strcat(systemMenuName, ".system");
+ Tcl_DStringInit(&ds);
+ Tcl_DStringAppend(&ds,
+ Tk_PathName(menuPtr->masterMenuPtr->tkwin), -1);
+ Tcl_DStringAppend(&ds, ".system", 7);
+
menuRefPtr = TkFindMenuReferences(menuPtr->interp,
- systemMenuName);
+ Tcl_DStringValue(&ds));
+
+ Tcl_DStringFree(&ds);
+
if ((menuRefPtr != NULL)
&& (menuRefPtr->menuPtr != NULL)
&& (menuPtr->parentTopLevelPtr != NULL)
@@ -653,7 +660,6 @@ ReconfigureWindowsMenu(
}
}
}
- ckfree(systemMenuName);
}
if (mePtr->childMenuRefPtr->menuPtr->menuFlags
& MENU_SYSTEM_MENU) {
@@ -664,6 +670,7 @@ ReconfigureWindowsMenu(
if (!systemMenu) {
InsertMenu(winMenuHdl, 0xFFFFFFFF, flags, itemID, lpNewItem);
}
+ Tcl_DStringFree(&translatedText);
if (itemText != NULL) {
ckfree(itemText);
itemText = NULL;
@@ -709,8 +716,10 @@ TkpPostMenu(interp, menuPtr, x, y)
POINT point;
Tk_Window parentWindow = Tk_Parent(menuPtr->tkwin);
int oldServiceMode = Tcl_GetServiceMode();
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
- inPostMenu++;
+ tsdPtr->inPostMenu++;
if (menuPtr->menuFlags & MENU_RECONFIGURE_PENDING) {
Tcl_CancelIdleCall(ReconfigureWindowsMenu, (ClientData) menuPtr);
@@ -719,7 +728,7 @@ TkpPostMenu(interp, menuPtr, x, y)
result = TkPreprocessMenu(menuPtr);
if (result != TCL_OK) {
- inPostMenu--;
+ tsdPtr->inPostMenu--;
return result;
}
@@ -729,7 +738,7 @@ TkpPostMenu(interp, menuPtr, x, y)
*/
if (menuPtr->tkwin == NULL) {
- inPostMenu--;
+ tsdPtr->inPostMenu--;
return TCL_OK;
}
@@ -770,14 +779,14 @@ TkpPostMenu(interp, menuPtr, x, y)
}
TrackPopupMenu(winMenuHdl, flags, x, y, 0,
- menuHWND, &noGoawayRect);
+ tsdPtr->menuHWND, &noGoawayRect);
Tcl_SetServiceMode(oldServiceMode);
GetCursorPos(&point);
Tk_PointerEvent(NULL, point.x, point.y);
- if (inPostMenu) {
- inPostMenu = 0;
+ if (tsdPtr->inPostMenu) {
+ tsdPtr->inPostMenu = 0;
}
return TCL_OK;
}
@@ -886,24 +895,27 @@ TkWinHandleMenuEvent(phwnd, pMessage, pwParam, plParam, plResult)
int returnResult = 0;
TkMenu *menuPtr;
TkMenuEntry *mePtr;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
switch (*pMessage) {
case WM_INITMENU:
TkMenuInit();
- hashEntryPtr = Tcl_FindHashEntry(&winMenuTable, (char *) *pwParam);
+ hashEntryPtr = Tcl_FindHashEntry(&tsdPtr->winMenuTable,
+ (char *) *pwParam);
if (hashEntryPtr != NULL) {
- oldServiceMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
+ tsdPtr->oldServiceMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
menuPtr = (TkMenu *) Tcl_GetHashValue(hashEntryPtr);
- modalMenuPtr = menuPtr;
+ tsdPtr->modalMenuPtr = menuPtr;
if (menuPtr->menuFlags & MENU_RECONFIGURE_PENDING) {
Tcl_CancelIdleCall(ReconfigureWindowsMenu,
(ClientData) menuPtr);
ReconfigureWindowsMenu((ClientData) menuPtr);
}
- if (!inPostMenu) {
+ if (!tsdPtr->inPostMenu) {
Tcl_Interp *interp;
int code;
-
+
interp = menuPtr->interp;
Tcl_Preserve((ClientData)interp);
code = TkPreprocessMenu(menuPtr);
@@ -918,7 +930,7 @@ TkWinHandleMenuEvent(phwnd, pMessage, pwParam, plParam, plResult)
*plResult = 0;
returnResult = 1;
} else {
- modalMenuPtr = NULL;
+ tsdPtr->modalMenuPtr = NULL;
}
break;
@@ -928,7 +940,7 @@ TkWinHandleMenuEvent(phwnd, pMessage, pwParam, plParam, plResult)
if (HIWORD(*pwParam) != 0) {
break;
}
- hashEntryPtr = Tcl_FindHashEntry(&commandTable,
+ hashEntryPtr = Tcl_FindHashEntry(&tsdPtr->commandTable,
(char *)LOWORD(*pwParam));
if (hashEntryPtr == NULL) {
break;
@@ -949,21 +961,23 @@ TkWinHandleMenuEvent(phwnd, pMessage, pwParam, plParam, plResult)
menuPtr = mePtr->menuPtr;
menuRefPtr = TkFindMenuReferences(menuPtr->interp,
Tk_PathName(menuPtr->tkwin));
- if ((menuRefPtr != NULL) && (menuRefPtr->parentEntryPtr
- != NULL)) {
- for (parentEntryPtr = menuRefPtr->parentEntryPtr;
- strcmp(parentEntryPtr->name,
- Tk_PathName(menuPtr->tkwin)) != 0;
- parentEntryPtr = parentEntryPtr->nextCascadePtr) {
-
- /*
- * Empty loop body.
- */
+ if ((menuRefPtr != NULL)
+ && (menuRefPtr->parentEntryPtr != NULL)) {
+ char *name;
+ for (parentEntryPtr = menuRefPtr->parentEntryPtr;
+ ;
+ parentEntryPtr =
+ parentEntryPtr->nextCascadePtr) {
+ name = Tcl_GetStringFromObj(
+ parentEntryPtr->namePtr, NULL);
+ if (strcmp(name, Tk_PathName(menuPtr->tkwin))
+ == 0) {
+ break;
+ }
}
- if (parentEntryPtr->menuPtr
- ->entries[parentEntryPtr->index]->state
- != tkDisabledUid) {
+ if (parentEntryPtr->menuPtr->entries[parentEntryPtr->index]
+ ->state != ENTRY_DISABLED) {
TkActivateMenuEntry(parentEntryPtr->menuPtr,
parentEntryPtr->index);
}
@@ -972,8 +986,8 @@ TkWinHandleMenuEvent(phwnd, pMessage, pwParam, plParam, plResult)
interp = menuPtr->interp;
Tcl_Preserve((ClientData)interp);
code = TkInvokeMenu(interp, menuPtr, mePtr->index);
- if ((code != TCL_OK) && (code != TCL_CONTINUE)
- && (code != TCL_BREAK)) {
+ if (code != TCL_OK && code != TCL_CONTINUE
+ && code != TCL_BREAK) {
Tcl_AddErrorInfo(interp, "\n (menu invoke)");
Tcl_BackgroundError(interp);
}
@@ -987,19 +1001,27 @@ TkWinHandleMenuEvent(phwnd, pMessage, pwParam, plParam, plResult)
case WM_MENUCHAR: {
unsigned char menuChar = (unsigned char) LOWORD(*pwParam);
- hashEntryPtr = Tcl_FindHashEntry(&winMenuTable, (char *) *plParam);
+ hashEntryPtr = Tcl_FindHashEntry(&tsdPtr->winMenuTable,
+ (char *) *plParam);
if (hashEntryPtr != NULL) {
int i;
*plResult = 0;
menuPtr = (TkMenu *) Tcl_GetHashValue(hashEntryPtr);
for (i = 0; i < menuPtr->numEntries; i++) {
- int underline = menuPtr->entries[i]->underline;
+ int underline;
+ char *label;
+
+ underline = menuPtr->entries[i]->underline;
+ if (menuPtr->entries[i]->labelPtr != NULL) {
+ label = Tcl_GetStringFromObj(
+ menuPtr->entries[i]->labelPtr, NULL);
+ }
if ((-1 != underline)
- && (NULL != menuPtr->entries[i]->label)
+ && (NULL != menuPtr->entries[i]->labelPtr)
&& (CharUpper((LPTSTR) menuChar)
- == CharUpper((LPTSTR) (unsigned char) menuPtr
- ->entries[i]->label[underline]))) {
+ == CharUpper((LPTSTR) (unsigned char)
+ label[underline]))) {
*plResult = (2 << 16) | i;
returnResult = 1;
break;
@@ -1020,9 +1042,14 @@ TkWinHandleMenuEvent(phwnd, pMessage, pwParam, plParam, plResult)
itemPtr->itemHeight = mePtr->height;
itemPtr->itemWidth = mePtr->width;
if (mePtr->hideMargin) {
- itemPtr->itemWidth += 2 - indicatorDimensions[0];
+ itemPtr->itemWidth += 2 - indicatorDimensions[1];
} else {
- itemPtr->itemWidth += 2 * menuPtr->activeBorderWidth;
+ int activeBorderWidth;
+
+ Tk_GetPixelsFromObj(menuPtr->interp, menuPtr->tkwin,
+ menuPtr->activeBorderWidthPtr,
+ &activeBorderWidth);
+ itemPtr->itemWidth += 2 * activeBorderWidth;
}
*plResult = 1;
returnResult = 1;
@@ -1036,13 +1063,15 @@ TkWinHandleMenuEvent(phwnd, pMessage, pwParam, plParam, plResult)
Tk_FontMetrics fontMetrics;
if (itemPtr != NULL) {
+ Tk_Font tkfont;
+
mePtr = (TkMenuEntry *) itemPtr->itemData;
menuPtr = mePtr->menuPtr;
twdPtr = (TkWinDrawable *) ckalloc(sizeof(TkWinDrawable));
twdPtr->type = TWD_WINDC;
twdPtr->winDC.hdc = itemPtr->hDC;
- if (mePtr->state != tkDisabledUid) {
+ if (mePtr->state != ENTRY_DISABLED) {
if (itemPtr->itemState & ODS_SELECTED) {
TkActivateMenuEntry(menuPtr, mePtr->index);
} else {
@@ -1050,8 +1079,9 @@ TkWinHandleMenuEvent(phwnd, pMessage, pwParam, plParam, plResult)
}
}
- Tk_GetFontMetrics(menuPtr->tkfont, &fontMetrics);
- TkpDrawMenuEntry(mePtr, (Drawable) twdPtr, menuPtr->tkfont,
+ tkfont = Tk_GetFontFromObj(menuPtr->tkwin, menuPtr->fontPtr);
+ Tk_GetFontMetrics(tkfont, &fontMetrics);
+ TkpDrawMenuEntry(mePtr, (Drawable) twdPtr, tkfont,
&fontMetrics, itemPtr->rcItem.left,
itemPtr->rcItem.top, itemPtr->rcItem.right
- itemPtr->rcItem.left, itemPtr->rcItem.bottom
@@ -1070,14 +1100,14 @@ TkWinHandleMenuEvent(phwnd, pMessage, pwParam, plParam, plResult)
TkMenuInit();
if ((flags == 0xFFFF) && (*plParam == 0)) {
- Tcl_SetServiceMode(oldServiceMode);
- if (modalMenuPtr != NULL) {
- RecursivelyClearActiveMenu(modalMenuPtr);
+ Tcl_SetServiceMode(tsdPtr->oldServiceMode);
+ if (tsdPtr->modalMenuPtr != NULL) {
+ RecursivelyClearActiveMenu(tsdPtr->modalMenuPtr);
}
} else {
menuPtr = NULL;
- if (*plParam != 0) {
- hashEntryPtr = Tcl_FindHashEntry(&winMenuTable,
+ if (*plParam != 0) {
+ hashEntryPtr = Tcl_FindHashEntry(&tsdPtr->winMenuTable,
(char *) *plParam);
if (hashEntryPtr != NULL) {
menuPtr = (TkMenu *) Tcl_GetHashValue(hashEntryPtr);
@@ -1090,15 +1120,17 @@ TkWinHandleMenuEvent(phwnd, pMessage, pwParam, plParam, plResult)
if (flags & MF_POPUP) {
mePtr = menuPtr->entries[LOWORD(*pwParam)];
} else {
- hashEntryPtr = Tcl_FindHashEntry(&commandTable,
+ hashEntryPtr = Tcl_FindHashEntry(
+ &tsdPtr->commandTable,
(char *) LOWORD(*pwParam));
if (hashEntryPtr != NULL) {
- mePtr = (TkMenuEntry *) Tcl_GetHashValue(hashEntryPtr);
+ mePtr = (TkMenuEntry *)
+ Tcl_GetHashValue(hashEntryPtr);
}
}
}
- if ((mePtr == NULL) || (mePtr->state == tkDisabledUid)) {
+ if ((mePtr == NULL) || (mePtr->state == ENTRY_DISABLED)) {
TkActivateMenuEntry(menuPtr, -1);
} else {
TkActivateMenuEntry(menuPtr, mePtr->index);
@@ -1171,18 +1203,21 @@ TkpSetWindowMenuBar(tkwin, menuPtr)
TkMenu *menuPtr; /* The menu we are inserting */
{
HMENU winMenuHdl;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
if (menuPtr != NULL) {
Tcl_HashEntry *hashEntryPtr;
int newEntry;
winMenuHdl = (HMENU) menuPtr->platformData;
- hashEntryPtr = Tcl_FindHashEntry(&winMenuTable, (char *) winMenuHdl);
+ hashEntryPtr = Tcl_FindHashEntry(&tsdPtr->winMenuTable,
+ (char *) winMenuHdl);
Tcl_DeleteHashEntry(hashEntryPtr);
DestroyMenu(winMenuHdl);
winMenuHdl = CreateMenu();
- hashEntryPtr = Tcl_CreateHashEntry(&winMenuTable, (char *) winMenuHdl,
- &newEntry);
+ hashEntryPtr = Tcl_CreateHashEntry(&tsdPtr->winMenuTable,
+ (char *) winMenuHdl, &newEntry);
Tcl_SetHashValue(hashEntryPtr, (char *) menuPtr);
menuPtr->platformData = (TkMenuPlatformData) winMenuHdl;
TkWinSetMenu(tkwin, winMenuHdl);
@@ -1254,7 +1289,11 @@ GetMenuIndicatorGeometry (
if (mePtr->hideMargin) {
*widthPtr = 0;
} else {
- *widthPtr = indicatorDimensions[1] - menuPtr->borderWidth;
+ int borderWidth;
+
+ Tk_GetPixelsFromObj(menuPtr->interp, menuPtr->tkwin,
+ menuPtr->borderWidthPtr, &borderWidth);
+ *widthPtr = indicatorDimensions[1] - borderWidth;
}
}
@@ -1286,10 +1325,11 @@ GetMenuAccelGeometry (
*heightPtr = fmPtr->linespace;
if (mePtr->type == CASCADE_ENTRY) {
*widthPtr = 0;
- } else if (mePtr->accel == NULL) {
+ } else if (mePtr->accelPtr == NULL) {
*widthPtr = 0;
} else {
- *widthPtr = Tk_TextWidth(tkfont, mePtr->accel, mePtr->accelLength);
+ char *accel = Tcl_GetStringFromObj(mePtr->accelPtr, NULL);
+ *widthPtr = Tk_TextWidth(tkfont, accel, mePtr->accelLength);
}
}
@@ -1379,7 +1419,7 @@ DrawWindowsSystemBitmap(display, drawable, gc, rectPtr, bitmapID, alignFlags)
Display *display; /* The display we are drawing into */
Drawable drawable; /* The drawable we are working with */
GC gc; /* The GC to draw with */
- CONST RECT *rectPtr; /* The rectangle to draw into */
+ CONST RECT *rectPtr; /* The rectangle to draw into */
int bitmapID; /* The windows id of the system
* bitmap to draw. */
int alignFlags; /* How to align the bitmap inside the
@@ -1465,47 +1505,52 @@ DrawMenuEntryIndicator(menuPtr, mePtr, d, gc, indicatorGC, tkfont, fmPtr, x,
int width;
int height;
{
- if ((mePtr->type == CHECK_BUTTON_ENTRY ||
- mePtr->type == RADIO_BUTTON_ENTRY)
- && mePtr->indicatorOn
- && mePtr->entryFlags & ENTRY_SELECTED) {
- RECT rect;
- GC whichGC;
-
- if (mePtr->state != tkNormalUid) {
- whichGC = gc;
- } else {
- whichGC = indicatorGC;
- }
-
- rect.top = y;
- rect.bottom = y + mePtr->height;
- rect.left = menuPtr->borderWidth + menuPtr->activeBorderWidth + x;
- rect.right = mePtr->indicatorSpace + x;
+ if ((mePtr->type == CHECK_BUTTON_ENTRY)
+ || (mePtr->type == RADIO_BUTTON_ENTRY)) {
+ if (mePtr->indicatorOn && (mePtr->entryFlags & ENTRY_SELECTED)) {
+ RECT rect;
+ GC whichGC;
+ int borderWidth, activeBorderWidth;
+ if (mePtr->state != ENTRY_NORMAL) {
+ whichGC = gc;
+ } else {
+ whichGC = indicatorGC;
+ }
- if ((mePtr->state == tkDisabledUid) && (menuPtr->disabledFg != NULL)
- && (versionInfo.dwMajorVersion >= 4)) {
- RECT hilightRect;
- COLORREF oldFgColor = whichGC->foreground;
-
- whichGC->foreground = GetSysColor(COLOR_3DHILIGHT);
- hilightRect.top = rect.top + 1;
- hilightRect.bottom = rect.bottom + 1;
- hilightRect.left = rect.left + 1;
- hilightRect.right = rect.right + 1;
- DrawWindowsSystemBitmap(menuPtr->display, d, whichGC,
- &hilightRect, OBM_CHECK, 0);
- whichGC->foreground = oldFgColor;
- }
+ rect.top = y;
+ rect.bottom = y + mePtr->height;
+ Tk_GetPixelsFromObj(menuPtr->interp, menuPtr->tkwin,
+ menuPtr->borderWidthPtr, &borderWidth);
+ Tk_GetPixelsFromObj(menuPtr->interp, menuPtr->tkwin,
+ menuPtr->activeBorderWidthPtr, &activeBorderWidth);
+ rect.left = borderWidth + activeBorderWidth + x;
+ rect.right = mePtr->indicatorSpace + x;
+
+ if ((mePtr->state == ENTRY_DISABLED)
+ && (menuPtr->disabledFgPtr != NULL)
+ && (versionInfo.dwMajorVersion >= 4)) {
+ RECT hilightRect;
+ COLORREF oldFgColor = whichGC->foreground;
+
+ whichGC->foreground = GetSysColor(COLOR_3DHILIGHT);
+ hilightRect.top = rect.top + 1;
+ hilightRect.bottom = rect.bottom + 1;
+ hilightRect.left = rect.left + 1;
+ hilightRect.right = rect.right + 1;
+ DrawWindowsSystemBitmap(menuPtr->display, d, whichGC,
+ &hilightRect, OBM_CHECK, 0);
+ whichGC->foreground = oldFgColor;
+ }
- DrawWindowsSystemBitmap(menuPtr->display, d, whichGC, &rect,
- OBM_CHECK, 0);
+ DrawWindowsSystemBitmap(menuPtr->display, d, whichGC, &rect,
+ OBM_CHECK, 0);
- if ((mePtr->state == tkDisabledUid)
- && (menuPtr->disabledImageGC != None)
- && (versionInfo.dwMajorVersion < 4)) {
- XFillRectangle(menuPtr->display, d, menuPtr->disabledImageGC,
- rect.left, rect.top, rect.right, rect.bottom);
+ if ((mePtr->state == ENTRY_DISABLED)
+ && (menuPtr->disabledImageGC != None)
+ && (versionInfo.dwMajorVersion < 4)) {
+ XFillRectangle(menuPtr->display, d, menuPtr->disabledImageGC,
+ rect.left, rect.top, rect.right, rect.bottom);
+ }
}
}
}
@@ -1550,18 +1595,23 @@ DrawMenuEntryAccelerator(menuPtr, mePtr, d, gc, tkfont, fmPtr,
{
int baseline;
int leftEdge = x + mePtr->indicatorSpace + mePtr->labelWidth;
+ char *accel;
+
+ if (mePtr->accelPtr != NULL) {
+ accel = Tcl_GetStringFromObj(mePtr->accelPtr, NULL);
+ }
baseline = y + (height + fmPtr->ascent - fmPtr->descent) / 2;
- if ((mePtr->state == tkDisabledUid) && (menuPtr->disabledFg != NULL)
- && ((mePtr->accel != NULL)
+ if ((mePtr->state == ENTRY_DISABLED) && (menuPtr->disabledFgPtr != NULL)
+ && ((mePtr->accelPtr != NULL)
|| ((mePtr->type == CASCADE_ENTRY) && drawArrow))) {
if (versionInfo.dwMajorVersion >= 4) {
COLORREF oldFgColor = gc->foreground;
gc->foreground = GetSysColor(COLOR_3DHILIGHT);
- if (mePtr->accel != NULL) {
- Tk_DrawChars(menuPtr->display, d, gc, tkfont, mePtr->accel,
+ if (mePtr->accelPtr != NULL) {
+ Tk_DrawChars(menuPtr->display, d, gc, tkfont, accel,
mePtr->accelLength, leftEdge + 1, baseline + 1);
}
@@ -1579,12 +1629,12 @@ DrawMenuEntryAccelerator(menuPtr, mePtr, d, gc, tkfont, fmPtr,
}
}
- if (mePtr->accel != NULL) {
- Tk_DrawChars(menuPtr->display, d, gc, tkfont, mePtr->accel,
+ if (mePtr->accelPtr != NULL) {
+ Tk_DrawChars(menuPtr->display, d, gc, tkfont, accel,
mePtr->accelLength, leftEdge, baseline);
}
- if ((mePtr->state == tkDisabledUid)
+ if ((mePtr->state == ENTRY_DISABLED)
&& (menuPtr->disabledImageGC != None)
&& (versionInfo.dwMajorVersion < 4)) {
XFillRectangle(menuPtr->display, d, menuPtr->disabledImageGC,
@@ -1601,7 +1651,7 @@ DrawMenuEntryAccelerator(menuPtr, mePtr, d, gc, tkfont, fmPtr,
rect.right = x + width - 1;
DrawWindowsSystemBitmap(menuPtr->display, d, gc, &rect, OBM_MNARROW,
ALIGN_BITMAP_RIGHT);
- if ((mePtr->state == tkDisabledUid)
+ if ((mePtr->state == ENTRY_DISABLED)
&& (menuPtr->disabledImageGC != None)
&& (versionInfo.dwMajorVersion < 4)) {
XFillRectangle(menuPtr->display, d, menuPtr->disabledImageGC,
@@ -1640,13 +1690,15 @@ DrawMenuSeparator(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, y, width, height)
int height; /* height of item */
{
XPoint points[2];
+ Tk_3DBorder border;
points[0].x = x;
points[0].y = y + height / 2;
points[1].x = x + width - 1;
points[1].y = points[0].y;
- Tk_Draw3DPolygon(menuPtr->tkwin, d,
- menuPtr->border, points, 2, 1, TK_RELIEF_RAISED);
+ border = Tk_Get3DBorderFromObj(menuPtr->tkwin, menuPtr->borderPtr);
+ Tk_Draw3DPolygon(menuPtr->tkwin, d, border, points, 2, 1,
+ TK_RELIEF_RAISED);
}
/*
@@ -1680,10 +1732,14 @@ DrawMenuUnderline(
int height) /* Height of entry */
{
if (mePtr->underline >= 0) {
+ char *label = Tcl_GetStringFromObj(mePtr->labelPtr, NULL);
+ char *start = Tcl_UtfAtIndex(label, mePtr->underline);
+ char *end = Tcl_UtfNext(start);
+
Tk_UnderlineChars(menuPtr->display, d,
- gc, tkfont, mePtr->label, x + mePtr->indicatorSpace,
+ gc, tkfont, label, x + mePtr->indicatorSpace,
y + (height + fmPtr->ascent - fmPtr->descent) / 2,
- mePtr->underline, mePtr->underline + 1);
+ start - label, end - label);
}
}
@@ -1745,8 +1801,8 @@ MenuKeyBindProc(clientData, interp, eventPtr, tkwin, keySym)
CallWindowProc(DefWindowProc, Tk_GetHWND(Tk_WindowId(tkwin)),
WM_SYSKEYDOWN, virtualKey, ((scanCode << 16)
| (1 << 29)));
- if (eventPtr->xkey.nchars > 0) {
- for (i = 0; i < eventPtr->xkey.nchars; i++) {
+ if (eventPtr->xkey.nbytes > 0) {
+ for (i = 0; i < eventPtr->xkey.nbytes; i++) {
CallWindowProc(DefWindowProc,
Tk_GetHWND(Tk_WindowId(tkwin)),
WM_SYSCHAR,
@@ -1872,9 +1928,14 @@ DrawMenuEntryLabel(
{
int baseline;
int indicatorSpace = mePtr->indicatorSpace;
- int leftEdge = x + indicatorSpace + menuPtr->activeBorderWidth;
+ int activeBorderWidth;
+ int leftEdge;
int imageHeight, imageWidth;
+ Tk_GetPixelsFromObj(menuPtr->interp, menuPtr->tkwin,
+ menuPtr->activeBorderWidthPtr, &activeBorderWidth);
+ leftEdge = x + indicatorSpace + activeBorderWidth;
+
/*
* Draw label or bitmap or image for entry.
*/
@@ -1892,27 +1953,25 @@ DrawMenuEntryLabel(
imageHeight, d, leftEdge,
(int) (y + (mePtr->height - imageHeight)/2));
}
- } else if (mePtr->bitmap != None) {
+ } else if (mePtr->bitmapPtr != NULL) {
int width, height;
-
- Tk_SizeOfBitmap(menuPtr->display,
- mePtr->bitmap, &width, &height);
- XCopyPlane(menuPtr->display,
- mePtr->bitmap, d,
- gc, 0, 0, (unsigned) width, (unsigned) height, leftEdge,
- (int) (y + (mePtr->height - height)/2), 1);
+ Pixmap bitmap = Tk_GetBitmapFromObj(menuPtr->tkwin, mePtr->bitmapPtr);
+ Tk_SizeOfBitmap(menuPtr->display, bitmap, &width, &height);
+ XCopyPlane(menuPtr->display, bitmap, d, gc, 0, 0, (unsigned) width,
+ (unsigned) height, leftEdge,
+ (int) (y + (mePtr->height - height)/2), 1);
} else {
if (mePtr->labelLength > 0) {
- Tk_DrawChars(menuPtr->display, d, gc,
- tkfont, mePtr->label, mePtr->labelLength,
- leftEdge, baseline);
+ char *label = Tcl_GetStringFromObj(mePtr->labelPtr, NULL);
+ Tk_DrawChars(menuPtr->display, d, gc, tkfont, label,
+ mePtr->labelLength, leftEdge, baseline);
DrawMenuUnderline(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, y,
width, height);
}
}
- if (mePtr->state == tkDisabledUid) {
- if (menuPtr->disabledFg == NULL) {
+ if (mePtr->state == ENTRY_DISABLED) {
+ if (menuPtr->disabledFgPtr == NULL) {
XFillRectangle(menuPtr->display, d, menuPtr->disabledGC, x, y,
(unsigned) width, (unsigned) height);
} else if ((mePtr->image != NULL)
@@ -1983,6 +2042,7 @@ DrawTearoffEntry(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, y, width, height)
{
XPoint points[2];
int segmentWidth, maxX;
+ Tk_3DBorder border;
if (menuPtr->menuType != MASTER_MENU) {
return;
@@ -1993,13 +2053,14 @@ DrawTearoffEntry(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, y, width, height)
points[1].y = points[0].y;
segmentWidth = 6;
maxX = width - 1;
+ border = Tk_Get3DBorderFromObj(menuPtr->tkwin, menuPtr->borderPtr);
while (points[0].x < maxX) {
points[1].x = points[0].x + segmentWidth;
if (points[1].x > maxX) {
points[1].x = maxX;
}
- Tk_Draw3DPolygon(menuPtr->tkwin, d, menuPtr->border, points, 2, 1,
+ Tk_Draw3DPolygon(menuPtr->tkwin, d, border, points, 2, 1,
TK_RELIEF_RAISED);
points[0].x += 2*segmentWidth;
}
@@ -2014,7 +2075,7 @@ DrawTearoffEntry(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, y, width, height)
*
* Results:
* Returns standard TCL result. If TCL_ERROR is returned, then
- * interp->result contains an error message.
+ * the interp's result contains an error message.
*
* Side effects:
* Configuration information get set for mePtr; old resources
@@ -2085,8 +2146,7 @@ TkpDrawMenuEntry(mePtr, d, tkfont, menuMetricsPtr, x, y, width, height,
* Choose the gc for drawing the foreground part of the entry.
*/
- if ((mePtr->state == tkActiveUid)
- && !strictMotif) {
+ if ((mePtr->state == ENTRY_ACTIVE) && !strictMotif) {
gc = mePtr->activeGC;
if (gc == NULL) {
gc = menuPtr->activeGC;
@@ -2094,21 +2154,22 @@ TkpDrawMenuEntry(mePtr, d, tkfont, menuMetricsPtr, x, y, width, height,
} else {
TkMenuEntry *cascadeEntryPtr;
int parentDisabled = 0;
+ char *name;
for (cascadeEntryPtr = menuPtr->menuRefPtr->parentEntryPtr;
cascadeEntryPtr != NULL;
cascadeEntryPtr = cascadeEntryPtr->nextCascadePtr) {
- if (strcmp(cascadeEntryPtr->name,
- Tk_PathName(menuPtr->tkwin)) == 0) {
- if (cascadeEntryPtr->state == tkDisabledUid) {
+ name = Tcl_GetStringFromObj(cascadeEntryPtr->namePtr, NULL);
+ if (strcmp(name, Tk_PathName(menuPtr->tkwin)) == 0) {
+ if (mePtr->state == ENTRY_DISABLED) {
parentDisabled = 1;
}
break;
}
}
- if (((parentDisabled || (mePtr->state == tkDisabledUid)))
- && (menuPtr->disabledFg != NULL)) {
+ if (((parentDisabled || (mePtr->state == ENTRY_DISABLED)))
+ && (menuPtr->disabledFgPtr != NULL)) {
gc = mePtr->disabledGC;
if (gc == NULL) {
gc = menuPtr->disabledGC;
@@ -2124,24 +2185,22 @@ TkpDrawMenuEntry(mePtr, d, tkfont, menuMetricsPtr, x, y, width, height,
if (indicatorGC == NULL) {
indicatorGC = menuPtr->indicatorGC;
}
-
- bgBorder = mePtr->border;
- if (bgBorder == NULL) {
- bgBorder = menuPtr->border;
- }
+
+ bgBorder = Tk_Get3DBorderFromObj(menuPtr->tkwin,
+ (mePtr->borderPtr == NULL) ? menuPtr->borderPtr
+ : mePtr->borderPtr);
if (strictMotif) {
activeBorder = bgBorder;
} else {
- activeBorder = mePtr->activeBorder;
- if (activeBorder == NULL) {
- activeBorder = menuPtr->activeBorder;
- }
+ activeBorder = Tk_Get3DBorderFromObj(menuPtr->tkwin,
+ (mePtr->activeBorderPtr == NULL) ? menuPtr->activeBorderPtr
+ : mePtr->activeBorderPtr);
}
- if (mePtr->tkfont == NULL) {
+ if (mePtr->fontPtr == NULL) {
fmPtr = menuMetricsPtr;
} else {
- tkfont = mePtr->tkfont;
+ tkfont = Tk_GetFontFromObj(menuPtr->tkwin, mePtr->fontPtr);
Tk_GetFontMetrics(tkfont, &entryMetrics);
fmPtr = &entryMetrics;
}
@@ -2204,13 +2263,16 @@ GetMenuLabelGeometry(mePtr, tkfont, fmPtr, widthPtr, heightPtr)
if (mePtr->image != NULL) {
Tk_SizeOfImage(mePtr->image, widthPtr, heightPtr);
- } else if (mePtr->bitmap != (Pixmap) NULL) {
- Tk_SizeOfBitmap(menuPtr->display, mePtr->bitmap, widthPtr, heightPtr);
+ } else if (mePtr->bitmapPtr != NULL) {
+ Pixmap bitmap = Tk_GetBitmapFromObj(menuPtr->tkwin, mePtr->bitmapPtr);
+ Tk_SizeOfBitmap(menuPtr->display, bitmap, widthPtr, heightPtr);
} else {
*heightPtr = fmPtr->linespace;
- if (mePtr->label != NULL) {
- *widthPtr = Tk_TextWidth(tkfont, mePtr->label, mePtr->labelLength);
+ if (mePtr->labelPtr != NULL) {
+ char *label = Tcl_GetStringFromObj(mePtr->labelPtr, NULL);
+
+ *widthPtr = Tk_TextWidth(tkfont, label, mePtr->labelLength);
} else {
*widthPtr = 0;
}
@@ -2247,7 +2309,7 @@ DrawMenuEntryBackground(
int width, /* width of rectangle to draw */
int height) /* height of rectangle to draw */
{
- if (mePtr->state == tkActiveUid) {
+ if (mePtr->state == ENTRY_ACTIVE) {
bgBorder = activeBorder;
}
Tk_Fill3DRectangle(menuPtr->tkwin, d, bgBorder,
@@ -2277,17 +2339,20 @@ void
TkpComputeStandardMenuGeometry(
TkMenu *menuPtr) /* Structure describing menu. */
{
- Tk_Font tkfont;
+ Tk_Font menuFont, tkfont;
Tk_FontMetrics menuMetrics, entryMetrics, *fmPtr;
int x, y, height, width, indicatorSpace, labelWidth, accelWidth;
int windowWidth, windowHeight, accelSpace;
int i, j, lastColumnBreak = 0;
+ int activeBorderWidth, borderWidth;
if (menuPtr->tkwin == NULL) {
return;
}
- x = y = menuPtr->borderWidth;
+ Tk_GetPixelsFromObj(menuPtr->interp, menuPtr->tkwin,
+ menuPtr->borderWidthPtr, &borderWidth);
+ x = y = borderWidth;
indicatorSpace = labelWidth = accelWidth = 0;
windowHeight = 0;
@@ -2302,19 +2367,22 @@ TkpComputeStandardMenuGeometry(
* give all of the geometry/drawing the entry's font and metrics.
*/
- Tk_GetFontMetrics(menuPtr->tkfont, &menuMetrics);
- accelSpace = Tk_TextWidth(menuPtr->tkfont, "M", 1);
+ menuFont = Tk_GetFontFromObj(menuPtr->tkwin, menuPtr->fontPtr);
+ Tk_GetFontMetrics(menuFont, &menuMetrics);
+ accelSpace = Tk_TextWidth(menuFont, "M", 1);
+ Tk_GetPixelsFromObj(menuPtr->interp, menuPtr->tkwin,
+ menuPtr->activeBorderWidthPtr, &activeBorderWidth);
for (i = 0; i < menuPtr->numEntries; i++) {
- tkfont = menuPtr->entries[i]->tkfont;
- if (tkfont == NULL) {
- tkfont = menuPtr->tkfont;
- fmPtr = &menuMetrics;
- } else {
+ if (menuPtr->entries[i]->fontPtr == NULL) {
+ tkfont = menuFont;
+ fmPtr = &menuMetrics;
+ } else {
+ tkfont = Tk_GetFontFromObj(menuPtr->tkwin,
+ menuPtr->entries[i]->fontPtr);
Tk_GetFontMetrics(tkfont, &entryMetrics);
fmPtr = &entryMetrics;
}
-
if ((i > 0) && menuPtr->entries[i]->columnBreak) {
if (accelWidth != 0) {
labelWidth += accelSpace;
@@ -2323,15 +2391,15 @@ TkpComputeStandardMenuGeometry(
menuPtr->entries[j]->indicatorSpace = indicatorSpace;
menuPtr->entries[j]->labelWidth = labelWidth;
menuPtr->entries[j]->width = indicatorSpace + labelWidth
- + accelWidth + 2 * menuPtr->activeBorderWidth;
+ + accelWidth + 2 * activeBorderWidth;
menuPtr->entries[j]->x = x;
menuPtr->entries[j]->entryFlags &= ~ENTRY_LAST_COLUMN;
}
x += indicatorSpace + labelWidth + accelWidth
- + 2 * menuPtr->borderWidth;
+ + 2 * borderWidth;
indicatorSpace = labelWidth = accelWidth = 0;
lastColumnBreak = i;
- y = menuPtr->borderWidth;
+ y = borderWidth;
}
if (menuPtr->entries[i]->type == SEPARATOR_ENTRY) {
@@ -2379,7 +2447,7 @@ TkpComputeStandardMenuGeometry(
indicatorSpace = width;
}
- menuPtr->entries[i]->height += 2 * menuPtr->activeBorderWidth + 1;
+ menuPtr->entries[i]->height += 2 * activeBorderWidth + 1;
}
menuPtr->entries[i]->y = y;
y += menuPtr->entries[i]->height;
@@ -2395,16 +2463,15 @@ TkpComputeStandardMenuGeometry(
menuPtr->entries[j]->indicatorSpace = indicatorSpace;
menuPtr->entries[j]->labelWidth = labelWidth;
menuPtr->entries[j]->width = indicatorSpace + labelWidth
- + accelWidth + 2 * menuPtr->activeBorderWidth;
+ + accelWidth + 2 * activeBorderWidth;
menuPtr->entries[j]->x = x;
menuPtr->entries[j]->entryFlags |= ENTRY_LAST_COLUMN;
}
windowWidth = x + indicatorSpace + labelWidth + accelWidth + accelSpace
- + 2 * menuPtr->activeBorderWidth
- + 2 * menuPtr->borderWidth;
+ + 2 * activeBorderWidth + 2 * borderWidth;
- windowHeight += menuPtr->borderWidth;
+ windowHeight += borderWidth;
/*
* The X server doesn't like zero dimensions, so round up to at least
@@ -2530,14 +2597,55 @@ static void
MenuExitHandler(
ClientData clientData) /* Not used */
{
- DestroyWindow(menuHWND);
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ DestroyWindow(tsdPtr->menuHWND);
UnregisterClass(MENU_CLASS_NAME, Tk_GetHINSTANCE());
}
/*
*----------------------------------------------------------------------
*
- * TkpMenuInit --
+ * TkWinGetMenuSystemDefault --
+ *
+ * Gets the Windows specific default value for a given X resource
+ * database name.
+ *
+ * Results:
+ * Returns a Tcl_Obj * with the default value. If there is no
+ * Windows-specific default for this attribute, returns NULL.
+ * This object has a ref count of 0.
+ *
+ * Side effects:
+ * Storage is allocated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+TkWinGetMenuSystemDefault(
+ Tk_Window tkwin, /* A window to use. */
+ char *dbName, /* The option database name. */
+ char *className) /* The name of the option class. */
+{
+ Tcl_Obj *valuePtr = NULL;
+
+ if ((strcmp(dbName, "activeBorderWidth") == 0) ||
+ (strcmp(dbName, "borderWidth") == 0)) {
+ valuePtr = Tcl_NewIntObj(defaultBorderWidth);
+ } else if (strcmp(dbName, "font") == 0) {
+ valuePtr = Tcl_NewStringObj(Tcl_DStringValue(&menuFontDString),
+ -1);
+ }
+
+ return valuePtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkWinMenuSetDefaults --
*
* Sets up the hash tables and the variables used by the menu package.
*
@@ -2552,37 +2660,20 @@ MenuExitHandler(
*/
void
-TkpMenuInit()
+SetDefaults(
+ int firstTime) /* Is this the first time this
+ * has been called? */
{
- WNDCLASS wndClass;
- char sizeString[4];
+ char sizeString[TCL_INTEGER_SPACE];
char faceName[LF_FACESIZE];
HDC scratchDC;
Tcl_DString boldItalicDString;
int bold = 0;
int italic = 0;
- int i;
TEXTMETRIC tm;
+ int pointSize;
+ HFONT menuFont;
- Tcl_InitHashTable(&winMenuTable, TCL_ONE_WORD_KEYS);
- Tcl_InitHashTable(&commandTable, TCL_ONE_WORD_KEYS);
-
- wndClass.style = CS_OWNDC;
- wndClass.lpfnWndProc = TkWinMenuProc;
- wndClass.cbClsExtra = 0;
- wndClass.cbWndExtra = 0;
- wndClass.hInstance = Tk_GetHINSTANCE();
- wndClass.hIcon = NULL;
- wndClass.hCursor = NULL;
- wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
- wndClass.lpszMenuName = NULL;
- wndClass.lpszClassName = MENU_CLASS_NAME;
- RegisterClass(&wndClass);
-
- menuHWND = CreateWindow(MENU_CLASS_NAME, "MenuWindow", WS_POPUP,
- 0, 0, 10, 10, NULL, NULL, Tk_GetHINSTANCE(), NULL);
-
- Tcl_CreateExitHandler(MenuExitHandler, (ClientData) NULL);
versionInfo.dwOSVersionInfoSize = sizeof(versionInfo);
@@ -2601,74 +2692,59 @@ TkpMenuInit()
* out of options via a break statement.
*/
- for (i = 0; ; i++) {
- if (tkMenuConfigSpecs[i].type == TK_CONFIG_END) {
- break;
- }
+ defaultBorderWidth = GetSystemMetrics(SM_CXBORDER);
+ if (GetSystemMetrics(SM_CYBORDER) > defaultBorderWidth) {
+ defaultBorderWidth = GetSystemMetrics(SM_CYBORDER);
+ }
- if ((strcmp(tkMenuConfigSpecs[i].dbName,
- "activeBorderWidth") == 0) ||
- (strcmp(tkMenuConfigSpecs[i].dbName, "borderWidth") == 0)) {
- int borderWidth;
- borderWidth = GetSystemMetrics(SM_CXBORDER);
- if (GetSystemMetrics(SM_CYBORDER) > borderWidth) {
- borderWidth = GetSystemMetrics(SM_CYBORDER);
- }
- sprintf(borderString, "%d", borderWidth);
- tkMenuConfigSpecs[i].defValue = borderString;
- } else if ((strcmp(tkMenuConfigSpecs[i].dbName, "font") == 0)) {
- int pointSize;
- HFONT menuFont;
-
- scratchDC = CreateDC("DISPLAY", NULL, NULL, NULL);
- Tcl_DStringInit(&menuFontDString);
-
- if (versionInfo.dwMajorVersion >= 4) {
- NONCLIENTMETRICS ncMetrics;
-
- ncMetrics.cbSize = sizeof(ncMetrics);
- SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncMetrics),
- &ncMetrics, 0);
- menuFont = CreateFontIndirect(&ncMetrics.lfMenuFont);
- } else {
- menuFont = GetStockObject(SYSTEM_FONT);
- }
- SelectObject(scratchDC, menuFont);
- GetTextMetrics(scratchDC, &tm);
- GetTextFace(scratchDC, sizeof(menuFontDString), faceName);
- pointSize = MulDiv(tm.tmHeight - tm.tmInternalLeading,
- 72, GetDeviceCaps(scratchDC, LOGPIXELSY));
- if (tm.tmWeight >= 700) {
- bold = 1;
- }
- if (tm.tmItalic) {
- italic = 1;
- }
+ scratchDC = CreateDC("DISPLAY", NULL, NULL, NULL);
+ if (!firstTime) {
+ Tcl_DStringFree(&menuFontDString);
+ }
+ Tcl_DStringInit(&menuFontDString);
- SelectObject(scratchDC, GetStockObject(SYSTEM_FONT));
- DeleteDC(scratchDC);
+ if (versionInfo.dwMajorVersion >= 4) {
+ NONCLIENTMETRICS ncMetrics;
- DeleteObject(menuFont);
-
- Tcl_DStringAppendElement(&menuFontDString, faceName);
- sprintf(sizeString, "%d", pointSize);
- Tcl_DStringAppendElement(&menuFontDString, sizeString);
-
- if (bold == 1 || italic == 1) {
- Tcl_DStringInit(&boldItalicDString);
- if (bold == 1) {
- Tcl_DStringAppendElement(&boldItalicDString, "bold");
- }
- if (italic == 1) {
- Tcl_DStringAppendElement(&boldItalicDString, "italic");
- }
- Tcl_DStringAppendElement(&menuFontDString,
- Tcl_DStringValue(&boldItalicDString));
- }
+ ncMetrics.cbSize = sizeof(ncMetrics);
+ SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncMetrics),
+ &ncMetrics, 0);
+ menuFont = CreateFontIndirect(&ncMetrics.lfMenuFont);
+ } else {
+ menuFont = GetStockObject(SYSTEM_FONT);
+ }
+ SelectObject(scratchDC, menuFont);
+ GetTextMetrics(scratchDC, &tm);
+ GetTextFace(scratchDC, sizeof(menuFontDString), faceName);
+ pointSize = MulDiv(tm.tmHeight - tm.tmInternalLeading,
+ 72, GetDeviceCaps(scratchDC, LOGPIXELSY));
+ if (tm.tmWeight >= 700) {
+ bold = 1;
+ }
+ if (tm.tmItalic) {
+ italic = 1;
+ }
+
+ SelectObject(scratchDC, GetStockObject(SYSTEM_FONT));
+ DeleteDC(scratchDC);
- tkMenuConfigSpecs[i].defValue = Tcl_DStringValue(&menuFontDString);
+ DeleteObject(menuFont);
+
+ Tcl_DStringAppendElement(&menuFontDString, faceName);
+ sprintf(sizeString, "%d", pointSize);
+ Tcl_DStringAppendElement(&menuFontDString, sizeString);
+
+ if (bold == 1 || italic == 1) {
+ Tcl_DStringInit(&boldItalicDString);
+ if (bold == 1) {
+ Tcl_DStringAppendElement(&boldItalicDString, "bold");
+ }
+ if (italic == 1) {
+ Tcl_DStringAppendElement(&boldItalicDString, "italic");
}
+ Tcl_DStringAppendElement(&menuFontDString,
+ Tcl_DStringValue(&boldItalicDString));
}
/*
@@ -2692,5 +2768,72 @@ TkpMenuInit()
indicatorDimensions[0] = HIWORD(dimensions);
indicatorDimensions[1] = LOWORD(dimensions);
}
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpMenuInit --
+ *
+ * Sets up the process-wide variables used by the menu package.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * lastMenuID gets initialized.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpMenuInit()
+{
+ WNDCLASS wndClass;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ wndClass.style = CS_OWNDC;
+ wndClass.lpfnWndProc = TkWinMenuProc;
+ wndClass.cbClsExtra = 0;
+ wndClass.cbWndExtra = 0;
+ wndClass.hInstance = Tk_GetHINSTANCE();
+ wndClass.hIcon = NULL;
+ wndClass.hCursor = NULL;
+ wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
+ wndClass.lpszMenuName = NULL;
+ wndClass.lpszClassName = MENU_CLASS_NAME;
+ RegisterClass(&wndClass);
+
+ tsdPtr->menuHWND = CreateWindow(MENU_CLASS_NAME, "MenuWindow", WS_POPUP,
+ 0, 0, 10, 10, NULL, NULL, Tk_GetHINSTANCE(), NULL);
+
+ Tcl_CreateExitHandler(MenuExitHandler, (ClientData) NULL);
+ SetDefaults(1);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpMenuThreadInit --
+ *
+ * Sets up the thread-local hash tables used by the menu module.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Hash tables winMenuTable and commandTable are initialized.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpMenuThreadInit()
+{
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+ Tcl_InitHashTable(&tsdPtr->winMenuTable, TCL_ONE_WORD_KEYS);
+ Tcl_InitHashTable(&tsdPtr->commandTable, TCL_ONE_WORD_KEYS);
}