1 /* 2 * tkMenu.h -- 3 * 4 * Declarations shared among all of the files that implement menu 5 * widgets. 6 * 7 * Copyright (c) 1996-1998 by Sun Microsystems, Inc. 8 * 9 * See the file "license.terms" for information on usage and redistribution of 10 * this file, and for a DISCLAIMER OF ALL WARRANTIES. 11 */ 12 13 #ifndef _TKMENU 14 #define _TKMENU 15 16 #ifndef _TKINT 17 #include "tkInt.h" 18 #endif 19 20 #ifndef _DEFAULT 21 #include "default.h" 22 #endif 23 24 /* 25 * Dummy types used by the platform menu code. 26 */ 27 28 typedef struct TkMenuPlatformData_ *TkMenuPlatformData; 29 typedef struct TkMenuPlatformEntryData_ *TkMenuPlatformEntryData; 30 31 /* 32 * Legal values for the "compound" field of TkMenuEntry and TkMenuButton 33 * records. 34 */ 35 36 enum compound { 37 COMPOUND_BOTTOM, COMPOUND_CENTER, COMPOUND_LEFT, COMPOUND_NONE, 38 COMPOUND_RIGHT, COMPOUND_TOP 39 }; 40 41 /* 42 * Additional menu entry drawing parameters for Windows platform. 43 * DRAW_MENU_ENTRY_ARROW makes TkpDrawMenuEntry draw the arrow 44 * itself when cascade entry is disabled. 45 * DRAW_MENU_ENTRY_NOUNDERLINE forbids underline when ODS_NOACCEL 46 * is set, thus obeying the system-wide Windows UI setting. 47 */ 48 49 enum drawingParameters { 50 DRAW_MENU_ENTRY_ARROW = (1<<0), 51 DRAW_MENU_ENTRY_NOUNDERLINE = (1<<1) 52 }; 53 54 /* 55 * One of the following data structures is kept for each entry of each menu 56 * managed by this file: 57 */ 58 59 typedef struct TkMenuEntry { 60 int type; /* Type of menu entry; see below for valid 61 * types. */ 62 struct TkMenu *menuPtr; /* Menu with which this entry is 63 * associated. */ 64 Tk_OptionTable optionTable; /* Option table for this menu entry. */ 65 Tcl_Obj *labelPtr; /* Main text label displayed in entry (NULL if 66 * no label). */ 67 int labelLength; /* Number of non-NULL characters in label. */ 68 int state; /* State of button for display purposes: 69 * normal, active, or disabled. */ 70 int underline; /* Value of -underline option: specifies index 71 * of character to underline (<0 means don't 72 * underline anything). */ 73 Tcl_Obj *underlinePtr; /* Index of character to underline. */ 74 Tcl_Obj *bitmapPtr; /* Bitmap to display in menu entry, or NULL. 75 * If not NULL then label is ignored. */ 76 Tcl_Obj *imagePtr; /* Name of image to display, or NULL. If not 77 * NULL, bitmap, text, and textVarName are 78 * ignored. */ 79 Tk_Image image; /* Image to display in menu entry, or NULL if 80 * none. */ 81 Tcl_Obj *selectImagePtr; /* Name of image to display when selected, or 82 * NULL. */ 83 Tk_Image selectImage; /* Image to display in entry when selected, or 84 * NULL if none. Ignored if image is NULL. */ 85 Tcl_Obj *accelPtr; /* Accelerator string displayed at right of 86 * menu entry. NULL means no such accelerator. 87 * Malloc'ed. */ 88 int accelLength; /* Number of non-NULL characters in 89 * accelerator. */ 90 int indicatorOn; /* True means draw indicator, false means 91 * don't draw it. This field is ignored unless 92 * the entry is a radio or check button. */ 93 /* 94 * Display attributes 95 */ 96 97 Tcl_Obj *borderPtr; /* Structure used to draw background for 98 * entry. NULL means use overall border for 99 * menu. */ 100 Tcl_Obj *fgPtr; /* Foreground color to use for entry. NULL 101 * means use foreground color from menu. */ 102 Tcl_Obj *activeBorderPtr; /* Used to draw background and border when 103 * element is active. NULL means use 104 * activeBorder from menu. */ 105 Tcl_Obj *activeFgPtr; /* Foreground color to use when entry is 106 * active. NULL means use active foreground 107 * from menu. */ 108 Tcl_Obj *indicatorFgPtr; /* Color for indicators in radio and check 109 * button entries. NULL means use indicatorFg 110 * GC from menu. */ 111 Tcl_Obj *fontPtr; /* Text font for menu entries. NULL means use 112 * overall font for menu. */ 113 int columnBreak; /* If this is 0, this item appears below the 114 * item in front of it. If this is 1, this 115 * item starts a new column. This field is 116 * always 0 for tearoff and separator 117 * entries. */ 118 int hideMargin; /* If this is 0, then the item has enough 119 * margin to accommodate a standard check mark 120 * and a default right margin. If this is 1, 121 * then the item has no such margins, and 122 * checkbuttons and radiobuttons with this set 123 * will have a rectangle drawn in the 124 * indicator around the item if the item is 125 * checked. This is useful for palette menus. 126 * This field is ignored for separators and 127 * tearoffs. */ 128 int indicatorSpace; /* The width of the indicator space for this 129 * entry. */ 130 int labelWidth; /* Number of pixels to allow for displaying 131 * labels in menu entries. */ 132 int compound; /* Value of -compound option; specifies 133 * whether the entry should show both an image 134 * and text, and, if so, how. */ 135 136 /* 137 * Information used to implement this entry's action: 138 */ 139 140 Tcl_Obj *commandPtr; /* Command to invoke when entry is invoked. 141 * Malloc'ed. */ 142 Tcl_Obj *namePtr; /* Name of variable (for check buttons and 143 * radio buttons) or menu (for cascade 144 * entries). Malloc'ed. */ 145 Tcl_Obj *onValuePtr; /* Value to store in variable when selected 146 * (only for radio and check buttons). 147 * Malloc'ed. */ 148 Tcl_Obj *offValuePtr; /* Value to store in variable when not 149 * selected (only for check buttons). 150 * Malloc'ed. */ 151 152 /* 153 * Information used for drawing this menu entry. 154 */ 155 156 int width; /* Number of pixels occupied by entry in 157 * horizontal dimension. Not used except in 158 * menubars. The width of norma menus is 159 * dependent on the rest of the menu. */ 160 int x; /* X-coordinate of leftmost pixel in entry. */ 161 int height; /* Number of pixels occupied by entry in 162 * vertical dimension, including raised border 163 * drawn around entry when active. */ 164 int y; /* Y-coordinate of topmost pixel in entry. */ 165 GC textGC; /* GC for drawing text in entry. NULL means 166 * use overall textGC for menu. */ 167 GC activeGC; /* GC for drawing text in entry when active. 168 * NULL means use overall activeGC for 169 * menu. */ 170 GC disabledGC; /* Used to produce disabled effect for entry. 171 * NULL means use overall disabledGC from menu 172 * structure. See comments for disabledFg in 173 * menu structure for more information. */ 174 GC indicatorGC; /* For drawing indicators. NULL means use GC 175 * from menu. */ 176 177 /* 178 * Miscellaneous fields. 179 */ 180 181 int entryFlags; /* Various flags. See below for 182 * definitions. */ 183 int index; /* Need to know which index we are. This is 184 * zero-based. This is the top-left entry of 185 * the menu. */ 186 187 /* 188 * Bookeeping for main menus and cascade menus. 189 */ 190 191 struct TkMenuReferences *childMenuRefPtr; 192 /* A pointer to the hash table entry for the 193 * child menu. Stored here when the menu entry 194 * is configured so that a hash lookup is not 195 * necessary later.*/ 196 struct TkMenuEntry *nextCascadePtr; 197 /* The next cascade entry that is a parent of 198 * this entry's child cascade menu. NULL end 199 * of list, this is not a cascade entry, or 200 * the menu that this entry point to does not 201 * yet exist. */ 202 TkMenuPlatformEntryData platformEntryData; 203 /* The data for the specific type of menu. 204 * Depends on platform and menu type what kind 205 * of options are in this structure. */ 206 } TkMenuEntry; 207 208 /* 209 * Flag values defined for menu entries: 210 * 211 * ENTRY_SELECTED: Non-zero means this is a radio or check button 212 * and that it should be drawn in the "selected" 213 * state. 214 * ENTRY_NEEDS_REDISPLAY: Non-zero means the entry should be redisplayed. 215 * ENTRY_LAST_COLUMN: Used by the drawing code. If the entry is in 216 * the last column, the space to its right needs 217 * to be filled. 218 * ENTRY_PLATFORM_FLAG1 - 4 These flags are reserved for use by the 219 * platform-dependent implementation of menus 220 * and should not be used by anything else. 221 */ 222 223 #define ENTRY_SELECTED 1 224 #define ENTRY_NEEDS_REDISPLAY 2 225 #define ENTRY_LAST_COLUMN 4 226 #define ENTRY_PLATFORM_FLAG1 (1 << 30) 227 #define ENTRY_PLATFORM_FLAG2 (1 << 29) 228 #define ENTRY_PLATFORM_FLAG3 (1 << 28) 229 #define ENTRY_PLATFORM_FLAG4 (1 << 27) 230 231 /* 232 * Types defined for MenuEntries: 233 */ 234 235 #define CASCADE_ENTRY 0 236 #define CHECK_BUTTON_ENTRY 1 237 #define COMMAND_ENTRY 2 238 #define RADIO_BUTTON_ENTRY 3 239 #define SEPARATOR_ENTRY 4 240 #define TEAROFF_ENTRY 5 241 242 /* 243 * Menu states 244 */ 245 246 #define ENTRY_ACTIVE 0 247 #define ENTRY_NORMAL 1 248 #define ENTRY_DISABLED 2 249 250 /* 251 * A data structure of the following type is kept for each menu widget: 252 */ 253 254 typedef struct TkMenu { 255 Tk_Window tkwin; /* Window that embodies the pane. NULL means 256 * that the window has been destroyed but the 257 * data structures haven't yet been cleaned 258 * up. */ 259 Display *display; /* Display containing widget. Needed, among 260 * other things, so that resources can be 261 * freed up even after tkwin has gone away. */ 262 Tcl_Interp *interp; /* Interpreter associated with menu. */ 263 Tcl_Command widgetCmd; /* Token for menu's widget command. */ 264 TkMenuEntry **entries; /* Array of pointers to all the entries in the 265 * menu. NULL means no entries. */ 266 int numEntries; /* Number of elements in entries. */ 267 int active; /* Index of active entry. -1 means nothing 268 * active. */ 269 int menuType; /* MAIN_MENU, TEAROFF_MENU, or MENUBAR. See 270 * below for definitions. */ 271 Tcl_Obj *menuTypePtr; /* Used to control whether created tkwin is a 272 * toplevel or not. "normal", "menubar", or 273 * "toplevel" */ 274 275 /* 276 * Information used when displaying widget: 277 */ 278 279 Tcl_Obj *borderPtr; /* Structure used to draw 3-D border and 280 * background for menu. */ 281 Tcl_Obj *borderWidthPtr; /* Width of border around whole menu. */ 282 Tcl_Obj *activeBorderPtr; /* Used to draw background and border for 283 * active element (if any). */ 284 Tcl_Obj *activeBorderWidthPtr; 285 /* Width of border around active element. */ 286 Tcl_Obj *reliefPtr; /* 3-d effect: TK_RELIEF_RAISED, etc. */ 287 Tcl_Obj *fontPtr; /* Text font for menu entries. */ 288 Tcl_Obj *fgPtr; /* Foreground color for entries. */ 289 Tcl_Obj *disabledFgPtr; /* Foreground color when disabled. NULL means 290 * use normalFg with a 50% stipple instead. */ 291 Tcl_Obj *activeFgPtr; /* Foreground color for active entry. */ 292 Tcl_Obj *indicatorFgPtr; /* Color for indicators in radio and check 293 * button entries. */ 294 Pixmap gray; /* Bitmap for drawing disabled entries in a 295 * stippled fashion. None means not allocated 296 * yet. */ 297 GC textGC; /* GC for drawing text and other features of 298 * menu entries. */ 299 GC disabledGC; /* Used to produce disabled effect. If 300 * disabledFg isn't NULL, this GC is used to 301 * draw text and icons for disabled entries. 302 * Otherwise text and icons are drawn with 303 * normalGC and this GC is used to stipple 304 * background across them. */ 305 GC activeGC; /* GC for drawing active entry. */ 306 GC indicatorGC; /* For drawing indicators. */ 307 GC disabledImageGC; /* Used for drawing disabled images. They have 308 * to be stippled. This is created when the 309 * image is about to be drawn the first 310 * time. */ 311 312 /* 313 * Information about geometry of menu. 314 */ 315 316 int totalWidth; /* Width of entire menu. */ 317 int totalHeight; /* Height of entire menu. */ 318 319 /* 320 * Miscellaneous information: 321 */ 322 323 int tearoff; /* 1 means this menu can be torn off. On some 324 * platforms, the user can drag an outline of 325 * the menu by just dragging outside of the 326 * menu, and the tearoff is created where the 327 * mouse is released. On others, an indicator 328 * (such as a dashed stripe) is drawn, and 329 * when the menu is selected, the tearoff is 330 * created. */ 331 Tcl_Obj *titlePtr; /* The title to use when this menu is torn 332 * off. If this is NULL, a default scheme will 333 * be used to generate a title for tearoff. */ 334 Tcl_Obj *tearoffCommandPtr; /* If non-NULL, points to a command to run 335 * whenever the menu is torn-off. */ 336 Tcl_Obj *takeFocusPtr; /* Value of -takefocus option; not used in the 337 * C code, but used by keyboard traversal 338 * scripts. Malloc'ed, but may be NULL. */ 339 Tcl_Obj *cursorPtr; /* Current cursor for window, or NULL. */ 340 Tcl_Obj *postCommandPtr; /* Used to detect cycles in cascade hierarchy 341 * trees when preprocessing postcommands on 342 * some platforms. See PostMenu for more 343 * details. */ 344 int postCommandGeneration; /* Need to do pre-invocation post command 345 * traversal. */ 346 int menuFlags; /* Flags for use by X; see below for 347 * definition. */ 348 TkMenuEntry *postedCascade; /* Points to menu entry for cascaded submenu 349 * that is currently posted or NULL if no 350 * submenu posted. */ 351 struct TkMenu *nextInstancePtr; 352 /* The next instance of this menu in the 353 * chain. */ 354 struct TkMenu *masterMenuPtr; 355 /* A pointer to the original menu for this 356 * clone chain. Points back to this structure 357 * if this menu is a main menu. */ 358 void *reserved1; /* not used any more. */ 359 Tk_Window parentTopLevelPtr;/* If this menu is a menubar, this is the 360 * toplevel that owns the menu. Only 361 * applicable for menubar clones. */ 362 struct TkMenuReferences *menuRefPtr; 363 /* Each menu is hashed into a table with the 364 * name of the menu's window as the key. The 365 * information in this hash table includes a 366 * pointer to the menu (so that cascades can 367 * find this menu), a pointer to the list of 368 * toplevel widgets that have this menu as its 369 * menubar, and a list of menu entries that 370 * have this menu specified as a cascade. */ 371 TkMenuPlatformData platformData; 372 /* The data for the specific type of menu. 373 * Depends on platform and menu type what kind 374 * of options are in this structure. */ 375 Tk_OptionSpec *extensionPtr;/* Needed by the configuration package for 376 * this widget to be extended. */ 377 Tk_SavedOptions *errorStructPtr; 378 /* We actually have to allocate these because 379 * multiple menus get changed during one 380 * ConfigureMenu call. */ 381 } TkMenu; 382 383 /* 384 * When the toplevel configure -menu command is executed, the menu may not 385 * exist yet. We need to keep a linked list of windows that reference a 386 * particular menu. 387 */ 388 389 typedef struct TkMenuTopLevelList { 390 struct TkMenuTopLevelList *nextPtr; 391 /* The next window in the list. */ 392 Tk_Window tkwin; /* The window that has this menu as its 393 * menubar. */ 394 } TkMenuTopLevelList; 395 396 /* 397 * The following structure is used to keep track of things which reference a 398 * menu. It is created when: 399 * - a menu is created. 400 * - a cascade entry is added to a menu with a non-null name 401 * - the "-menu" configuration option is used on a toplevel widget with a 402 * non-null parameter. 403 * 404 * One of these three fields must be non-NULL, but any of the fields may be 405 * NULL. This structure makes it easy to determine whether or not anything 406 * like recalculating platform data or geometry is necessary when one of the 407 * three actions above is performed. 408 */ 409 410 typedef struct TkMenuReferences { 411 struct TkMenu *menuPtr; /* The menu data structure. This is NULL if 412 * the menu does not exist. */ 413 TkMenuTopLevelList *topLevelListPtr; 414 /* First in the list of all toplevels that 415 * have this menu as its menubar. NULL if no 416 * toplevel widgets have this menu as its 417 * menubar. */ 418 TkMenuEntry *parentEntryPtr;/* First in the list of all cascade menu 419 * entries that have this menu as their child. 420 * NULL means no cascade entries. */ 421 Tcl_HashEntry *hashEntryPtr;/* This is needed because the pathname of the 422 * window (which is what we hash on) may not 423 * be around when we are deleting. */ 424 } TkMenuReferences; 425 426 /* 427 * Flag bits for menus: 428 * 429 * REDRAW_PENDING: Non-zero means a DoWhenIdle handler has 430 * already been queued to redraw this window. 431 * RESIZE_PENDING: Non-zero means a call to ComputeMenuGeometry 432 * has already been scheduled. 433 * MENU_DELETION_PENDING Non-zero means that we are currently 434 * destroying this menu's internal structures. 435 * This is useful when we are in the middle of 436 * cleaning this main menu's chain of menus up 437 * when TkDestroyMenu was called again on this 438 * menu (via a destroy binding or somesuch). 439 * MENU_WIN_DESTRUCTION_PENDING Non-zero means we are in the middle of 440 * destroying this menu's Tk_Window. 441 * MENU_PLATFORM_FLAG1... Reserved for use by the platform-specific menu 442 * code. 443 */ 444 445 #define REDRAW_PENDING 1 446 #define RESIZE_PENDING 2 447 #define MENU_DELETION_PENDING 4 448 #define MENU_WIN_DESTRUCTION_PENDING 8 449 #define MENU_PLATFORM_FLAG1 (1 << 30) 450 #define MENU_PLATFORM_FLAG2 (1 << 29) 451 #define MENU_PLATFORM_FLAG3 (1 << 28) 452 453 /* 454 * Each menu created by the user is a MAIN_MENU. When a menu is torn off, a 455 * TEAROFF_MENU instance is created. When a menu is assigned to a toplevel as 456 * a menu bar, a MENUBAR instance is created. All instances have the same 457 * configuration information. If the main instance is deleted, all instances 458 * are deleted. If one of the other instances is deleted, only that instance 459 * is deleted. 460 */ 461 462 #define UNKNOWN_TYPE -1 463 #define MAIN_MENU 0 464 #define MASTER_MENU 0 465 #define TEAROFF_MENU 1 466 #define MENUBAR 2 467 468 /* 469 * Various geometry definitions: 470 */ 471 472 #define CASCADE_ARROW_HEIGHT 10 473 #define CASCADE_ARROW_WIDTH 8 474 #define DECORATION_BORDER_WIDTH 2 475 476 /* 477 * Menu-related functions that are shared among Tk modules but not exported to 478 * the outside world: 479 */ 480 481 MODULE_SCOPE int TkActivateMenuEntry(TkMenu *menuPtr, int index); 482 MODULE_SCOPE void TkBindMenu(Tk_Window tkwin, TkMenu *menuPtr); 483 MODULE_SCOPE TkMenuReferences*TkCreateMenuReferences(Tcl_Interp *interp, 484 const char *name); 485 MODULE_SCOPE void TkDestroyMenu(TkMenu *menuPtr); 486 MODULE_SCOPE void TkEventuallyRecomputeMenu(TkMenu *menuPtr); 487 MODULE_SCOPE void TkEventuallyRedrawMenu(TkMenu *menuPtr, 488 TkMenuEntry *mePtr); 489 MODULE_SCOPE TkMenuReferences*TkFindMenuReferences(Tcl_Interp *interp, const char *name); 490 MODULE_SCOPE TkMenuReferences*TkFindMenuReferencesObj(Tcl_Interp *interp, 491 Tcl_Obj *namePtr); 492 MODULE_SCOPE int TkFreeMenuReferences(TkMenuReferences *menuRefPtr); 493 MODULE_SCOPE Tcl_HashTable *TkGetMenuHashTable(Tcl_Interp *interp); 494 MODULE_SCOPE int TkGetMenuIndex(Tcl_Interp *interp, TkMenu *menuPtr, 495 Tcl_Obj *objPtr, int lastOK, int *indexPtr); 496 MODULE_SCOPE void TkMenuInitializeDrawingFields(TkMenu *menuPtr); 497 MODULE_SCOPE void TkMenuInitializeEntryDrawingFields(TkMenuEntry *mePtr); 498 MODULE_SCOPE int TkInvokeMenu(Tcl_Interp *interp, TkMenu *menuPtr, 499 int index); 500 MODULE_SCOPE void TkMenuConfigureDrawOptions(TkMenu *menuPtr); 501 MODULE_SCOPE int TkMenuConfigureEntryDrawOptions( 502 TkMenuEntry *mePtr, int index); 503 MODULE_SCOPE void TkMenuFreeDrawOptions(TkMenu *menuPtr); 504 MODULE_SCOPE void TkMenuEntryFreeDrawOptions(TkMenuEntry *mePtr); 505 MODULE_SCOPE void TkMenuEventProc(ClientData clientData, 506 XEvent *eventPtr); 507 MODULE_SCOPE void TkMenuImageProc(ClientData clientData, int x, int y, 508 int width, int height, int imgWidth, 509 int imgHeight); 510 MODULE_SCOPE void TkMenuInit(void); 511 MODULE_SCOPE void TkMenuSelectImageProc(ClientData clientData, int x, 512 int y, int width, int height, int imgWidth, 513 int imgHeight); 514 MODULE_SCOPE Tcl_Obj * TkNewMenuName(Tcl_Interp *interp, 515 Tcl_Obj *parentNamePtr, TkMenu *menuPtr); 516 MODULE_SCOPE int TkPostCommand(TkMenu *menuPtr); 517 MODULE_SCOPE int TkPostSubmenu(Tcl_Interp *interp, TkMenu *menuPtr, 518 TkMenuEntry *mePtr); 519 MODULE_SCOPE int TkPostTearoffMenu(Tcl_Interp *interp, TkMenu *menuPtr, 520 int x, int y); 521 MODULE_SCOPE int TkPreprocessMenu(TkMenu *menuPtr); 522 MODULE_SCOPE void TkRecomputeMenu(TkMenu *menuPtr); 523 524 /* 525 * These routines are the platform-dependent routines called by the common 526 * code. 527 */ 528 529 MODULE_SCOPE void TkpComputeMenubarGeometry(TkMenu *menuPtr); 530 MODULE_SCOPE void TkpComputeStandardMenuGeometry(TkMenu *menuPtr); 531 MODULE_SCOPE int TkpConfigureMenuEntry(TkMenuEntry *mePtr); 532 MODULE_SCOPE void TkpDestroyMenu(TkMenu *menuPtr); 533 MODULE_SCOPE void TkpDestroyMenuEntry(TkMenuEntry *mEntryPtr); 534 MODULE_SCOPE void TkpDrawMenuEntry(TkMenuEntry *mePtr, 535 Drawable d, Tk_Font tkfont, 536 const Tk_FontMetrics *menuMetricsPtr, int x, 537 int y, int width, int height, int strictMotif, 538 int drawingParameters); 539 MODULE_SCOPE void TkpMenuInit(void); 540 MODULE_SCOPE int TkpMenuNewEntry(TkMenuEntry *mePtr); 541 MODULE_SCOPE int TkpNewMenu(TkMenu *menuPtr); 542 MODULE_SCOPE int TkpPostMenu(Tcl_Interp *interp, TkMenu *menuPtr, 543 int x, int y, int index); 544 MODULE_SCOPE int TkpPostTearoffMenu(Tcl_Interp *interp, TkMenu *menuPtr, 545 int x, int y, int index); 546 MODULE_SCOPE void TkpSetWindowMenuBar(Tk_Window tkwin, TkMenu *menuPtr); 547 548 #endif /* _TKMENU */ 549