static int TextSetup(TextElement *text, Tk_Window tkwin) { const char *string = Tcl_GetString(text->textObj); Tk_Justify justify = TK_JUSTIFY_LEFT; int wrapLength = 0; text->tkfont = Tk_GetFontFromObj(tkwin, text->fontObj); Tk_GetJustifyFromObj(NULL, text->justifyObj, &justify); Tk_GetPixelsFromObj(NULL, tkwin, text->wrapLengthObj, &wrapLength); Tcl_GetBooleanFromObj(NULL, text->embossedObj, &text->embossed); text->textLayout = Tk_ComputeTextLayout( text->tkfont, string, -1/*numChars*/, wrapLength, justify, 0/*flags*/, &text->width, &text->height); return 1; }
void TkpComputeMenubarGeometry( TkMenu *menuPtr) /* Structure describing menu. */ { Tk_Font tkfont, menuFont; Tk_FontMetrics menuMetrics, entryMetrics, *fmPtr; int width, height, i, j, x, y, currentRowHeight, maxWidth; int maxWindowWidth, lastRowBreak, lastEntry; int borderWidth, activeBorderWidth, helpMenuIndex = -1; TkMenuEntry *mePtr; if (menuPtr->tkwin == NULL) { return; } Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->borderWidthPtr, &borderWidth); Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->activeBorderWidthPtr, &activeBorderWidth); maxWidth = 0; if (menuPtr->numEntries == 0) { height = 0; } else { int borderWidth; maxWindowWidth = Tk_Width(menuPtr->tkwin); if (maxWindowWidth == 1) { maxWindowWidth = 0x7ffffff; } currentRowHeight = 0; Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->borderWidthPtr, &borderWidth); x = y = borderWidth; lastRowBreak = 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 measureing and drawing routines. * We will measure the font metrics of the menu once, and if an entry * has a font set, we will measure it as we come to it, and then we * decide which set to give the geometry routines. */ menuFont = Tk_GetFontFromObj(menuPtr->tkwin, menuPtr->fontPtr); Tk_GetFontMetrics(menuFont, &menuMetrics); for (i = 0; i < menuPtr->numEntries; i++) { mePtr = menuPtr->entries[i]; mePtr->entryFlags &= ~ENTRY_LAST_COLUMN; if (mePtr->fontPtr != NULL) { tkfont = Tk_GetFontFromObj(menuPtr->tkwin, mePtr->fontPtr); Tk_GetFontMetrics(tkfont, &entryMetrics); fmPtr = &entryMetrics; } else { tkfont = menuFont; fmPtr = &menuMetrics; } /* * For every entry, we need to check to see whether or not we * wrap. If we do wrap, then we have to adjust all of the previous * entries' height and y position, because when we see them the * first time, we don't know how big its neighbor might be. */ if ((mePtr->type == SEPARATOR_ENTRY) || (mePtr->type == TEAROFF_ENTRY)) { mePtr->height = mePtr->width = 0; } else { GetMenuLabelGeometry(mePtr, tkfont, fmPtr, &width, &height); mePtr->height = height + 2 * activeBorderWidth + 10; mePtr->width = width; GetMenuIndicatorGeometry(menuPtr, mePtr, tkfont, fmPtr, &width, &height); mePtr->indicatorSpace = width; if (width > 0) { mePtr->width += width; } mePtr->width += 2 * activeBorderWidth + 10; } if (mePtr->entryFlags & ENTRY_HELP_MENU) { helpMenuIndex = i; } else if (x + mePtr->width + borderWidth > maxWindowWidth) { if (i == lastRowBreak) { mePtr->y = y; mePtr->x = x; lastRowBreak++; y += mePtr->height; currentRowHeight = 0; } else { x = borderWidth; for (j = lastRowBreak; j < i; j++) { menuPtr->entries[j]->y = y + currentRowHeight - menuPtr->entries[j]->height; menuPtr->entries[j]->x = x; x += menuPtr->entries[j]->width; } lastRowBreak = i; y += currentRowHeight; currentRowHeight = mePtr->height; } if (x > maxWidth) { maxWidth = x; } x = borderWidth; } else { x += mePtr->width; if (mePtr->height > currentRowHeight) { currentRowHeight = mePtr->height; } } } lastEntry = menuPtr->numEntries - 1; if (helpMenuIndex == lastEntry) { lastEntry--; } if ((lastEntry >= 0) && (x + menuPtr->entries[lastEntry]->width + borderWidth > maxWidth)) { maxWidth = x + menuPtr->entries[lastEntry]->width + borderWidth; } x = borderWidth; for (j = lastRowBreak; j < menuPtr->numEntries; j++) { if (j == helpMenuIndex) { continue; } menuPtr->entries[j]->y = y + currentRowHeight - menuPtr->entries[j]->height; menuPtr->entries[j]->x = x; x += menuPtr->entries[j]->width; } if (helpMenuIndex != -1) { mePtr = menuPtr->entries[helpMenuIndex]; if (x + mePtr->width + borderWidth > maxWindowWidth) { y += currentRowHeight; currentRowHeight = mePtr->height; x = borderWidth; } else if (mePtr->height > currentRowHeight) { currentRowHeight = mePtr->height; } mePtr->x = maxWindowWidth - borderWidth - mePtr->width; mePtr->y = y + currentRowHeight - mePtr->height; } height = y + currentRowHeight + borderWidth; } width = Tk_Width(menuPtr->tkwin); /* * 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 (width <= 0) { width = 1; } if (height <= 0) { height = 1; } menuPtr->totalWidth = maxWidth; menuPtr->totalHeight = height; }
void TkpComputeStandardMenuGeometry( TkMenu *menuPtr) /* Structure describing menu. */ { Tk_Font tkfont, menuFont; Tk_FontMetrics menuMetrics, entryMetrics, *fmPtr; int x, y, height, width, indicatorSpace, labelWidth, accelWidth; int windowWidth, windowHeight, accelSpace, i, j, lastColumnBreak = 0; TkMenuEntry *mePtr; int borderWidth, activeBorderWidth; 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 = 0; windowHeight = windowWidth = 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); accelSpace = Tk_TextWidth(menuFont, "M", 1); 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 (accelWidth != 0) { labelWidth += accelSpace; } for (j = lastColumnBreak; j < i; j++) { menuPtr->entries[j]->indicatorSpace = indicatorSpace; menuPtr->entries[j]->labelWidth = labelWidth; menuPtr->entries[j]->width = indicatorSpace + labelWidth + accelWidth + 2 * activeBorderWidth; menuPtr->entries[j]->x = x; menuPtr->entries[j]->entryFlags &= ~ENTRY_LAST_COLUMN; } x += indicatorSpace + labelWidth + accelWidth + 2 * activeBorderWidth; windowWidth = x; indicatorSpace = labelWidth = accelWidth = 0; lastColumnBreak = i; y = borderWidth; } if (mePtr->type == SEPARATOR_ENTRY) { GetMenuSeparatorGeometry(menuPtr, mePtr, tkfont, fmPtr, &width, &height); mePtr->height = height; } else if (mePtr->type == TEAROFF_ENTRY) { GetTearoffEntryGeometry(menuPtr, mePtr, tkfont, fmPtr, &width, &height); mePtr->height = height; labelWidth = width; } 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, &width, &height); mePtr->height = height; if (!mePtr->hideMargin) { width += MENU_MARGIN_WIDTH; } if (width > labelWidth) { labelWidth = width; } GetMenuAccelGeometry(menuPtr, mePtr, tkfont, fmPtr, &width, &height); if (height > mePtr->height) { mePtr->height = height; } if (!mePtr->hideMargin) { width += MENU_MARGIN_WIDTH; } if (width > accelWidth) { accelWidth = width; } GetMenuIndicatorGeometry(menuPtr, mePtr, tkfont, fmPtr, &width, &height); if (height > mePtr->height) { mePtr->height = height; } if (!mePtr->hideMargin) { width += MENU_MARGIN_WIDTH; } if (width > indicatorSpace) { indicatorSpace = width; } mePtr->height += 2 * activeBorderWidth + MENU_DIVIDER_HEIGHT; } mePtr->y = y; y += mePtr->height; if (y > windowHeight) { windowHeight = y; } } if (accelWidth != 0) { labelWidth += accelSpace; } for (j = lastColumnBreak; j < menuPtr->numEntries; j++) { menuPtr->entries[j]->indicatorSpace = indicatorSpace; menuPtr->entries[j]->labelWidth = labelWidth; menuPtr->entries[j]->width = indicatorSpace + labelWidth + accelWidth + 2 * activeBorderWidth; menuPtr->entries[j]->x = x; menuPtr->entries[j]->entryFlags |= ENTRY_LAST_COLUMN; } windowWidth = x + indicatorSpace + labelWidth + accelWidth + 2 * activeBorderWidth + 2 * 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; }
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, indicatorGC; XColor *indicatorColor, *disableColor = NULL; TkMenu *menuPtr = mePtr->menuPtr; Tk_3DBorder bgBorder, activeBorder; const Tk_FontMetrics *fmPtr; Tk_FontMetrics entryMetrics; int padY = (menuPtr->menuType == MENUBAR) ? 3 : 0; int adjustedY = y + padY; int adjustedHeight = height - 2 * padY; /* * Choose the gc for drawing the foreground part of the entry. */ if ((mePtr->state == ENTRY_ACTIVE) && !strictMotif) { gc = mePtr->activeGC; if (gc == NULL) { gc = menuPtr->activeGC; } } else { TkMenuEntry *cascadeEntryPtr; int parentDisabled = 0; for (cascadeEntryPtr = menuPtr->menuRefPtr->parentEntryPtr; cascadeEntryPtr != NULL; cascadeEntryPtr = cascadeEntryPtr->nextCascadePtr) { if (cascadeEntryPtr->namePtr != NULL) { const char *name = Tcl_GetString(cascadeEntryPtr->namePtr); if (strcmp(name, Tk_PathName(menuPtr->tkwin)) == 0) { if (cascadeEntryPtr->state == ENTRY_DISABLED) { parentDisabled = 1; } break; } } } if (((parentDisabled || (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; } if (mePtr->indicatorFgPtr) { indicatorColor = Tk_GetColorFromObj(menuPtr->tkwin, mePtr->indicatorFgPtr); } else { indicatorColor = Tk_GetColorFromObj(menuPtr->tkwin, menuPtr->indicatorFgPtr); } if (menuPtr->disabledFgPtr != NULL) { disableColor = Tk_GetColorFromObj(menuPtr->tkwin, menuPtr->disabledFgPtr); } 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) { if (mePtr->state == ENTRY_ACTIVE) { bgBorder = activeBorder; } DrawMenuEntryIndicator(menuPtr, mePtr, d, bgBorder, indicatorColor, disableColor, tkfont, fmPtr, x, adjustedY, width, adjustedHeight); } } }