diff options
Diffstat (limited to 'win/tkWinMenu.c')
-rw-r--r-- | win/tkWinMenu.c | 667 |
1 files changed, 415 insertions, 252 deletions
diff --git a/win/tkWinMenu.c b/win/tkWinMenu.c index 00e24b7..44f53fc 100644 --- a/win/tkWinMenu.c +++ b/win/tkWinMenu.c @@ -1,20 +1,21 @@ /* * tkWinMenu.c -- * - * This module implements the Mac-platform specific features of menus. + * 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. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * SCCS: @(#) tkWinMenu.c 1.102 97/10/28 13:56:58 + * SCCS: @(#) tkWinMenu.c 1.110 98/01/26 19:43:53 */ #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. @@ -74,7 +75,7 @@ static Tcl_HashTable winMenuTable; * 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. */ @@ -122,7 +123,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 +155,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)); @@ -315,6 +317,7 @@ TkpDestroyMenu(menuPtr) TkMenu *menuPtr; /* The common menu structure */ { HMENU winMenuHdl = (HMENU) menuPtr->platformData; + char *searchName; if (menuPtr->menuFlags & MENU_RECONFIGURE_PENDING) { Tcl_CancelIdleCall(ReconfigureWindowsMenu, (ClientData) menuPtr); @@ -330,7 +333,9 @@ TkpDestroyMenu(menuPtr) for (searchEntryPtr = menuPtr->menuRefPtr->parentEntryPtr; searchEntryPtr != NULL; searchEntryPtr = searchEntryPtr->nextCascadePtr) { - if (strcmp(searchEntryPtr->name, + searchName = Tcl_GetStringFromObj(searchEntryPtr->namePtr, + NULL); + if (strcmp(searchName, menuName) == 0) { Tk_Window parentTopLevelPtr = searchEntryPtr ->menuPtr->parentTopLevelPtr; @@ -410,18 +415,22 @@ 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; + char *label = (mePtr->labelPtr == NULL) ? "" + : Tcl_GetStringFromObj(mePtr->labelPtr, NULL); + char *accel = (mePtr->accelPtr == NULL) ? "" + : Tcl_GetStringFromObj(mePtr->accelPtr, NULL); /* * We have to construct the string with an ampersand @@ -431,14 +440,14 @@ GetEntryText(mePtr) */ for (i = 0; i < mePtr->labelLength; i++) { - if (mePtr->label[i] == '&') { + if (label[i] == '&') { size++; } } if (mePtr->underline >= 0) { size++; - if (mePtr->label[mePtr->underline] == '&') { + if (label[mePtr->underline] == '&') { size++; } } @@ -448,7 +457,7 @@ GetEntryText(mePtr) } for (i = 0; i < mePtr->accelLength; i++) { - if (mePtr->accel[i] == '&') { + if (accel[i] == '&') { size++; } } @@ -459,13 +468,13 @@ GetEntryText(mePtr) itemText[0] = 0; } else { for (i = 0, j = 0; i < mePtr->labelLength; i++, j++) { - if (mePtr->label[i] == '&') { + if (label[i] == '&') { itemText[j++] = '&'; } if (i == mePtr->underline) { itemText[j++] = '&'; } - itemText[j] = mePtr->label[i]; + itemText[j] = label[i]; } itemText[j] = '\0'; } @@ -474,10 +483,10 @@ GetEntryText(mePtr) strcat(itemText, "\t"); for (i = 0, j = strlen(itemText); i < mePtr->accelLength; i++, j++) { - if (mePtr->accel[i] == '&') { + if (accel[i] == '&') { itemText[j++] = '&'; } - itemText[j] = mePtr->accel[i]; + itemText[j] = accel[i]; } itemText[j] = '\0'; } @@ -509,8 +518,8 @@ 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; @@ -552,6 +561,8 @@ ReconfigureWindowsMenu( if (mePtr->type == SEPARATOR_ENTRY) { flags |= MF_SEPARATOR; } else { + int columnBreak, state; + itemText = GetEntryText(mePtr); if ((menuPtr->menuType == MENUBAR) || (menuPtr->menuFlags & MENU_SYSTEM_MENU)) { @@ -565,7 +576,9 @@ ReconfigureWindowsMenu( * Set enabling and disabling correctly. */ - if (mePtr->state == tkDisabledUid) { + Tcl_GetIndexFromObj(NULL, mePtr->statePtr, tkMenuStateStrings, + NULL, 0, &state); + if (state == ENTRY_DISABLED) { flags |= MF_DISABLED; } @@ -579,7 +592,9 @@ ReconfigureWindowsMenu( flags |= MF_CHECKED; } - if (mePtr->columnBreak) { + Tcl_GetBooleanFromObj(NULL, mePtr->columnBreakPtr, + &columnBreak); + if (columnBreak) { flags |= MF_MENUBREAK; } @@ -603,10 +618,6 @@ ReconfigureWindowsMenu( char *systemMenuName = ckalloc(strlen( Tk_PathName(menuPtr->masterMenuPtr->tkwin)) + strlen(".system") + 1); - - strcpy(systemMenuName, - Tk_PathName(menuPtr->masterMenuPtr->tkwin)); - strcat(systemMenuName, ".system"); menuRefPtr = TkFindMenuReferences(menuPtr->interp, systemMenuName); if ((menuRefPtr != NULL) @@ -904,6 +915,7 @@ TkWinHandleMenuEvent(phwnd, pMessage, pwParam, plParam, plResult) if (mePtr != NULL) { TkMenuReferences *menuRefPtr; TkMenuEntry *parentEntryPtr; + int code; /* * We have to set the parent of this menu to be active @@ -914,28 +926,40 @@ 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; + int state; + 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) { + Tcl_GetIndexFromObj(NULL, parentEntryPtr->menuPtr + ->entries[parentEntryPtr->index] + ->statePtr, tkMenuStateStrings, NULL, + 0, &state); + if (state != ENTRY_DISABLED) { TkActivateMenuEntry(parentEntryPtr->menuPtr, parentEntryPtr->index); } } - TkInvokeMenu(mePtr->menuPtr->interp, + code = TkInvokeMenu(mePtr->menuPtr->interp, menuPtr, mePtr->index); + if (code != TCL_OK && code != TCL_CONTINUE + && code != TCL_BREAK) { + Tcl_AddErrorInfo(mePtr->menuPtr->interp, + "\n (menu invoke)"); + Tcl_BackgroundError(mePtr->menuPtr->interp); + } } *plResult = 0; returnResult = 1; @@ -954,12 +978,19 @@ TkWinHandleMenuEvent(phwnd, pMessage, pwParam, plParam, plResult) *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; break; } @@ -973,16 +1004,25 @@ TkWinHandleMenuEvent(phwnd, pMessage, pwParam, plParam, plResult) LPMEASUREITEMSTRUCT itemPtr = (LPMEASUREITEMSTRUCT) *plParam; if (itemPtr != NULL) { + int hideMargin; + mePtr = (TkMenuEntry *) itemPtr->itemData; menuPtr = mePtr->menuPtr; TkRecomputeMenu(menuPtr); itemPtr->itemHeight = mePtr->height; itemPtr->itemWidth = mePtr->width; - if (mePtr->hideMargin) { - itemPtr->itemWidth += 2 - indicatorDimensions[0]; + Tcl_GetBooleanFromObj(NULL, mePtr->hideMarginPtr, + &hideMargin); + if (hideMargin) { + 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; @@ -996,13 +1036,18 @@ TkWinHandleMenuEvent(phwnd, pMessage, pwParam, plParam, plResult) Tk_FontMetrics fontMetrics; if (itemPtr != NULL) { + int state; + 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) { + Tcl_GetIndexFromObj(NULL, mePtr->statePtr, + tkMenuStateStrings, NULL, 0, &state); + if (state != ENTRY_DISABLED) { if (itemPtr->itemState & ODS_SELECTED) { TkActivateMenuEntry(menuPtr, mePtr->index); } else { @@ -1010,8 +1055,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 @@ -1045,6 +1091,8 @@ TkWinHandleMenuEvent(phwnd, pMessage, pwParam, plParam, plResult) } if (menuPtr != NULL) { + int state; + mePtr = NULL; if (flags != 0xFFFF) { if (flags & MF_POPUP) { @@ -1053,15 +1101,22 @@ TkWinHandleMenuEvent(phwnd, pMessage, pwParam, plParam, plResult) hashEntryPtr = Tcl_FindHashEntry(&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) { TkActivateMenuEntry(menuPtr, -1); } else { - TkActivateMenuEntry(menuPtr, mePtr->index); + Tcl_GetIndexFromObj(NULL, mePtr->statePtr, + tkMenuStateStrings, NULL, 0, &state); + if (state == ENTRY_DISABLED) { + TkActivateMenuEntry(menuPtr, -1); + } else { + TkActivateMenuEntry(menuPtr, mePtr->index); + } } MenuSelectEvent(menuPtr); Tcl_ServiceAll(); @@ -1210,11 +1265,18 @@ GetMenuIndicatorGeometry ( int *widthPtr, /* The resulting width */ int *heightPtr) /* The resulting height */ { + int hideMargin; + *heightPtr = indicatorDimensions[0]; - if (mePtr->hideMargin) { + Tcl_GetBooleanFromObj(NULL, mePtr->hideMarginPtr, &hideMargin); + if (hideMargin) { *widthPtr = 0; } else { - *widthPtr = indicatorDimensions[1] - menuPtr->borderWidth; + int borderWidth; + + Tk_GetPixelsFromObj(menuPtr->interp, menuPtr->tkwin, + menuPtr->borderWidthPtr, &borderWidth); + *widthPtr = indicatorDimensions[1] - borderWidth; } } @@ -1246,10 +1308,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); } } @@ -1339,7 +1402,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 @@ -1425,47 +1488,59 @@ 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)) { + int indicatorOn; + + Tcl_GetBooleanFromObj(NULL, mePtr->indicatorOnPtr, &indicatorOn); + + if (indicatorOn && (mePtr->entryFlags & ENTRY_SELECTED)) { + RECT rect; + GC whichGC; + int state; + int borderWidth, activeBorderWidth; + Tcl_GetIndexFromObj(NULL, mePtr->statePtr, tkMenuStateStrings, + NULL, 0, &state); + if (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 ((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 ((state == ENTRY_DISABLED) + && (menuPtr->disabledImageGC != None) + && (versionInfo.dwMajorVersion < 4)) { + XFillRectangle(menuPtr->display, d, menuPtr->disabledImageGC, + rect.left, rect.top, rect.right, rect.bottom); + } } } } @@ -1510,18 +1585,26 @@ DrawMenuEntryAccelerator(menuPtr, mePtr, d, gc, tkfont, fmPtr, { int baseline; int leftEdge = x + mePtr->indicatorSpace + mePtr->labelWidth; + int state; + 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) + Tcl_GetIndexFromObj(NULL, mePtr->statePtr, tkMenuStateStrings, NULL, + 0, &state); + if ((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); } @@ -1539,12 +1622,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 ((state == ENTRY_DISABLED) && (menuPtr->disabledImageGC != None) && (versionInfo.dwMajorVersion < 4)) { XFillRectangle(menuPtr->display, d, menuPtr->disabledImageGC, @@ -1561,7 +1644,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 ((state == ENTRY_DISABLED) && (menuPtr->disabledImageGC != None) && (versionInfo.dwMajorVersion < 4)) { XFillRectangle(menuPtr->display, d, menuPtr->disabledImageGC, @@ -1600,13 +1683,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); } /* @@ -1640,8 +1725,10 @@ DrawMenuUnderline( int height) /* Height of entry */ { if (mePtr->underline >= 0) { + char *label = Tcl_GetStringFromObj(mePtr->labelPtr, NULL); + 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); } @@ -1822,8 +1909,14 @@ DrawMenuEntryLabel( { int baseline; int indicatorSpace = mePtr->indicatorSpace; - int leftEdge = x + indicatorSpace + menuPtr->activeBorderWidth; + int activeBorderWidth; + int leftEdge; int imageHeight, imageWidth; + int state; + + Tk_GetPixelsFromObj(menuPtr->interp, menuPtr->tkwin, + menuPtr->activeBorderWidthPtr, &activeBorderWidth); + leftEdge = x + indicatorSpace + activeBorderWidth; /* * Draw label or bitmap or image for entry. @@ -1842,27 +1935,27 @@ 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) { + Tcl_GetIndexFromObj(NULL, mePtr->statePtr, tkMenuStateStrings, NULL, + 0, &state); + if (state == ENTRY_DISABLED) { + if (menuPtr->disabledFgPtr == NULL) { XFillRectangle(menuPtr->display, d, menuPtr->disabledGC, x, y, (unsigned) width, (unsigned) height); } else if ((mePtr->image != NULL) @@ -1933,6 +2026,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; @@ -1943,13 +2037,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; } @@ -1964,7 +2059,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 @@ -2030,13 +2125,15 @@ TkpDrawMenuEntry(mePtr, d, tkfont, menuMetricsPtr, x, y, width, height, int padY = (menuPtr->menuType == MENUBAR) ? 3 : 0; int adjustedY = y + padY; int adjustedHeight = height - 2 * padY; + int state; /* * Choose the gc for drawing the foreground part of the entry. */ - if ((mePtr->state == tkActiveUid) - && !strictMotif) { + Tcl_GetIndexFromObj(NULL, mePtr->statePtr, tkMenuStateStrings, NULL, + 0, &state); + if ((state == ENTRY_ACTIVE) && !strictMotif) { gc = mePtr->activeGC; if (gc == NULL) { gc = menuPtr->activeGC; @@ -2044,21 +2141,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 (state == ENTRY_DISABLED) { parentDisabled = 1; } break; } } - if (((parentDisabled || (mePtr->state == tkDisabledUid))) - && (menuPtr->disabledFg != NULL)) { + if (((parentDisabled || (state == ENTRY_DISABLED))) + && (menuPtr->disabledFgPtr != NULL)) { gc = mePtr->disabledGC; if (gc == NULL) { gc = menuPtr->disabledGC; @@ -2074,24 +2172,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; } @@ -2112,11 +2208,14 @@ TkpDrawMenuEntry(mePtr, d, tkfont, menuMetricsPtr, x, y, width, height, DrawTearoffEntry(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, adjustedY, width, adjustedHeight); } else { + int hideMargin; + DrawMenuEntryLabel(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, adjustedY, width, adjustedHeight); DrawMenuEntryAccelerator(menuPtr, mePtr, d, gc, tkfont, fmPtr, activeBorder, x, adjustedY, width, adjustedHeight, drawArrow); - if (!mePtr->hideMargin) { + Tcl_GetBooleanFromObj(NULL, mePtr->hideMarginPtr, &hideMargin); + if (!hideMargin) { DrawMenuEntryIndicator(menuPtr, mePtr, d, gc, indicatorGC, tkfont, fmPtr, x, adjustedY, width, adjustedHeight); } @@ -2154,13 +2253,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; } @@ -2197,7 +2299,11 @@ DrawMenuEntryBackground( int width, /* width of rectangle to draw */ int height) /* height of rectangle to draw */ { - if (mePtr->state == tkActiveUid) { + int state; + + Tcl_GetIndexFromObj(NULL, mePtr->statePtr, tkMenuStateStrings, + NULL, 0, &state); + if (state == ENTRY_ACTIVE) { bgBorder = activeBorder; } Tk_Fill3DRectangle(menuPtr->tkwin, d, bgBorder, @@ -2227,17 +2333,21 @@ 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 columnBreak; + 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; @@ -2252,20 +2362,26 @@ 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) { + + Tcl_GetBooleanFromObj(NULL, menuPtr->entries[i]->columnBreakPtr, + &columnBreak); + if ((i > 0) && columnBreak) { if (accelWidth != 0) { labelWidth += accelSpace; } @@ -2273,15 +2389,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) { @@ -2329,7 +2445,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; @@ -2345,16 +2461,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 @@ -2487,7 +2602,45 @@ MenuExitHandler( /* *---------------------------------------------------------------------- * - * 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. * @@ -2502,37 +2655,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); @@ -2551,74 +2687,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; + } - tkMenuConfigSpecs[i].defValue = Tcl_DStringValue(&menuFontDString); + SelectObject(scratchDC, GetStockObject(SYSTEM_FONT)); + DeleteDC(scratchDC); + + 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)); } /* @@ -2642,5 +2763,47 @@ TkpMenuInit() indicatorDimensions[0] = HIWORD(dimensions); indicatorDimensions[1] = LOWORD(dimensions); } +} + +/* + *---------------------------------------------------------------------- + * + * TkpMenuInit -- + * + * Sets up the hash tables and the variables used by the menu package. + * + * Results: + * None. + * + * Side effects: + * lastMenuID gets initialized, and the parent hash and the command hash + * are allocated. + * + *---------------------------------------------------------------------- + */ + +void +TkpMenuInit() +{ + WNDCLASS wndClass; + 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); + SetDefaults(1); } |