tkMacOSXMenu.c
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:129k
- } else {
- if (!geometryPtr->accelGlyph) {
- width = Tk_TextWidth(tkfont, accel +
- geometryPtr->accelTextStart, mePtr->accelLength -
- geometryPtr->accelTextStart);
- }
- if (width < maxWidth) {
- *textWidthPtr = maxWidth;
- } else {
- *textWidthPtr = width;
- }
- if (geometryPtr->modifierNum) {
- *modWidthPtr = geometryPtr->modifierWidth;
- }
- }
- } else {
- *textWidthPtr = Tk_TextWidth(tkfont, accel, mePtr->accelLength);
- }
- }
- }
- /*
- *----------------------------------------------------------------------
- *
- * GetTearoffEntryGeometry --
- *
- * Gets the width and height of of a tearoff entry.
- *
- * Results:
- * widthPtr and heightPtr are set.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
- void
- GetTearoffEntryGeometry (
- TkMenu *menuPtr, /* The menu we are drawing */
- TkMenuEntry *mePtr, /* The entry we are measuring */
- Tk_Font tkfont, /* The precalculated font */
- const Tk_FontMetrics *fmPtr,/* The precalculated font metrics */
- int *widthPtr, /* The resulting width */
- int *heightPtr) /* The resulting height */
- {
- #ifdef USE_TK_MDEF
- const int useMDEF = ((MacMenu *) menuPtr->platformData)->useMDEF;
- #endif
- if (useMDEF && menuPtr->menuType != TEAROFF_MENU) {
- *heightPtr = fmPtr->linespace + menuItemExtraHeight;
- *widthPtr = menuPtr->totalWidth;
- } else {
- *widthPtr = *heightPtr = 0;
- }
- }
- /*
- *----------------------------------------------------------------------
- *
- * GetMenuSeparatorGeometry --
- *
- * Gets the width and height of menu separator.
- *
- * Results:
- * widthPtr and heightPtr are set.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
- void
- GetMenuSeparatorGeometry(
- TkMenu *menuPtr, /* The menu we are drawing */
- TkMenuEntry *mePtr, /* The entry we are measuring */
- Tk_Font tkfont, /* The precalculated font */
- const Tk_FontMetrics *fmPtr,/* The precalcualted font metrics */
- int *widthPtr, /* The resulting width */
- int *heightPtr) /* The resulting height */
- {
- *widthPtr = 0;
- *heightPtr = menuSeparatorHeight;
- }
- /*
- *----------------------------------------------------------------------
- *
- * DrawMenuEntryIndicator --
- *
- * This procedure draws the indicator part of a menu.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Commands are output to X to display the menu in its
- * current mode.
- *
- *----------------------------------------------------------------------
- */
- void
- DrawMenuEntryIndicator(
- TkMenu *menuPtr, /* The menu we are drawing */
- TkMenuEntry *mePtr, /* The entry we are drawing */
- Drawable d, /* The drawable we are drawing */
- GC gc, /* The GC we are drawing with */
- GC indicatorGC, /* The GC to use for the indicator */
- Tk_Font tkfont, /* The precalculated font */
- const Tk_FontMetrics *fmPtr,/* The precalculated font metrics */
- int x, /* topleft hand corner of entry */
- int y, /* topleft hand corner of entry */
- int width, /* width of entry */
- int height) /* height of entry */
- {
- if ((mePtr->type == CHECK_BUTTON_ENTRY) ||
- (mePtr->type == RADIO_BUTTON_ENTRY)) {
- if (mePtr->indicatorOn && (mePtr->entryFlags & ENTRY_SELECTED)) {
- short mark;
- int baseline = y + (height + fmPtr->ascent - fmPtr->descent)/2;
- GetItemMark(((MacMenu *) menuPtr->platformData)->menuHdl,
- mePtr->index + 1, &mark);
- if (IS_THEME_MENU_FONT(tkfont)) {
- ThemeFontID font = kThemeMenuItemMarkFont;
- TextEncoding encoding = GetApplicationTextEncoding();
- CFStringRef cfStr;
- ThemeDrawState drawState;
- Rect bounds = {y, x + menuMarkIndent, y + height, x + width};
- if (mark < kSpaceCharCode) {
- font = kThemeMenuItemCmdKeyFont;
- encoding = kTextEncodingMacKeyboardGlyphs;
- }
- switch (mePtr->state) {
- case ENTRY_ACTIVE:
- drawState = kThemeStatePressed;
- break;
- case ENTRY_DISABLED:
- drawState = kThemeStateInactive;
- break;
- default:
- drawState = kThemeStateActive;
- break;
- }
- cfStr = CFStringCreateWithBytes(NULL, (UInt8*)&mark, 1,
- encoding, false);
- if (cfStr) {
- DrawThemeText(d, gc, cfStr, font, drawState, &bounds,
- baseline, teFlushDefault);
- CFRelease(cfStr);
- }
- } else if (mark != 0) {
- const char *markUtf = NULL;
- int len;
- len = GetUtfMarkCharacter(mark, &markUtf);
- Tk_DrawChars(menuPtr->display, d, gc, tkfont, markUtf, len,
- x + menuMarkIndent, baseline);
- }
- }
- }
- }
- #ifdef USE_TK_MDEF
- /*
- *----------------------------------------------------------------------
- *
- * DrawMenuBackground --
- *
- * If Appearance is present, draws the Appearance background
- *
- * Results:
- * Nothing
- *
- * Side effects:
- * Commands are output to X to display the menu in its
- * current mode.
- *
- *----------------------------------------------------------------------
- */
- void
- DrawMenuBackground(
- TkMenu *menuPtr,
- Rect *menuRectPtr, /* The menu rect */
- Drawable d) /* What we are drawing into */
- {
- Tk_3DBorder border;
- EraseMenuBackground(((MacMenu *) menuPtr->platformData)->menuHdl,
- menuRectPtr, ((MacDrawable*)d)->context);
- border = Tk_Get3DBorderFromObj(menuPtr->tkwin, menuPtr->borderPtr);
- Tk_Fill3DRectangle(menuPtr->tkwin, d, border,
- menuRectPtr->left, menuRectPtr->top,
- menuRectPtr->right - menuRectPtr->left,
- menuRectPtr->bottom - menuRectPtr->top, 0, TK_RELIEF_FLAT);
- }
- #endif /* USE_TK_MDEF */
- /*
- *----------------------------------------------------------------------
- *
- * DrawMenuEntryAccelerator --
- *
- * This procedure draws the accelerator part of a menu.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Commands are output to X to display the menu in its
- * current mode.
- *
- *----------------------------------------------------------------------
- */
- void
- DrawMenuEntryAccelerator(
- TkMenu *menuPtr, /* The menu we are drawing */
- TkMenuEntry *mePtr, /* The entry we are drawing */
- Drawable d, /* The drawable we are drawing in */
- GC gc, /* The gc to draw into */
- Tk_Font tkfont, /* The precalculated font */
- const Tk_FontMetrics *fmPtr,/* The precalculated font metrics */
- Tk_3DBorder activeBorder, /* border for menu background */
- int x, /* The left side of the entry */
- int y, /* The top of the entry */
- int width, /* The width of the entry */
- int height, /* The height of the entry */
- int drawArrow) /* Whether or not to draw cascade arrow */
- {
- if (mePtr->type != CASCADE_ENTRY && mePtr->accelLength > 0) {
- const char *accel = (mePtr->accelPtr == NULL) ? ""
- : Tcl_GetString(mePtr->accelPtr);
- EntryGeometry *geometryPtr = (EntryGeometry*)mePtr->platformEntryData;
- int leftEdge = x + width - geometryPtr->accelTextWidth;
- int baseline = y + (height + fmPtr->ascent - fmPtr->descent) / 2;
- if (IS_THEME_MENU_FONT(tkfont)) {
- CFStringRef cfStr;
- ThemeDrawState drawState;
- switch (mePtr->state) {
- case ENTRY_ACTIVE:
- drawState = kThemeStatePressed;
- break;
- case ENTRY_DISABLED:
- drawState = kThemeStateInactive;
- break;
- default:
- drawState = kThemeStateActive;
- break;
- }
- if ((mePtr->entryFlags & ENTRY_ACCEL_MASK) == 0) {
- leftEdge -= geometryPtr->modifierWidth;
- }
- if (geometryPtr->accelGlyph) {
- Rect bounds = {y, leftEdge, y + height, leftEdge +
- geometryPtr->accelTextWidth};
- cfStr = CFStringCreateWithBytes(NULL,
- (UInt8*)&geometryPtr->accelGlyph, 1,
- kTextEncodingMacKeyboardGlyphs, false);
- if (cfStr) {
- DrawThemeText(d, gc, cfStr, kThemeMenuItemCmdKeyFont,
- drawState, &bounds, baseline, teFlushDefault);
- CFRelease(cfStr);
- }
- } else {
- Tk_DrawChars(menuPtr->display, d, gc, tkfont, accel +
- geometryPtr->accelTextStart, mePtr->accelLength -
- geometryPtr->accelTextStart, leftEdge, baseline);
- }
- if (geometryPtr->modifierNum) {
- Rect bounds = {y, leftEdge - geometryPtr->modifierWidth,
- y + height, leftEdge};
- cfStr = CFStringCreateWithCharacters(NULL,
- geometryPtr->modifierUniChars,
- geometryPtr->modifierNum);
- if (cfStr) {
- DrawThemeText(d, gc, cfStr, kThemeMenuItemCmdKeyFont,
- drawState, &bounds, baseline, teFlushDefault);
- CFRelease(cfStr);
- }
- }
- } else {
- Tk_DrawChars(menuPtr->display, d, gc, tkfont, accel,
- mePtr->accelLength, leftEdge, baseline);
- }
- }
- }
- /*
- *----------------------------------------------------------------------
- *
- * DrawMenuSeparator --
- *
- * The menu separator is drawn.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Commands are output to X to display the menu in its
- * current mode.
- *
- *----------------------------------------------------------------------
- */
- void
- DrawMenuSeparator(
- TkMenu *menuPtr, /* The menu we are drawing */
- TkMenuEntry *mePtr, /* The entry we are drawing */
- Drawable d, /* The drawable we are drawing into */
- GC gc, /* The gc we are drawing with */
- Tk_Font tkfont, /* The precalculated font */
- const Tk_FontMetrics *fmPtr,/* The precalculated font metrics */
- int x, /* left coordinate of entry */
- int y, /* top coordinate of entry */
- int width, /* width of entry */
- int height) /* height of entry */
- {
- TkMacOSXDrawingContext dc;
- Rect r;
- r.top = y;
- r.left = x;
- r.bottom = y + height;
- r.right = x + width;
- if (TkMacOSXSetupDrawingContext(d, gc, 1, &dc)) {
- ChkErr(DrawThemeMenuSeparator, &r);
- TkMacOSXRestoreDrawingContext(&dc);
- }
- }
- #ifdef USE_TK_MDEF
- /*
- *----------------------------------------------------------------------
- *
- * AppearanceEntryDrawWrapper --
- *
- * It routes to the Appearance Managers DrawThemeEntry, which will
- * then call us back after setting up the drawing context.
- *
- * Results:
- * A menu entry is drawn
- *
- * Side effects:
- * None
- *
- *----------------------------------------------------------------------
- */
- void
- AppearanceEntryDrawWrapper(
- TkMenuEntry *mePtr,
- Rect *menuRectPtr,
- MenuTrackingData *mtdPtr,
- Drawable d,
- Tk_FontMetrics *fmPtr,
- Tk_Font tkfont,
- int erase)
- {
- MenuEntryUserData meData;
- Rect itemRect;
- ThemeMenuState theState;
- ThemeMenuItemType theType;
- Tk_FontMetrics entryMetrics;
- meData.mePtr = mePtr;
- meData.mdefDrawable = d;
- if (mePtr->fontPtr == NULL) {
- meData.fmPtr = fmPtr;
- meData.tkfont = tkfont;
- } else {
- meData.tkfont = Tk_GetFontFromObj(mePtr->menuPtr->tkwin,
- mePtr->fontPtr);
- Tk_GetFontMetrics(meData.tkfont, &entryMetrics);
- fmPtr = &entryMetrics;
- }
- itemRect.left = menuRectPtr->left + mePtr->x;
- itemRect.top = mtdPtr->virtualMenuTop + mePtr->y;
- itemRect.right = mePtr->entryFlags & ENTRY_LAST_COLUMN ?
- menuRectPtr->right : itemRect.left + mePtr->width;
- itemRect.bottom = itemRect.top + mePtr->height;
- if (mePtr->state == ENTRY_ACTIVE) {
- theState = kThemeMenuSelected;
- } else if (mePtr->state == ENTRY_DISABLED) {
- theState = kThemeMenuDisabled;
- } else {
- theState = kThemeMenuActive;
- }
- if (mePtr->type == CASCADE_ENTRY) {
- theType = kThemeMenuItemHierarchical;
- } else {
- theType = kThemeMenuItemPlain;
- }
- if (erase) {
- DisableScreenUpdates();
- DrawMenuBackground(mePtr->menuPtr, &itemRect, d);
- }
- DrawThemeMenuItem(menuRectPtr, &itemRect,
- mtdPtr->virtualMenuTop, mtdPtr->virtualMenuBottom, theState,
- theType | kThemeMenuItemNoBackground, tkThemeMenuItemDrawingUPP,
- (unsigned long) &meData);
- if (erase) {
- EnableScreenUpdates();
- }
- }
- /*
- *----------------------------------------------------------------------
- *
- * ThemeMenuItemDrawingProc --
- *
- * This routine is called from the Appearance DrawThemeMenuEntry
- *
- * Results:
- * A menu entry is drawn
- *
- * Side effects:
- * None
- *
- *----------------------------------------------------------------------
- */
- pascal void
- ThemeMenuItemDrawingProc(
- const Rect *inBounds,
- SInt16 inDepth,
- Boolean inIsColorDevice,
- SInt32 inUserData)
- {
- MenuEntryUserData *meData = (MenuEntryUserData *) inUserData;
- TkpDrawMenuEntry(meData->mePtr, meData->mdefDrawable, meData->tkfont,
- meData->fmPtr, inBounds->left, inBounds->top, inBounds->right -
- inBounds->left + menuItemExtraWidth, inBounds->bottom -
- inBounds->top + menuItemExtraHeight, 0, 1);
- }
- #endif /* USE_TK_MDEF */
- /*
- *----------------------------------------------------------------------
- *
- * TkMacOSXHandleTearoffMenu() --
- *
- * This routine sees if the MDEF has set a menu and a mouse position
- * for tearing off and makes a tearoff menu if it has.
- *
- * Results:
- * menuPtr->interp will have the result of the tearoff command.
- *
- * Side effects:
- * A new tearoff menu is created if it is supposed to be.
- *
- *----------------------------------------------------------------------
- */
- void
- TkMacOSXHandleTearoffMenu(void)
- {
- /*
- * Obsolete: Nothing to do.
- */
- }
- /*
- *--------------------------------------------------------------
- *
- * TkpInitializeMenuBindings --
- *
- * For every interp, initializes the bindings for Windows
- * menus. Does nothing on Mac or XWindows.
- *
- * Results:
- * None.
- *
- * Side effects:
- * C-level bindings are setup for the interp which will
- * handle Alt-key sequences for menus without beeping
- * or interfering with user-defined Alt-key bindings.
- *
- *--------------------------------------------------------------
- */
- void
- TkpInitializeMenuBindings(
- Tcl_Interp *interp, /* The interpreter to set. */
- Tk_BindingTable bindingTable)
- /* The table to add to. */
- {
- /*
- * Nothing to do.
- */
- }
- /*
- *--------------------------------------------------------------
- *
- * TkpComputeMenubarGeometry --
- *
- * This procedure is invoked to recompute the size and
- * layout of a menu that is a menubar clone.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Fields of menu entries are changed to reflect their
- * current positions, and the size of the menu window
- * itself may be changed.
- *
- *--------------------------------------------------------------
- */
- void
- TkpComputeMenubarGeometry(
- TkMenu *menuPtr) /* Structure describing menu. */
- {
- TkpComputeStandardMenuGeometry(menuPtr);
- }
- /*
- *----------------------------------------------------------------------
- *
- * DrawTearoffEntry --
- *
- * This procedure draws a tearoff entry.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Commands are output to X to display the menu in its
- * current mode.
- *
- *----------------------------------------------------------------------
- */
- void
- DrawTearoffEntry(
- TkMenu *menuPtr, /* The menu we are drawing */
- TkMenuEntry *mePtr, /* The entry we are drawing */
- Drawable d, /* The drawable we are drawing into */
- GC gc, /* The gc we are drawing with */
- Tk_Font tkfont, /* The font we are drawing with */
- const Tk_FontMetrics *fmPtr,/* The metrics we are drawing with */
- int x, /* Left edge of entry. */
- int y, /* Top edge of entry. */
- int width, /* Width of entry. */
- int height) /* Height of entry. */
- {
- XPoint points[2];
- int margin, segmentWidth, maxX;
- Tk_3DBorder border;
- if (menuPtr->menuType != MASTER_MENU ) {
- return;
- }
- margin = fmPtr->linespace/2;
- points[0].x = x;
- points[0].y = y + height/2;
- points[1].y = points[0].y;
- segmentWidth = 6;
- maxX = x + menuPtr->totalWidth - 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, border, points, 2, 1,
- TK_RELIEF_RAISED);
- points[0].x += 2*segmentWidth;
- }
- }
- /*
- *----------------------------------------------------------------------
- *
- * TkMacOSXSetHelpMenuItemCount --
- *
- * Has to be called after the first call to InsertMenu. Sets
- * up the global variable for the number of items in the
- * unmodified help menu.
- * NB. Nobody uses this any more, since you can get the number
- * of system help items from HMGetHelpMenu trivially.
- * But it is in the stubs table...
- *
- * Results:
- * None.
- *
- * Side effects:
- * Nothing.
- *
- *----------------------------------------------------------------------
- */
- void
- TkMacOSXSetHelpMenuItemCount(void)
- {
- /*
- * Obsolete: Nothing to do.
- */
- }
- /*
- *----------------------------------------------------------------------
- *
- * TkMacOSXMenuClick --
- *
- * Prepares a menubar for MenuSelect or MenuKey.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Any pending configurations of the menubar are completed.
- *
- *----------------------------------------------------------------------
- */
- void
- TkMacOSXMenuClick(void)
- {
- TkMenu *menuPtr;
- TkMenuReferences *menuRefPtr;
- if ((currentMenuBarInterp != NULL) && (currentMenuBarName != NULL)) {
- menuRefPtr = TkFindMenuReferences(currentMenuBarInterp,
- currentMenuBarName);
- for (menuPtr = menuRefPtr->menuPtr->masterMenuPtr;
- menuPtr != NULL; menuPtr = menuPtr->nextInstancePtr) {
- if (menuPtr->menuType == MENUBAR) {
- CompleteIdlers(menuPtr);
- break;
- }
- }
- }
- if (menuBarFlags & MENUBAR_REDRAW_PENDING) {
- Tcl_CancelIdleCall(DrawMenuBarWhenIdle, NULL);
- DrawMenuBarWhenIdle(NULL);
- }
- }
- /*
- *----------------------------------------------------------------------
- *
- * TkpDrawMenuEntry --
- *
- * Draws the given menu entry at the given coordinates with the
- * given attributes.
- *
- * Results:
- * None.
- *
- * Side effects:
- * X Server commands are executed to display the menu entry.
- *
- *----------------------------------------------------------------------
- */
- void
- TkpDrawMenuEntry(
- TkMenuEntry *mePtr, /* The entry to draw */
- Drawable d, /* What to draw into */
- Tk_Font tkfont, /* Precalculated font for menu */
- const Tk_FontMetrics *menuMetricsPtr,
- /* Precalculated metrics for menu */
- int x, /* X-coordinate of topleft of entry */
- int y, /* Y-coordinate of topleft of entry */
- int width, /* Width of the entry rectangle */
- int height, /* Height of the current rectangle */
- int strictMotif, /* Boolean flag */
- int drawArrow) /* Whether or not to draw the cascade
- * arrow for cascade items. Only applies
- * to Windows. */
- {
- GC gc;
- TkMenu *menuPtr = mePtr->menuPtr;
- int padY = (menuPtr->menuType == MENUBAR) ? 3 : 0;
- GC indicatorGC;
- Tk_3DBorder bgBorder, activeBorder;
- const Tk_FontMetrics *fmPtr;
- Tk_FontMetrics entryMetrics;
- int adjustedY = y + padY;
- int adjustedHeight = height - 2 * padY;
- /*
- * Choose the gc for drawing the foreground part of the entry.
- * Under Appearance, we pass a null (appearanceGC) to tell
- * ourselves not to change whatever color the appearance manager has set.
- */
- if ((mePtr->state == ENTRY_ACTIVE) && !strictMotif) {
- gc = mePtr->activeGC;
- if (gc == NULL) {
- gc = menuPtr->activeGC;
- }
- } else {
- TkMenuEntry *parentEntryPtr = GetParentMenuEntry(menuPtr);
- if (((parentEntryPtr && parentEntryPtr->state == ENTRY_DISABLED) ||
- (mePtr->state == ENTRY_DISABLED)) &&
- (menuPtr->disabledFgPtr != NULL)) {
- gc = mePtr->disabledGC;
- if (gc == NULL) {
- gc = menuPtr->disabledGC;
- }
- } else {
- gc = mePtr->textGC;
- if (gc == NULL) {
- gc = menuPtr->textGC;
- }
- }
- }
- indicatorGC = mePtr->indicatorGC;
- if (indicatorGC == NULL) {
- indicatorGC = menuPtr->indicatorGC;
- }
- bgBorder = Tk_Get3DBorderFromObj(menuPtr->tkwin,
- (mePtr->borderPtr == NULL)
- ? menuPtr->borderPtr : mePtr->borderPtr);
- if (strictMotif) {
- activeBorder = bgBorder;
- } else {
- activeBorder = Tk_Get3DBorderFromObj(menuPtr->tkwin,
- (mePtr->activeBorderPtr == NULL)
- ? menuPtr->activeBorderPtr : mePtr->activeBorderPtr);
- }
- if (mePtr->fontPtr == NULL) {
- fmPtr = menuMetricsPtr;
- } else {
- tkfont = Tk_GetFontFromObj(menuPtr->tkwin, mePtr->fontPtr);
- Tk_GetFontMetrics(tkfont, &entryMetrics);
- fmPtr = &entryMetrics;
- }
- /*
- * Need to draw the entire background, including padding. On Unix,
- * for menubars, we have to draw the rest of the entry taking
- * into account the padding.
- */
- DrawMenuEntryBackground(menuPtr, mePtr, d, activeBorder, bgBorder, x, y,
- width, height);
- if (mePtr->type == SEPARATOR_ENTRY) {
- DrawMenuSeparator(menuPtr, mePtr, d, gc, tkfont,
- fmPtr, x, adjustedY, width, adjustedHeight);
- } else if (mePtr->type == TEAROFF_ENTRY) {
- DrawTearoffEntry(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, adjustedY,
- width, adjustedHeight);
- } else {
- 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) {
- DrawMenuEntryIndicator(menuPtr, mePtr, d, gc, indicatorGC, tkfont,
- fmPtr, x, adjustedY, width, adjustedHeight);
- }
- }
- }
- /*
- *--------------------------------------------------------------
- *
- * TkpComputeStandardMenuGeometry --
- *
- * This procedure is invoked to recompute the size and
- * layout of a menu that is not a menubar clone.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Fields of menu entries are changed to reflect their
- * current positions, and the size of the menu window
- * itself may be changed.
- *
- *--------------------------------------------------------------
- */
- void
- TkpComputeStandardMenuGeometry(
- TkMenu *menuPtr) /* Structure describing menu. */
- {
- Tk_Font tkfont, menuFont;
- Tk_FontMetrics menuMetrics, entryMetrics, *fmPtr;
- int x, y, height, modifierWidth, labelWidth, indicatorSpace;
- int windowWidth, windowHeight, accelWidth, maxAccelTextWidth;
- int i, j, lastColumnBreak, maxModifierWidth, maxWidth, nonAccelMargin;
- int maxNonAccelMargin, maxEntryWithAccelWidth, maxEntryWithoutAccelWidth;
- int entryWidth, maxIndicatorSpace, borderWidth, activeBorderWidth;
- TkMenuEntry *mePtr, *columnEntryPtr;
- EntryGeometry *geometryPtr;
- int haveAccel = 0;
- if (menuPtr->tkwin == NULL) {
- return;
- }
- Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->borderWidthPtr,
- &borderWidth);
- Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->activeBorderWidthPtr,
- &activeBorderWidth);
- x = y = borderWidth;
- indicatorSpace = labelWidth = accelWidth = maxAccelTextWidth = 0;
- windowHeight = windowWidth = maxWidth = lastColumnBreak = 0;
- maxModifierWidth = nonAccelMargin = maxNonAccelMargin = 0;
- maxEntryWithAccelWidth = maxEntryWithoutAccelWidth = 0;
- maxIndicatorSpace = 0;
- /*
- * On the Mac especially, getting font metrics can be quite slow,
- * so we want to do it intelligently. We are going to precalculate
- * them and pass them down to all of the measuring and drawing
- * routines. We will measure the font metrics of the menu once.
- * If an entry does not have its own font set, then we give
- * the geometry/drawing routines the menu's font and metrics.
- * If an entry has its own font, we will measure that font and
- * give all of the geometry/drawing the entry's font and metrics.
- */
- menuFont = Tk_GetFontFromObj(menuPtr->tkwin, menuPtr->fontPtr);
- Tk_GetFontMetrics(menuFont, &menuMetrics);
- for (i = 0; i < menuPtr->numEntries; i++) {
- mePtr = menuPtr->entries[i];
- if (mePtr->type == CASCADE_ENTRY || mePtr->accelLength > 0) {
- haveAccel = 1;
- break;
- }
- }
- for (i = 0; i < menuPtr->numEntries; i++) {
- mePtr = menuPtr->entries[i];
- if (mePtr->fontPtr == NULL) {
- tkfont = menuFont;
- fmPtr = &menuMetrics;
- } else {
- tkfont = Tk_GetFontFromObj(menuPtr->tkwin, mePtr->fontPtr);
- Tk_GetFontMetrics(tkfont, &entryMetrics);
- fmPtr = &entryMetrics;
- }
- if ((i > 0) && mePtr->columnBreak) {
- if (maxIndicatorSpace != 0) {
- maxIndicatorSpace += 2;
- }
- for (j = lastColumnBreak; j < i; j++) {
- columnEntryPtr = menuPtr->entries[j];
- geometryPtr =
- (EntryGeometry *) columnEntryPtr->platformEntryData;
- columnEntryPtr->indicatorSpace = maxIndicatorSpace;
- columnEntryPtr->width = maxIndicatorSpace + maxWidth
- + 2 * activeBorderWidth;
- geometryPtr->accelTextWidth = maxAccelTextWidth;
- geometryPtr->modifierWidth = maxModifierWidth;
- columnEntryPtr->x = x;
- columnEntryPtr->entryFlags &= ~ENTRY_LAST_COLUMN;
- if (maxEntryWithoutAccelWidth > maxEntryWithAccelWidth) {
- geometryPtr->nonAccelMargin = maxEntryWithoutAccelWidth
- - maxEntryWithAccelWidth;
- if (geometryPtr->nonAccelMargin > maxNonAccelMargin) {
- geometryPtr->nonAccelMargin = maxNonAccelMargin;
- }
- } else {
- geometryPtr->nonAccelMargin = 0;
- }
- }
- x += maxIndicatorSpace + maxWidth + 2 * borderWidth;
- windowWidth = x;
- maxWidth = maxIndicatorSpace = maxAccelTextWidth = 0;
- maxModifierWidth = maxNonAccelMargin = maxEntryWithAccelWidth = 0;
- maxEntryWithoutAccelWidth = 0;
- lastColumnBreak = i;
- y = borderWidth;
- }
- geometryPtr = (EntryGeometry *) mePtr->platformEntryData;
- if (mePtr->type == SEPARATOR_ENTRY) {
- GetMenuSeparatorGeometry(menuPtr, mePtr, tkfont,
- fmPtr, &entryWidth, &height);
- mePtr->height = height;
- } else if (mePtr->type == TEAROFF_ENTRY) {
- GetTearoffEntryGeometry(menuPtr, mePtr, tkfont,
- fmPtr, &entryWidth, &height);
- mePtr->height = height;
- } else {
- /*
- * For each entry, compute the height required by that
- * particular entry, plus three widths: the width of the
- * label, the width to allow for an indicator to be displayed
- * to the left of the label (if any), and the width of the
- * accelerator to be displayed to the right of the label
- * (if any). These sizes depend, of course, on the type
- * of the entry.
- */
- GetMenuLabelGeometry(mePtr, tkfont, fmPtr, &labelWidth, &height);
- mePtr->height = height;
- nonAccelMargin = 0;
- if (mePtr->type == CASCADE_ENTRY) {
- GetMenuAccelGeometry(menuPtr, mePtr, tkfont, fmPtr,
- &modifierWidth, &accelWidth, &height);
- } else if (mePtr->accelLength == 0) {
- if (haveAccel && !mePtr->hideMargin) {
- if (IS_THEME_MENU_FONT(tkfont)) {
- nonAccelMargin = menuSymbols[COMMAND_SYMBOL].width;
- } else {
- nonAccelMargin = Tk_TextWidth(tkfont,
- menuSymbols[COMMAND_SYMBOL].utf,
- menuSymbols[COMMAND_SYMBOL].utfLen);
- }
- }
- accelWidth = modifierWidth = 0;
- } else {
- GetMenuAccelGeometry(menuPtr, mePtr, tkfont,
- fmPtr, &modifierWidth, &accelWidth, &height);
- if (height > mePtr->height) {
- mePtr->height = height;
- }
- }
- if (!(mePtr->hideMargin)) {
- GetMenuIndicatorGeometry(menuPtr, mePtr, tkfont,
- fmPtr, &indicatorSpace, &height);
- if (height > mePtr->height) {
- mePtr->height = height;
- }
- } else {
- indicatorSpace = 0;
- }
- if (nonAccelMargin > maxNonAccelMargin) {
- maxNonAccelMargin = nonAccelMargin;
- }
- if (accelWidth > maxAccelTextWidth) {
- maxAccelTextWidth = accelWidth;
- }
- if (modifierWidth > maxModifierWidth) {
- maxModifierWidth = modifierWidth;
- }
- if (indicatorSpace > maxIndicatorSpace) {
- maxIndicatorSpace = indicatorSpace;
- }
- entryWidth = labelWidth + modifierWidth + accelWidth
- + nonAccelMargin;
- if (entryWidth > maxWidth) {
- maxWidth = entryWidth;
- }
- if (mePtr->accelLength > 0) {
- if (entryWidth > maxEntryWithAccelWidth) {
- maxEntryWithAccelWidth = entryWidth;
- }
- } else {
- if (entryWidth > maxEntryWithoutAccelWidth) {
- maxEntryWithoutAccelWidth = entryWidth;
- }
- }
- mePtr->height += 2 * activeBorderWidth;
- }
- mePtr->y = y;
- y += menuPtr->entries[i]->height + borderWidth;
- if (y > windowHeight) {
- windowHeight = y;
- }
- }
- for (j = lastColumnBreak; j < menuPtr->numEntries; j++) {
- columnEntryPtr = menuPtr->entries[j];
- geometryPtr = (EntryGeometry *) columnEntryPtr->platformEntryData;
- columnEntryPtr->indicatorSpace = maxIndicatorSpace;
- columnEntryPtr->width = maxIndicatorSpace + maxWidth
- + 2 * activeBorderWidth;
- geometryPtr->accelTextWidth = maxAccelTextWidth;
- columnEntryPtr->x = x;
- columnEntryPtr->entryFlags |= ENTRY_LAST_COLUMN;
- if (maxEntryWithoutAccelWidth > maxEntryWithAccelWidth) {
- geometryPtr->nonAccelMargin = maxEntryWithoutAccelWidth
- - maxEntryWithAccelWidth;
- if (geometryPtr->nonAccelMargin > maxNonAccelMargin) {
- geometryPtr->nonAccelMargin = maxNonAccelMargin;
- }
- } else {
- geometryPtr->nonAccelMargin = 0;
- }
- }
- windowWidth = x + maxIndicatorSpace + maxWidth
- + 2 * activeBorderWidth + borderWidth;
- windowHeight += borderWidth;
- /*
- * The X server doesn't like zero dimensions, so round up to at least
- * 1 (a zero-sized menu should never really occur, anyway).
- */
- if (windowWidth <= 0) {
- windowWidth = 1;
- }
- if (windowHeight <= 0) {
- windowHeight = 1;
- }
- menuPtr->totalWidth = windowWidth;
- menuPtr->totalHeight = windowHeight;
- }
- /*
- *----------------------------------------------------------------------
- *
- * DrawMenuEntryLabel --
- *
- * This procedure draws the label part of a menu.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Commands are output to X to display the menu in its
- * current mode.
- *
- *----------------------------------------------------------------------
- */
- void
- DrawMenuEntryLabel(
- TkMenu *menuPtr, /* The menu we are drawing */
- TkMenuEntry *mePtr, /* The entry we are drawing */
- Drawable d, /* What we are drawing into */
- GC gc, /* The gc we are drawing into */
- Tk_Font tkfont, /* The precalculated font */
- const Tk_FontMetrics *fmPtr,/* The precalculated font metrics */
- int x, /* left edge */
- int y, /* right edge */
- int width, /* width of entry */
- int height) /* height of entry */
- {
- int imageWidth, imageHeight, textWidth = 0, textHeight = 0;
- int indicatorSpace = mePtr->indicatorSpace;
- int leftEdge = x + indicatorSpace;
- int haveImage = 0, haveText = 0;
- int imageXOffset = 0, imageYOffset = 0;
- int textXOffset = 0, textYOffset = 0;
- Pixmap bitmap = (Pixmap) NULL;
- Tcl_DString itemTextDString;
- /*
- * Work out what we will need to draw first.
- */
- if (mePtr->image != NULL) {
- Tk_SizeOfImage(mePtr->image, &imageWidth, &imageHeight);
- haveImage = 1;
- } else if (mePtr->bitmapPtr != NULL) {
- bitmap = Tk_GetBitmapFromObj(menuPtr->tkwin, mePtr->bitmapPtr);
- Tk_SizeOfBitmap(menuPtr->display, bitmap, &imageWidth, &imageHeight);
- haveImage = 1;
- }
- if (!haveImage || (mePtr->compound != COMPOUND_NONE)) {
- if (mePtr->labelLength > 0) {
- GetEntryText(mePtr, &itemTextDString);
- if (mePtr->compound != COMPOUND_NONE) {
- textWidth = Tk_TextWidth(tkfont,
- Tcl_DStringValue(&itemTextDString),
- Tcl_DStringLength(&itemTextDString)) +
- menuTextLeadingEdgeMargin + menuTextTrailingEdgeMargin;
- textHeight = fmPtr->linespace;
- }
- haveText = 1;
- }
- }
- /*
- * Now work out what the relative positions are.
- */
- if (haveImage && haveText && (mePtr->compound != COMPOUND_NONE)) {
- int fullWidth = (imageWidth > textWidth ? imageWidth : textWidth);
- switch ((enum compound) mePtr->compound) {
- case COMPOUND_TOP:
- textXOffset = (fullWidth - textWidth)/2;
- textYOffset = imageHeight/2 + 2;
- imageXOffset = (fullWidth - imageWidth)/2;
- imageYOffset = -textHeight/2;
- break;
- case COMPOUND_BOTTOM:
- textXOffset = (fullWidth - textWidth)/2;
- textYOffset = -imageHeight/2;
- imageXOffset = (fullWidth - imageWidth)/2;
- imageYOffset = textHeight/2 + 2;
- break;
- case COMPOUND_LEFT:
- /*
- * Position image in the indicator space to the left of the
- * entries, unless this entry is a radio|check button because
- * then the indicator space will be used.
- */
- textXOffset = imageWidth + 2 - menuTextLeadingEdgeMargin;
- if ((mePtr->type != CHECK_BUTTON_ENTRY)
- && (mePtr->type != RADIO_BUTTON_ENTRY)) {
- textXOffset -= indicatorSpace;
- imageXOffset = -indicatorSpace;
- }
- if (textXOffset < 0) {
- textXOffset = 0;
- }
- break;
- case COMPOUND_RIGHT:
- imageXOffset = textWidth + 2 - menuTextTrailingEdgeMargin;
- break;
- case COMPOUND_CENTER:
- textXOffset = (fullWidth - textWidth)/2;
- imageXOffset = (fullWidth - imageWidth)/2;
- break;
- case COMPOUND_NONE:
- /*
- * Never reached.
- */
- break;
- }
- }
- /*
- * Draw label and/or bitmap or image for entry.
- */
- if (mePtr->image != NULL) {
- if ((mePtr->selectImage != NULL)
- && (mePtr->entryFlags & ENTRY_SELECTED)) {
- Tk_RedrawImage(mePtr->selectImage, 0, 0, imageWidth, imageHeight,
- d, leftEdge + imageXOffset,
- y + (mePtr->height - imageHeight)/2 + imageYOffset);
- } else {
- Tk_RedrawImage(mePtr->image, 0, 0, imageWidth, imageHeight,
- d, leftEdge + imageXOffset,
- y + (mePtr->height - imageHeight)/2 + imageYOffset);
- }
- } else if (mePtr->bitmapPtr != NULL) {
- XCopyPlane(menuPtr->display, bitmap, d, gc, 0, 0, imageWidth,
- imageHeight, leftEdge + imageXOffset,
- y + (mePtr->height - imageHeight)/2 + imageYOffset, 1);
- }
- if (haveText) {
- int baseline = y + (height + fmPtr->ascent - fmPtr->descent)/2;
- Tk_DrawChars(menuPtr->display, d, gc, tkfont,
- Tcl_DStringValue(&itemTextDString),
- Tcl_DStringLength(&itemTextDString),
- leftEdge + menuTextLeadingEdgeMargin + textXOffset,
- baseline + textYOffset);
- Tcl_DStringFree(&itemTextDString);
- }
- if (mePtr->state == ENTRY_DISABLED) {
- if (menuPtr->disabledFgPtr == NULL) {
- /* XFillRectangle(menuPtr->display, d, menuPtr->disabledGC, x, y,
- width, height); */
- } else if ((mePtr->image != NULL)
- && (menuPtr->disabledImageGC != None)) {
- XFillRectangle(menuPtr->display, d, menuPtr->disabledImageGC,
- leftEdge + imageXOffset,
- y + (mePtr->height - imageHeight)/2 + imageYOffset,
- imageWidth, imageHeight);
- }
- }
- }
- /*
- *----------------------------------------------------------------------
- *
- * DrawMenuEntryBackground --
- *
- * This procedure draws the background part of a menu entry.
- * Under Appearance, we only draw the background if the entry's
- * border is set, we DO NOT inherit it from the menu...
- *
- * Results:
- * None.
- *
- * Side effects:
- * Commands are output to X to display the menu in its
- * current mode.
- *
- *----------------------------------------------------------------------
- */
- void
- DrawMenuEntryBackground(
- TkMenu *menuPtr, /* The menu we are drawing. */
- TkMenuEntry *mePtr, /* The entry we are drawing. */
- Drawable d, /* What we are drawing into */
- Tk_3DBorder activeBorder, /* Border for active items */
- Tk_3DBorder bgBorder, /* Border for the background */
- int x, /* left edge */
- int y, /* top edge */
- int width, /* width of rectangle to draw */
- int height) /* height of rectangle to draw */
- {
- if ((menuPtr->menuType == TEAROFF_MENU)
- || ((mePtr->state == ENTRY_ACTIVE)
- && (mePtr->activeBorderPtr != None))
- || ((mePtr->state != ENTRY_ACTIVE) && (mePtr->borderPtr != None))) {
- if (mePtr->state == ENTRY_ACTIVE) {
- bgBorder = activeBorder;
- }
- Tk_Fill3DRectangle(menuPtr->tkwin, d, bgBorder,
- x, y, width, height, 0, TK_RELIEF_FLAT);
- }
- }
- /*
- *----------------------------------------------------------------------
- *
- * GetMenuLabelGeometry --
- *
- * Figures out the size of the label portion of a menu item.
- *
- * Results:
- * widthPtr and heightPtr are filled in with the correct geometry
- * information.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
- void
- GetMenuLabelGeometry(
- TkMenuEntry *mePtr, /* The entry we are computing */
- Tk_Font tkfont, /* The precalculated font */
- const Tk_FontMetrics *fmPtr,/* The precalculated metrics */
- int *widthPtr, /* The resulting width of the label portion */
- int *heightPtr) /* The resulting height of the label portion */
- {
- TkMenu *menuPtr = mePtr->menuPtr;
- int haveImage = 0, tornOff = (menuPtr->menuType == TEAROFF_MENU);
- #ifdef USE_TK_MDEF
- const int useMDEF = ((MacMenu *) menuPtr->platformData)->useMDEF;
- #endif
- if (mePtr->image != NULL && (useMDEF || tornOff)) {
- Tk_SizeOfImage(mePtr->image, widthPtr, heightPtr);
- haveImage = 1;
- } else if (mePtr->bitmapPtr != NULL && (useMDEF || tornOff)) {
- Pixmap bitmap = Tk_GetBitmapFromObj(menuPtr->tkwin, mePtr->bitmapPtr);
- Tk_SizeOfBitmap(menuPtr->display, bitmap, widthPtr, heightPtr);
- haveImage = 1;
- }
- if (!haveImage || (mePtr->compound != COMPOUND_NONE)) {
- int textWidth = 0, textHeight = fmPtr->linespace;
- if (mePtr->labelPtr != NULL) {
- Tcl_DString itemTextDString;
- GetEntryText(mePtr, &itemTextDString);
- textWidth = Tk_TextWidth(tkfont,
- Tcl_DStringValue(&itemTextDString),
- Tcl_DStringLength(&itemTextDString)) +
- menuTextLeadingEdgeMargin + menuTextTrailingEdgeMargin;
- Tcl_DStringFree(&itemTextDString);
- if (haveImage && (mePtr->compound != COMPOUND_NONE)) {
- switch ((enum compound) mePtr->compound) {
- int margin;
- case COMPOUND_TOP:
- case COMPOUND_BOTTOM:
- if (textWidth > *widthPtr) {
- *widthPtr = textWidth;
- }
- *heightPtr += textHeight + 2;
- break;
- case COMPOUND_LEFT:
- margin = *widthPtr + 2;
- if (margin > menuTextLeadingEdgeMargin) {
- margin = menuTextLeadingEdgeMargin;
- }
- *widthPtr += textWidth + 2 - margin;
- if (textHeight > *heightPtr) {
- *heightPtr = textHeight;
- }
- break;
- case COMPOUND_RIGHT:
- margin = menuTextTrailingEdgeMargin;
- *widthPtr += textWidth + 2 - margin;
- if (textHeight > *heightPtr) {
- *heightPtr = textHeight;
- }
- break;
- case COMPOUND_CENTER:
- if (textWidth > *widthPtr) {
- *widthPtr = textWidth;
- }
- if (textHeight > *heightPtr) {
- *heightPtr = textHeight;
- }
- break;
- case COMPOUND_NONE:
- /*
- * Never reached.
- */
- break;
- }
- goto labelGeomDone;
- }
- }
- *widthPtr = textWidth;
- *heightPtr = textHeight;
- }
- labelGeomDone:
- *heightPtr += menuItemExtraHeight;
- *widthPtr += menuItemExtraWidth;
- }
- /*
- *----------------------------------------------------------------------
- *
- * TkMacOSXGenerateParentMenuSelectEvent --
- *
- * Respond to a hierarchical menu being opened.
- *
- * Results:
- * True if event(s) are generated - false otherwise.
- *
- * Side effects:
- * Places a virtual event on the event queue.
- *
- *----------------------------------------------------------------------
- */
- int
- TkMacOSXGenerateParentMenuSelectEvent(
- MenuRef menu)
- {
- TkMenu *menuPtr = MenuPtrForMenuRef(menu);
- if (menuPtr) {
- TkMenuEntry *parentEntryPtr = GetParentMenuEntry(menuPtr);
- if (parentEntryPtr && (menuPtr = parentEntryPtr->menuPtr)) {
- TkActivateMenuEntry(menuPtr, parentEntryPtr->index);
- MenuSelectEvent(menuPtr);
- Tcl_ServiceAll();
- return true;
- }
- }
- return false;
- }
- /*
- *----------------------------------------------------------------------
- *
- * TkMacOSXGenerateMenuSelectEvent --
- *
- * Respond to a menu item being selected.
- *
- * Results:
- * True if event(s) are generated - false otherwise.
- *
- * Side effects:
- * Places a virtual event on the event queue.
- *
- *----------------------------------------------------------------------
- */
- int
- TkMacOSXGenerateMenuSelectEvent(
- MenuRef menu,
- MenuItemIndex index)
- {
- TkMenu *menuPtr = MenuPtrForMenuRef(menu);
- int item = index - 1;
- if (menuPtr) {
- if (item < 0 || item >= menuPtr->numEntries ||
- (menuPtr->entries[item])->state == ENTRY_DISABLED) {
- TkActivateMenuEntry(menuPtr, -1);
- } else {
- TkActivateMenuEntry(menuPtr, item);
- MenuSelectEvent(menuPtr);
- Tcl_ServiceAll();
- return true;
- }
- }
- return false;
- }
- /*
- *----------------------------------------------------------------------
- *
- * MenuSelectEvent --
- *
- * Generates a "MenuSelect" virtual event. This can be used to
- * do context-sensitive menu help.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Places a virtual event on the event queue.
- *
- *----------------------------------------------------------------------
- */
- void
- MenuSelectEvent(
- TkMenu *menuPtr) /* the menu we have selected. */
- {
- XVirtualEvent event;
- bzero(&event, sizeof(XVirtualEvent));
- event.type = VirtualEvent;
- event.serial = menuPtr->display->request;
- event.send_event = false;
- event.display = menuPtr->display;
- Tk_MakeWindowExist(menuPtr->tkwin);
- event.event = Tk_WindowId(menuPtr->tkwin);
- event.root = XRootWindow(menuPtr->display, 0);
- event.subwindow = None;
- event.time = TkpGetMS();
- XQueryPointer(NULL, None, NULL, NULL, &event.x_root, &event.y_root, NULL,
- NULL, &event.state);
- event.same_screen = true;
- event.name = Tk_GetUid("MenuSelect");
- Tk_QueueWindowEvent((XEvent *) &event, TCL_QUEUE_TAIL);
- }
- /*
- *----------------------------------------------------------------------
- *
- * TkMacOSXClearActiveMenu --
- *
- * Clears Tk's active entry for the given MenuRef.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Generates <<MenuSelect>> virtual events.
- *
- *----------------------------------------------------------------------
- */
- void
- TkMacOSXClearActiveMenu(
- MenuRef menu)
- {
- TkMenu *menuPtr = MenuPtrForMenuRef(menu);
- if (menuPtr) {
- RecursivelyClearActiveMenu(menuPtr);
- }
- }
- /*
- *----------------------------------------------------------------------
- *
- * RecursivelyClearActiveMenu --
- *
- * Recursively clears the active entry in the menu's cascade hierarchy.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Generates <<MenuSelect>> virtual events.
- *
- *----------------------------------------------------------------------
- */
- void
- RecursivelyClearActiveMenu(
- TkMenu *menuPtr) /* The menu to reset. */
- {
- int i;
- TkMenuEntry *mePtr;
- TkActivateMenuEntry(menuPtr, -1);
- for (i = 0; i < menuPtr->numEntries; i++) {
- mePtr = menuPtr->entries[i];
- if (mePtr->type == CASCADE_ENTRY) {
- if ((mePtr->childMenuRefPtr != NULL)
- && (mePtr->childMenuRefPtr->menuPtr != NULL)) {
- RecursivelyClearActiveMenu(mePtr->childMenuRefPtr->menuPtr);
- }
- }
- }
- }
- /*
- *----------------------------------------------------------------------
- *
- * TkMacOSXClearMenubarActive --
- *
- * Recursively clears the active entry in the current menubar hierarchy.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Generates <<MenuSelect>> virtual events.
- *
- *----------------------------------------------------------------------
- */
- void
- TkMacOSXClearMenubarActive(void)
- {
- TkMenuReferences *menuBarRefPtr;
- if (currentMenuBarName != NULL) {
- menuBarRefPtr = TkFindMenuReferences(currentMenuBarInterp,
- currentMenuBarName);
- if ((menuBarRefPtr != NULL) && (menuBarRefPtr->menuPtr != NULL)) {
- TkMenu *menuPtr;
- for (menuPtr = menuBarRefPtr->menuPtr->masterMenuPtr;
- menuPtr != NULL; menuPtr = menuPtr->nextInstancePtr) {
- if (menuPtr->menuType == MENUBAR) {
- RecursivelyClearActiveMenu(menuPtr);
- }
- }
- }
- }
- }
- /*
- *----------------------------------------------------------------------
- *
- * TkpMenuNotifyToplevelCreate --
- *
- * This routine reconfigures the menu and the clones indicated by
- * menuName becuase a toplevel has been created and any system
- * menus need to be created. Only applicable to Windows.
- *
- * Results:
- * None.
- *
- * Side effects:
- * An idle handler is set up to do the reconfiguration.
- *
- *----------------------------------------------------------------------
- */
- void
- TkpMenuNotifyToplevelCreate(
- Tcl_Interp *interp, /* The interp the menu lives in. */
- char *menuName) /* The name of the menu to reconfigure. */
- {
- /*
- * Nothing to do.
- */
- }
- /*
- *----------------------------------------------------------------------
- *
- * TkpMenuInit --
- *
- * Initializes Mac-specific menu data.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Allocates a hash table.
- *
- *----------------------------------------------------------------------
- */
- void
- TkpMenuInit(void)
- {
- MenuSymbol *ms = menuSymbols;
- CFStringRef cfStr;
- lastMenuID = 256;
- Tcl_InitHashTable(&commandTable, TCL_ONE_WORD_KEYS);
- currentMenuBarOwner = NULL;
- currentAppleMenuID = 0;
- currentHelpMenuID = 0;
- currentMenuBarInterp = NULL;
- currentMenuBarName = NULL;
- windowListPtr = NULL;
- #ifdef USE_TK_MDEF
- tkThemeMenuItemDrawingUPP
- = NewMenuItemDrawingUPP(ThemeMenuItemDrawingProc);
- useMDEFVar = Tcl_NewStringObj("::tk::mac::useCustomMDEF", -1);
- macMDEFDrawable.winPtr = NULL;
- macMDEFDrawable.xOff = 0;
- macMDEFDrawable.yOff = 0;
- macMDEFDrawable.visRgn = NULL;
- macMDEFDrawable.aboveVisRgn = NULL;
- macMDEFDrawable.drawRect = CGRectNull;
- macMDEFDrawable.referenceCount = 0;
- macMDEFDrawable.toplevel = NULL;
- macMDEFDrawable.flags = 0;
- macMDEFDrawable.grafPtr = NULL;
- macMDEFDrawable.context = NULL;
- macMDEFDrawable.size = CGSizeZero;
- #endif
- ChkErr(GetThemeMetric, kThemeMetricMenuMarkColumnWidth,
- &menuMarkColumnWidth);
- ChkErr(GetThemeMetric, kThemeMetricMenuMarkIndent, &menuMarkIndent);
- ChkErr(GetThemeMetric, kThemeMetricMenuTextLeadingEdgeMargin,
- &menuTextLeadingEdgeMargin);
- ChkErr(GetThemeMetric, kThemeMetricMenuTextTrailingEdgeMargin,
- &menuTextTrailingEdgeMargin);
- ChkErr(GetThemeMenuItemExtra, kThemeMenuItemPlain, &menuItemExtraHeight,
- &menuItemExtraWidth);
- ChkErr(GetThemeMenuSeparatorHeight, &menuSeparatorHeight);
- while (ms->unicode) {
- ms->utfLen = Tcl_UniCharToUtf(ms->unicode, ms->utf);
- ms->utf[ms->utfLen] = 0;
- cfStr = CFStringCreateWithCharacters(NULL, &ms->unicode, 1);
- if (cfStr) {
- ms->width = MeasureThemeText(cfStr, kThemeMenuItemCmdKeyFont);
- CFRelease(cfStr);
- }
- ms++;
- }
- }
- /*
- *----------------------------------------------------------------------
- *
- * TkpMenuThreadInit --
- *
- * Does platform-specific initialization of thread-specific
- * menu state.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
- void
- TkpMenuThreadInit(void)
- {
- /*
- * Nothing to do.
- */
- }
- /*
- *----------------------------------------------------------------------
- *
- * TkpPreprocessMacMenu --
- *
- * Handle preprocessing of menubar if it exists.
- *
- * Results:
- * None.
- *
- * Side effects:
- * All post commands for the current menubar get executed.
- *
- *----------------------------------------------------------------------
- */
- void
- TkMacOSXPreprocessMenu(void)
- {
- if ((currentMenuBarName != NULL) && (currentMenuBarInterp != NULL)) {
- TkMenuReferences *mbRefPtr =
- TkFindMenuReferences(currentMenuBarInterp,currentMenuBarName);
- if ((mbRefPtr != NULL) && (mbRefPtr->menuPtr != NULL)) {
- int code;
- Tcl_Preserve((ClientData) currentMenuBarInterp);
- code = TkPreprocessMenu(mbRefPtr->menuPtr->masterMenuPtr);
- if ((code != TCL_OK) && (code != TCL_CONTINUE)
- && (code != TCL_BREAK)) {
- Tcl_AddErrorInfo(currentMenuBarInterp,
- "n (menu preprocess)");
- Tcl_BackgroundError(currentMenuBarInterp);
- }
- Tcl_Release((ClientData) currentMenuBarInterp);
- }
- }
- }
- #ifdef USE_TK_MDEF
- #pragma mark MDEF
- /*
- *----------------------------------------------------------------------
- *
- * MenuDefProc --
- *
- * This routine is the MDEF handler for Tk. It receives all messages
- * for the menu and dispatches them.
- *
- * Results:
- * None.
- *
- * Side effects:
- * This routine causes menus to be drawn and will certainly allocate
- * memory as a result. Also, the menu can scroll up and down, and
- * various other interface actions can take place.
- *
- *----------------------------------------------------------------------
- */
- void
- MenuDefProc(
- SInt16 message, /* What action are we taking? */
- MenuRef menu, /* The menu we are working with */
- Rect *menuRectPtr, /* A pointer to the rect for the
- * whole menu. */
- Point hitPt, /* Where the mouse was clicked for
- * the appropriate messages. */
- SInt16 *whichItem) /* Output result. Which item was
- * hit by the user? */
- {
- TkMenu *menuPtr;
- Tcl_HashEntry *commandEntryPtr;
- MenuID menuID;
- menuID = GetMenuID(menu);
- commandEntryPtr = Tcl_FindHashEntry(&commandTable, (char*)(intptr_t)menuID);
- if (commandEntryPtr) {
- menuPtr = (TkMenu *) Tcl_GetHashValue(commandEntryPtr);
- } else {
- menuPtr = NULL;
- }
- switch (message) {
- case kMenuInitMsg:
- *whichItem = noErr;
- break;
- case kMenuDisposeMsg:
- break;
- case kMenuHiliteItemMsg:
- HandleMenuHiliteMsg(menu, menuRectPtr, hitPt, whichItem, menuPtr);
- break;
- case kMenuCalcItemMsg:
- HandleMenuCalcItemMsg(menu, menuRectPtr, hitPt, whichItem,
- menuPtr);
- break;
- case kMenuDrawItemsMsg:
- #ifdef TK_MAC_DEBUG_MENUS
- TkMacOSXDbgMsg("MDEF: DrawItemsMsg");
- #endif
- /*
- * We do nothing here, because we don't support the Menu Managers
- * dynamic item groups
- */
- break;
- case kMenuThemeSavvyMsg:
- *whichItem = kThemeSavvyMenuResponse;
- break;
- case kMenuSizeMsg:
- #ifdef TK_MAC_DEBUG_MENUS
- TkMacOSXDbgMsg("MDEF: SizeMsg %d, %d", hitPt.h, hitPt.v);
- #endif
- SetMenuWidth(menu, hitPt.h < menuPtr->totalWidth ? hitPt.h :
- menuPtr->totalWidth);
- SetMenuHeight(menu, hitPt.v < menuPtr->totalHeight ? hitPt.v :
- menuPtr->totalHeight);
- break;
- case kMenuDrawMsg:
- HandleMenuDrawMsg(menu, menuRectPtr, hitPt, whichItem, menuPtr);
- break;
- case kMenuFindItemMsg:
- HandleMenuFindItemMsg(menu, menuRectPtr, hitPt, whichItem,
- menuPtr);
- break;
- case kMenuPopUpMsg:
- HandleMenuPopUpMsg(menu, menuRectPtr, hitPt, whichItem, menuPtr);
- break;
- }
- }
- /*
- *----------------------------------------------------------------------
- *
- * HandleMenuHiliteMsg --
- *
- * Handles the MenuDefProc's hilite message.
- *
- * Results:
- * A menu entry is drawn
- *
- * Side effects:
- * None
- *
- *----------------------------------------------------------------------
- */
- void
- HandleMenuHiliteMsg(
- MenuRef menu,
- Rect *menuRectPtr,
- Point hitPt,
- SInt16 *whichItem,
- TkMenu *menuPtr)
- {
- OSStatus err;
- Tk_Font tkfont;
- Tk_FontMetrics fontMetrics;
- MDEFHiliteItemData *hidPtr = (MDEFHiliteItemData *)whichItem;
- int oldItem = hidPtr->previousItem - 1;
- int newItem = hidPtr->newItem - 1;
- MenuTrackingData mtd, *mtdPtr = &mtd;
- #ifdef TK_MAC_DEBUG_MENUS
- TkMacOSXDbgMsg("MDEF: HiliteMsg %d -> %d", hidPtr->previousItem,
- hidPtr->newItem);
- #endif
- GetPort(&macMDEFDrawable.grafPtr);
- macMDEFDrawable.context = (CGContextRef) hidPtr->context;
- err = ChkErr(GetMenuTrackingData, menu, mtdPtr);
- if (err != noErr) {
- return;
- }
- tkfont = Tk_GetFontFromObj(menuPtr->tkwin, menuPtr->fontPtr);
- Tk_GetFontMetrics(tkfont, &fontMetrics);
- if (oldItem >= 0) {
- AppearanceEntryDrawWrapper(menuPtr->entries[oldItem], menuRectPtr,
- mtdPtr, (Drawable) &macMDEFDrawable, &fontMetrics, tkfont, 1);
- }
- if (newItem >= 0) {
- AppearanceEntryDrawWrapper(menuPtr->entries[newItem], menuRectPtr,
- mtdPtr, (Drawable) &macMDEFDrawable, &fontMetrics, tkfont, 0);
- }
- }
- /*
- *----------------------------------------------------------------------
- *
- * HandleMenuDrawMsg --
- *
- * Handles the MenuDefProc's draw message.
- *
- * Results:
- * A menu entry is drawn
- *
- * Side effects:
- * None
- *
- *----------------------------------------------------------------------
- */
- void
- HandleMenuDrawMsg(
- MenuRef menu,
- Rect *menuRectPtr,
- Point hitPt,
- SInt16 *whichItem,
- TkMenu *menuPtr)
- {
- Tk_Font menuFont;
- Tk_FontMetrics fontMetrics;
- TkMenuEntry *mePtr;
- int i;
- Rect menuClipRect, bounds;
- MDEFDrawData *ddPtr = (MDEFDrawData*)whichItem;
- MenuTrackingData *mtdPtr = &(ddPtr->trackingData);
- TkWindow *winPtr = (TkWindow*)menuPtr->tkwin;
- GetPort(&macMDEFDrawable.grafPtr);
- GetPortBounds(macMDEFDrawable.grafPtr, &bounds);
- macMDEFDrawable.context = (CGContextRef) ddPtr->context;
- #ifdef TK_MAC_DEBUG_MENUS
- TkMacOSXDbgMsg("MDEF: DrawMsg %d - %d; %d - %d", menuRectPtr->top,
- menuRectPtr->bottom, bounds.top, bounds.bottom);
- #endif
- winPtr->changes.x = menuRectPtr->left;
- winPtr->changes.y = menuRectPtr->top;
- winPtr->changes.width = menuRectPtr->right - menuRectPtr->left;
- winPtr->changes.height = menuRectPtr->bottom - menuRectPtr->top;
- TkpClipDrawableToRect(menuPtr->display, (Drawable) &macMDEFDrawable,
- 0, 0, -1, -1);
- #if 0
- if (menuPtr->menuRefPtr->topLevelListPtr != NULL) {
- menuType = kThemeMenuTypePullDown;
- } else if (menuPtr->menuRefPtr->parentEntryPtr != NULL) {
- menuType = kThemeMenuTypeHierarchical;
- } else {
- menuType = kThemeMenuTypePopUp;
- }
- #endif
- DrawMenuBackground(menuPtr, menuRectPtr, (Drawable) &macMDEFDrawable);
- menuFont = Tk_GetFontFromObj(menuPtr->tkwin, menuPtr->fontPtr);
- Tk_GetFontMetrics(menuFont, &fontMetrics);
- menuClipRect = *menuRectPtr;
- mtdPtr->virtualMenuBottom = mtdPtr->virtualMenuTop + menuPtr->totalHeight;
- /*
- * Next, figure out scrolling information.
- */
- if ((menuRectPtr->bottom - menuRectPtr->top) < menuPtr->totalHeight) {
- short arrowHeight = fontMetrics.linespace + 1;
- Rect arrowRect, eraseRect;
- ThemeMenuState menuState = IsMenuItemEnabled(menu, 0) ?
- kThemeMenuActive : kThemeMenuDisabled;
- if (mtdPtr->virtualMenuTop < menuRectPtr->top) {
- arrowRect = bounds;
- /*arrowRect.top += 1;*/
- arrowRect.bottom = arrowRect.top + arrowHeight;
- eraseRect = arrowRect;
- eraseRect.top = menuRectPtr->top;
- menuClipRect.top = arrowRect.bottom;
- ChkErr(EraseMenuBackground, menu, &eraseRect,
- macMDEFDrawable.context);
- ChkErr(DrawThemeMenuItem, menuRectPtr, &arrowRect,
- mtdPtr->virtualMenuTop, mtdPtr->virtualMenuBottom,
- menuState, kThemeMenuItemScrollUpArrow, NULL, 0);
- #ifdef TK_MAC_DEBUG_MENUS
- TkMacOSXDbgMsg("upArrow: %d - %d, %d - %d", arrowRect.top,
- arrowRect.bottom, arrowRect.left, arrowRect.right);
- #endif
- }
- if (mtdPtr->virtualMenuBottom > menuRectPtr->bottom) {
- arrowRect = bounds;
- arrowRect.bottom -= 1;
- arrowRect.top = arrowRect.bottom - arrowHeight;
- eraseRect = arrowRect;
- eraseRect.bottom = menuRectPtr->bottom;
- menuClipRect.bottom = arrowRect.top;
- ChkErr(EraseMenuBackground, menu, &eraseRect,
- macMDEFDrawable.context);
- ChkErr(DrawThemeMenuItem, menuRectPtr, &arrowRect,
- mtdPtr->virtualMenuTop, mtdPtr->virtualMenuBottom,
- menuState, kThemeMenuItemScrollDownArrow, NULL, 0);
- #ifdef TK_MAC_DEBUG_MENUS
- TkMacOSXDbgMsg("downArrow: %d - %d, %d - %d", arrowRect.top,
- arrowRect.bottom, arrowRect.left, arrowRect.right);
- #endif
- }
- TkpClipDrawableToRect(menuPtr->display, (Drawable) &macMDEFDrawable,
- menuClipRect.left, menuClipRect.top, menuClipRect.right -
- menuClipRect.left, menuClipRect.bottom - menuClipRect.top);
- }
- /*
- * Now, actually draw the menu. Don't draw entries that
- * are higher than the top arrow, and don't draw entries
- * that are lower than the bottom.
- */
- for (i = 0; i < menuPtr->numEntries; i++) {
- mePtr = menuPtr->entries[i];
- if (mtdPtr->virtualMenuTop + mePtr->y + mePtr->height <
- menuClipRect.top || mtdPtr->virtualMenuTop + mePtr->y >
- menuClipRect.bottom) {
- continue;
- }
- AppearanceEntryDrawWrapper(mePtr, menuRectPtr, mtdPtr,
- (Drawable) &macMDEFDrawable, &fontMetrics, menuFont, 0);
- }
- MDEFScrollFlag = 1;
- }
- /*
- *----------------------------------------------------------------------
- *
- * HandleMenuFindItemMsg --
- *
- * Handles the MenuDefProc's FindItems message. We have to
- * respond by filling in the itemSelected, itemUnderMouse and
- * itemRect fields. This is also the time to scroll the menu if
- * it is too long to fit on the screen.
- *
- * Results:
- * The Menu system is informed of the selected item & the item
- * under the mouse.
- *
- * Side effects:
- * The menu might get scrolled.
- *
- *----------------------------------------------------------------------
- */
- void
- HandleMenuFindItemMsg(
- MenuRef menu,
- Rect *menuRectPtr,
- Point hitPt,
- SInt16 *whichItem,
- TkMenu *menuPtr)
- {
- Tk_Font menuFont;
- Tk_FontMetrics fontMetrics;
- TkMenuEntry *mePtr;
- int i, newItem = -1, itemUnderMouse = -1;
- Rect itemRect = {0, 0, 0, 0}, menuClipRect, bounds;
- int hasTopScroll, hasBottomScroll;
- MDEFFindItemData *fiPtr = (MDEFFindItemData *)whichItem;
- MenuTrackingData *mtdPtr = &(fiPtr->trackingData), topMtd;
- enum {
- DONT_SCROLL, DOWN_SCROLL, UP_SCROLL
- } scrollDirection;
- short arrowHeight;
- #ifdef TK_MAC_DEBUG_MENUS
- static Point lastHitPt = {0, 0};
- if (hitPt.h != lastHitPt.h || hitPt.v != lastHitPt.v) {
- lastHitPt = hitPt;
- TkMacOSXDbgMsg("MDEF: FindItemMsg: %d, %d", hitPt.h, hitPt.v);
- }
- #endif
- GetPort(&macMDEFDrawable.grafPtr);
- GetPortBounds(macMDEFDrawable.grafPtr, &bounds);
- macMDEFDrawable.context = (CGContextRef) fiPtr->context;
- /*
- * Now we need to take care of scrolling the menu.
- */
- menuFont = Tk_GetFontFromObj(menuPtr->tkwin, menuPtr->fontPtr);
- Tk_GetFontMetrics(menuFont, &fontMetrics);
- arrowHeight = fontMetrics.linespace + 1;
- menuClipRect = *menuRectPtr;
- hasTopScroll = mtdPtr->virtualMenuTop < menuRectPtr->top;
- hasBottomScroll = mtdPtr->virtualMenuBottom > menuRectPtr->bottom;
- scrollDirection = DONT_SCROLL;
- if (hasTopScroll) {
- menuClipRect.top = bounds.top + arrowHeight;
- if (hitPt.v < menuClipRect.top) {
- newItem = -1;
- scrollDirection = DOWN_SCROLL;
- }
- }
- if (hasBottomScroll) {
- menuClipRect.bottom = bounds.bottom - 1 - arrowHeight;
- if (hitPt.v > menuClipRect.bottom) {
- newItem = -1;
- scrollDirection = UP_SCROLL;
- }
- }
- if (MDEFScrollFlag) {
- scrollDirection = DONT_SCROLL;
- MDEFScrollFlag = 0;
- }
- /*
- * Don't scroll if there are other menus open above us
- */
- ChkErr(GetMenuTrackingData, NULL, &topMtd);
- if (menu != topMtd.menu) {
- scrollDirection = DONT_SCROLL;
- }
- if (scrollDirection == DONT_SCROLL) {
- /*
- * Find out which item was hit. If it is the same as the old item,
- * we don't need to do anything.
- */
- if (PtInRect(hitPt, menuRectPtr)) {
- for (i = 0; i < menuPtr->numEntries; i++) {
- mePtr = menuPtr->entries[i];
- itemRect.left = menuRectPtr->left + mePtr->x;
- itemRect.top = mtdPtr->virtualMenuTop + mePtr->y;
- itemRect.right = mePtr->entryFlags & ENTRY_LAST_COLUMN ?
- menuRectPtr->right : itemRect.left + mePtr->width;
- itemRect.bottom = itemRect.top + mePtr->height;
- if (PtInRect(hitPt, &itemRect)) {
- if ((mePtr->type == SEPARATOR_ENTRY)
- || (mePtr->state == ENTRY_DISABLED)) {
- newItem = -1;
- itemUnderMouse = i;
- } else {
- TkMenuEntry *parentEntryPtr =
- GetParentMenuEntry(menuPtr);
- if (parentEntryPtr &&
- parentEntryPtr->state == ENTRY_DISABLED) {
- newItem = -1;
- itemUnderMouse = i;
- } else {
- newItem = i;
- itemUnderMouse = i;
- }
- }
- break;
- }
- }
- }
- } else {
- short scrollAmt;
- unsigned long scrollDelay;
- Rect arrowRect, eraseRect, scrolledMenuClipRect;
- ThemeMenuState menuState = IsMenuItemEnabled(menu, 0) ?
- kThemeMenuActive : kThemeMenuDisabled;
- int oldItem = mtdPtr->itemSelected - 1;
- short d;
- TkpClipDrawableToRect(menuPtr->display, (Drawable) &macMDEFDrawable,
- 0, 0, -1, -1);
- scrollAmt = fontMetrics.linespace + menuItemExtraHeight;
- if (scrollDirection == UP_SCROLL) {
- scrollAmt = -scrollAmt;
- d = hitPt.v - bounds.bottom;
- } else {
- d = bounds.top - hitPt.v;
- }
- scrollDelay = (d >= scrollAmt/2) ? 1 : 10;
- menuClipRect = *menuRectPtr;
- if (mtdPtr->virtualMenuTop + scrollAmt < menuRectPtr->top) {
- arrowRect = bounds;
- /*arrowRect.top += 1;*/
- arrowRect.bottom = arrowRect.top + arrowHeight;
- eraseRect = arrowRect;
- eraseRect.top = menuRectPtr->top;
- menuClipRect.top = arrowRect.bottom;
- if (!hasTopScroll) {
- ChkErr(EraseMenuBackground, menu, &eraseRect,
- macMDEFDrawable.context);
- ChkErr(DrawThemeMenuItem, menuRectPtr, &arrowRect,
- mtdPtr->virtualMenuTop + scrollAmt,
- mtdPtr->virtualMenuBottom + scrollAmt,
- menuState, kThemeMenuItemScrollUpArrow, NULL, 0);
- #ifdef TK_MAC_DEBUG_MENUS
- TkMacOSXDbgMsg("upArrow: %d - %d, %d - %d", arrowRect.top,
- arrowRect.bottom, arrowRect.left, arrowRect.right);
- #endif
- }
- }
- if (mtdPtr->virtualMenuBottom + scrollAmt > menuRectPtr->bottom) {
- arrowRect = bounds;
- arrowRect.bottom -= 1;
- arrowRect.top = arrowRect.bottom - arrowHeight;
- eraseRect = arrowRect;
- eraseRect.bottom = menuRectPtr->bottom;
- menuClipRect.bottom = arrowRect.top;
- if (!hasBottomScroll) {
- ChkErr(EraseMenuBackground, menu, &eraseRect,
- macMDEFDrawable.context);
- ChkErr(DrawThemeMenuItem, menuRectPtr, &arrowRect,
- mtdPtr->virtualMenuTop + scrollAmt,
- mtdPtr->virtualMenuBottom + scrollAmt,
- menuState, kThemeMenuItemScrollDownArrow, NULL, 0);
- #ifdef TK_MAC_DEBUG_MENUS
- TkMacOSXDbgMsg("downArrow: %d - %d, %d - %d", arrowRect.top,
- arrowRect.bottom, arrowRect.left, arrowRect.right);
- #endif
- }
- }
- TkpClipDrawableToRect(menuPtr->display, (Drawable) &macMDEFDrawable,
- menuClipRect.left, menuClipRect.top, menuClipRect.right -
- menuClipRect.left, menuClipRect.bottom - menuClipRect.top);
- TkActivateMenuEntry(menuPtr, -1);
- if (oldItem >= 0) {
- AppearanceEntryDrawWrapper(menuPtr->entries[oldItem], menuRectPtr,
- mtdPtr, (Drawable) &macMDEFDrawable, &fontMetrics,
- menuFont, 1);
- }
- ChkErr(ScrollMenuImage, menu, &menuClipRect, 0, scrollAmt,
- macMDEFDrawable.context);
- mtdPtr->virtualMenuTop += scrollAmt;
- mtdPtr->virtualMenuBottom += scrollAmt;
- scrolledMenuClipRect = menuClipRect;
- OffsetRect(&scrolledMenuClipRect, 0, scrollAmt);
- menuClipRect = bounds;
- if (mtdPtr->virtualMenuTop < menuRectPtr->top) {
- menuClipRect.top += arrowHeight;
- }
- if (mtdPtr->virtualMenuBottom > menuRectPtr->bottom) {
- menuClipRect.bottom -= arrowHeight;
- }
- TkpClipDrawableToRect(menuPtr->display, (Drawable) &macMDEFDrawable,
- menuClipRect.left, menuClipRect.top, menuClipRect.right -
- menuClipRect.left, menuClipRect.bottom - menuClipRect.top);
- if (scrolledMenuClipRect.bottom < menuClipRect.bottom) {
- menuClipRect.top = scrolledMenuClipRect.bottom;
- } else if (scrolledMenuClipRect.top < menuClipRect.top) {
- menuClipRect.bottom = scrolledMenuClipRect.top;
- }
- for (i = 0; i < menuPtr->numEntries; i++) {
- mePtr = menuPtr->entries[i];
- if (mtdPtr->virtualMenuTop + mePtr->y + mePtr->height <
- menuClipRect.top || mtdPtr->virtualMenuTop + mePtr->y >
- menuClipRect.bottom) {
- continue;
- }
- #ifdef TK_MAC_DEBUG_MENUS
- TkMacOSXDbgMsg("Drawing item %i", i);
- #endif
- AppearanceEntryDrawWrapper(mePtr, menuRectPtr, mtdPtr,
- (Drawable) &macMDEFDrawable, &fontMetrics, menuFont, 1);
- }
- Delay(scrollDelay, NULL);
- }
- mtdPtr->itemSelected = newItem + 1;
- mtdPtr->itemUnderMouse = itemUnderMouse + 1;
- mtdPtr->itemRect = itemRect;
- }
- /*
- *----------------------------------------------------------------------
- *
- * HandleMenuPopUpMsg --
- *
- * Handles the MenuDefProc's PopUp message. The menu is
- * posted with the selected item at the point given in hitPt.
- *
- * Results:
- * A menu is posted.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
- void
- HandleMenuPopUpMsg(
- MenuRef menu,
- Rect *menuRectPtr,
- Point hitPt,
- SInt16 *whichItem,
- TkMenu *menuPtr)
- {
- int maxMenuHeight;
- int oldItem;
- Rect portRect;
- BitMap screenBits;
- static SInt16 menuBarHeight = 0;
- #ifdef TK_MAC_DEBUG_MENUS
- TkMacOSXDbgMsg("MDEF: PopUpMsg");
- #endif
- if (!menuBarHeight) {
- ChkErr(GetThemeMenuBarHeight, &menuBarHeight);
- }
- GetQDGlobalsScreenBits(&screenBits);
- /*
- * Note that for some oddball reason, h and v are reversed in the
- * point given to us by the MDEF.
- */
- oldItem = *whichItem;
- if (oldItem >= menuPtr->numEntries) {
- oldItem = -1;
- }
- portRect.top = 0;
- portRect.bottom = 1280;
- maxMenuHeight = screenBits.bounds.bottom - screenBits.bounds.top
- - menuBarHeight - SCREEN_MARGIN;
- if (menuPtr->totalHeight > maxMenuHeight) {
- menuRectPtr->top = menuBarHeight;
- } else {
- int delta;
- menuRectPtr->top = hitPt.h;
- if (oldItem >= 0) {
- menuRectPtr->top -= menuPtr->entries[oldItem]->y;
- }
- if (menuRectPtr->top < menuBarHeight) {
- /*
- * Displace downward if the menu would stick off the top of the
- * screen.
- */
- menuRectPtr->top = menuBarHeight + SCREEN_MARGIN;
- } else {
- /*
- * Or upward if the menu sticks off the bottom end...
- */
- delta = menuRectPtr->top + menuPtr->totalHeight - maxMenuHeight;
- if (delta > 0) {
- menuRectPtr->top -= delta;
- }
- }
- }
- menuRectPtr->left = hitPt.v;
- menuRectPtr->right = menuRectPtr->left + menuPtr->totalWidth;
- menuRectPtr->bottom = menuRectPtr->top +
- ((maxMenuHeight < menuPtr->totalHeight)
- ? maxMenuHeight : menuPtr->totalHeight);
- if (menuRectPtr->top == menuBarHeight) {
- *whichItem = hitPt.h;
- } else {
- *whichItem = menuRectPtr->top;
- }
- }
- /*
- *----------------------------------------------------------------------
- *
- * HandleMenuCalcItemMsg --
- *
- * Handles the MenuDefProc's CalcItem message. It is supposed
- * to calculate the Rect of the menu entry in whichItem in the
- * menu, and put that in menuRectPtr. I assume this works, but I
- * have never seen the MenuManager send this message.
- *
- * Results:
- * The Menu Manager is informed of the bounding rect of a
- * menu rect.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
- void
- HandleMenuCalcItemMsg(
- MenuRef menu,
- Rect *menuRectPtr,
- Point hitPt,
- SInt16 *whichItem,
- TkMenu *menuPtr)
- {
- TkMenuEntry *mePtr;
- MenuTrackingData mtd, *mtdPtr = &mtd;
- OSStatus err;
- int virtualTop, item = *whichItem-1;
- err = ChkErr(GetMenuTrackingData, menu, mtdPtr);
- if (err == noErr) {
- virtualTop = mtdPtr->virtualMenuTop;
- } else {
- virtualTop = 0;
- }
- if (item >= 0 && item < menuPtr->numEntries) {
- mePtr = menuPtr->entries[item];
- menuRectPtr->left = mePtr->x;
- menuRectPtr->top = mePtr->y + virtualTop;
- if (mePtr->entryFlags & ENTRY_LAST_COLUMN) {
- menuRectPtr->right = menuPtr->totalWidth;
- } else {
- menuRectPtr->right = mePtr->x + mePtr->width;
- }
- menuRectPtr->bottom = menuRectPtr->top + mePtr->height;
- }
- #ifdef TK_MAC_DEBUG_MENUS
- TkMacOSXDbgMsg("MDEF: CalcItemMsg %d: %d, %d", *whichItem,
- menuRectPtr->left, menuRectPtr->top);
- #endif
- }
- #endif /* USE_TK_MDEF */