1: #include <X/mit-copyright.h> 2: 3: /* $Header: XMenuInternal.c,v 10.17 86/02/01 16:15:10 tony Rel $ */ 4: /* Copyright Massachusetts Institute of Technology 1985 */ 5: 6: /* 7: * XMenu: MIT Project Athena, X Window system menu package 8: * 9: * XMenuInternal.c - XMenu internal (not user visable) routines. 10: * 11: * Author: Tony Della Fera, DEC 12: * November, 1985 13: * 14: */ 15: 16: #include "XMenuInternal.h" 17: 18: /* 19: * Toggle color macro. 20: */ 21: #define toggle_color(x) \ 22: ((x) == menu->bkgnd_color ? menu->s_frg_color : menu->bkgnd_color) 23: 24: /* 25: * Internal Window creation queue sizes. 26: */ 27: #define S_QUE_SIZE 300 28: #define P_QUE_SIZE 20 29: #define BUFFER_SIZE (S_QUE_SIZE >= P_QUE_SIZE ? S_QUE_SIZE : P_QUE_SIZE) 30: 31: 32: /* 33: * XMWinQue - Internal window creation queue datatype. 34: */ 35: typedef struct _xm_win_que_def { 36: int sq_size; 37: XMSelect *sq[S_QUE_SIZE]; 38: XMSelect **sq_ptr; 39: int pq_size; 40: XMPane *pq[P_QUE_SIZE]; 41: XMPane **pq_ptr; 42: } XMWinQue; 43: 44: /* 45: * _XMWinQue - Internal static window creation queue. 46: */ 47: static XMWinQue _XMWinQue; 48: 49: /* 50: * _XMErrorCode - Global XMenu error code. 51: */ 52: int _XMErrorCode = XME_NO_ERROR; 53: 54: /* 55: * _XMErrorList - Global XMenu error code discription strings. 56: */ 57: char * 58: _XMErrorList[XME_CODE_COUNT] = { 59: "No error", /* XME_NO_ERROR */ 60: "Menu not initialized", /* XME_NOT_INIT */ 61: "Argument out of bounds", /* XME_ARG_BOUNDS */ 62: "Pane not found", /* XME_P_NOT_FOUND */ 63: "Selection not found", /* XME_S_NOT_FOUND */ 64: "Invalid menu style parameter", /* XME_STYLE_PARAM */ 65: "Unable to grab mouse", /* XME_GRAB_MOUSE */ 66: "Unable to interpret locator", /* XME_INTERP_LOC */ 67: "Unable to calloc memory", /* XME_CALLOC */ 68: "Unable to create XAssocTable", /* XME_CREATE_ASSOC */ 69: "Unable to store bitmap", /* XME_STORE_BITMAP */ 70: "Unable to make tile pixmaps", /* XME_MAKE_TILES */ 71: "Unable to make pixmap", /* XME_MAKE_PIXMAP */ 72: "Unable to create cursor", /* XME_CREATE_CURSOR */ 73: "Unable to open font", /* XME_OPEN_FONT */ 74: "Unable to create windows", /* XME_CREATE_WINDOW */ 75: "Unable to create transparencies", /* XME_CREATE_TRANSP */ 76: }; 77: 78: /* 79: * _XMEventHandler - Internal event handler variable. 80: */ 81: int (*_XMEventHandler)() = NULL; 82: 83: 84: 85: /* 86: * _XMWinQueInit - Internal routine to initialize the window 87: * queue. 88: */ 89: _XMWinQueInit() 90: { 91: /* 92: * Blank the queue structure. 93: */ 94: bzero(&_XMWinQue, sizeof(XMWinQue)); 95: 96: /* 97: * Initialize the next free location pointers. 98: */ 99: _XMWinQue.sq_ptr = _XMWinQue.sq; 100: _XMWinQue.pq_ptr = _XMWinQue.pq; 101: } 102: 103: 104: 105: /* 106: * _XMWinQueAddPane - Internal routine to add a pane to the pane 107: * window queue. 108: */ 109: int 110: _XMWinQueAddPane(menu, p_ptr) 111: register XMenu *menu; /* Menu being manipulated. */ 112: register XMPane *p_ptr; /* XMPane being queued. */ 113: { 114: /* 115: * If the queue is currently full then flush it. 116: */ 117: if (_XMWinQue.pq_size == P_QUE_SIZE) { 118: if (_XMWinQueFlush(menu) == _FAILURE) return(_FAILURE); 119: } 120: 121: /* 122: * Insert the new XMPane pointer and increment the queue pointer 123: * and the queue size. 124: */ 125: *_XMWinQue.pq_ptr = p_ptr; 126: _XMWinQue.pq_ptr++; 127: _XMWinQue.pq_size++; 128: 129: /* 130: * All went well, return successfully. 131: */ 132: _XMErrorCode = XME_NO_ERROR; 133: return(_SUCCESS); 134: } 135: 136: 137: 138: /* 139: * _XMWinQueAddSelection - Internal routine to add a selection to 140: * the selection window queue. 141: */ 142: int 143: _XMWinQueAddSelection(menu, s_ptr) 144: register XMenu *menu; /* Menu being manipulated. */ 145: register XMSelect *s_ptr; /* XMSelection being queued. */ 146: { 147: /* 148: * If this entry will overflow the queue then flush it. 149: */ 150: if (_XMWinQue.sq_size == S_QUE_SIZE) { 151: if (_XMWinQueFlush(menu) == _FAILURE) return(_FAILURE); 152: } 153: 154: /* 155: * Insert the new XMSelect pointer and increment the queue pointer 156: * and the queue size. 157: */ 158: *_XMWinQue.sq_ptr = s_ptr; 159: _XMWinQue.sq_ptr++; 160: _XMWinQue.sq_size++; 161: 162: /* 163: * All went well, return successfully. 164: */ 165: _XMErrorCode = XME_NO_ERROR; 166: return(_SUCCESS); 167: } 168: 169: 170: 171: /* 172: * _XMWinQueFlush - Internal routine to flush the pane and 173: * selection window queues. 174: */ 175: int 176: _XMWinQueFlush(menu) 177: register XMenu *menu; /* Menu being manipulated. */ 178: { 179: register int pq_index; /* Pane queue index. */ 180: register int sq_index; /* Selection queue index. */ 181: register XMPane *p_ptr; /* XMPane pointer. */ 182: register XMSelect *s_ptr; /* XMSelect pointer. */ 183: 184: int win_count; /* Count of created windows. */ 185: Window window; /* Window id temporary variable. */ 186: BatchFrame batch_buf[BUFFER_SIZE]; /* Window batch creation buffer. */ 187: 188: /* 189: * If the pane window queue is not empty... 190: */ 191: if (_XMWinQue.pq_size > 0) { 192: /* 193: * Pack the window batch buffer. 194: */ 195: for (pq_index = 0; pq_index < _XMWinQue.pq_size; pq_index++) { 196: /* 197: * Retrieve the an XMPane pointer. 198: */ 199: p_ptr = _XMWinQue.pq[pq_index]; 200: 201: /* 202: * Pack the next buffer location with the data 203: * associated with the XMPane. 204: */ 205: batch_buf[pq_index].type = IsOpaque; 206: batch_buf[pq_index].parent = menu->parent; 207: batch_buf[pq_index].x = p_ptr->window_x; 208: batch_buf[pq_index].y = p_ptr->window_y; 209: batch_buf[pq_index].width = p_ptr->window_w; 210: batch_buf[pq_index].height = p_ptr->window_h; 211: batch_buf[pq_index].bdrwidth = menu->p_bdr_width; 212: batch_buf[pq_index].border = menu->p_bdr_pixmap; 213: batch_buf[pq_index].background = menu->inact_pixmap; 214: } 215: 216: /* 217: * Transmit the pane window buffer. 218: */ 219: win_count = XCreateWindowBatch(batch_buf, _XMWinQue.pq_size); 220: if (win_count != _XMWinQue.pq_size) { 221: _XMErrorCode = XME_CREATE_WINDOW; 222: return(_FAILURE); 223: } 224: 225: /* 226: * Retrieve the resulting window id's. 227: */ 228: for (pq_index = 0; pq_index < _XMWinQue.pq_size; pq_index++) { 229: window = batch_buf[pq_index].self; 230: /* 231: * Store the window id with its XMPane structure. 232: */ 233: p_ptr = _XMWinQue.pq[pq_index]; 234: p_ptr->window = window; 235: /* 236: * Insert the new window id and its 237: * associated XMPane structure into the 238: * assoction table. 239: */ 240: XMakeAssoc(menu->assoc_tab, window, p_ptr); 241: /* 242: * Select input events on the new window. 243: */ 244: XSelectInput(window, menu->p_events); 245: } 246: 247: /* 248: * Reset the pane queue pointer and size. 249: */ 250: _XMWinQue.pq_size = 0; 251: _XMWinQue.pq_ptr = _XMWinQue.pq; 252: } 253: 254: /* 255: * If the selection window queue is not empty... 256: */ 257: if (_XMWinQue.sq_size > 0) { 258: /* 259: * Pack the selection transparency buffer. 260: */ 261: for (sq_index = 0; sq_index < _XMWinQue.sq_size; sq_index++) { 262: /* 263: * Retrieve the an XMSelect pointer. 264: */ 265: s_ptr = _XMWinQue.sq[sq_index]; 266: 267: /* 268: * Pack the next buffer location with the data 269: * associated with the XMPane. 270: */ 271: batch_buf[sq_index].type = IsTransparent; 272: batch_buf[sq_index].parent = s_ptr->parent_p->window; 273: batch_buf[sq_index].x = s_ptr->window_x; 274: batch_buf[sq_index].y = s_ptr->window_y; 275: batch_buf[sq_index].width = s_ptr->window_w; 276: batch_buf[sq_index].height = s_ptr->window_h; 277: } 278: 279: /* 280: * Transmit the selection transparency buffer. 281: */ 282: win_count = XCreateWindowBatch(batch_buf, _XMWinQue.sq_size); 283: if (win_count != _XMWinQue.sq_size) { 284: _XMErrorCode = XME_CREATE_TRANSP; 285: return(_FAILURE); 286: } 287: 288: /* 289: * Retrieve the resulting window id's. 290: */ 291: for (sq_index = 0; sq_index < _XMWinQue.sq_size; sq_index++) { 292: window = batch_buf[sq_index].self; 293: /* 294: * Store the window id with its XMSelect structure. 295: */ 296: s_ptr = _XMWinQue.sq[sq_index]; 297: s_ptr->window = window; 298: /* 299: * Insert the new window id and its 300: * associated XMSelect structure into the 301: * assoction table. 302: */ 303: XMakeAssoc(menu->assoc_tab, window, s_ptr); 304: /* 305: * Select input events on the new window. 306: */ 307: XSelectInput(window, menu->s_events); 308: } 309: 310: /* 311: * Reset the selection queue pointer and size. 312: */ 313: _XMWinQue.sq_size = 0; 314: _XMWinQue.sq_ptr = _XMWinQue.sq; 315: } 316: 317: /* 318: * Flush X's internal queues. 319: */ 320: XFlush(); 321: 322: /* 323: * All went well, return successfully. 324: */ 325: _XMErrorCode = XME_NO_ERROR; 326: return(_SUCCESS); 327: } 328: 329: 330: 331: /* 332: * _XMGetPanePtr - Given a menu pointer and a pane index number, return 333: * a pane pointer that points to the indexed pane. 334: */ 335: XMPane * 336: _XMGetPanePtr(menu, p_num) 337: register XMenu *menu; /* Menu to find the pane in. */ 338: register int p_num; /* Index number of pane to find. */ 339: { 340: register XMPane *p_ptr; /* Pane pointer to be returned. */ 341: register int i; /* Loop counter. */ 342: 343: /* 344: * Is the pane number out of range? 345: */ 346: if ((p_num < 0) || (p_num > (menu->p_count - 1))) { 347: _XMErrorCode = XME_P_NOT_FOUND; 348: return(NULL); 349: } 350: 351: /* 352: * Find the right pane. 353: */ 354: p_ptr = menu->p_list->next; 355: for (i = 0; i < p_num; i++) p_ptr = p_ptr->next; 356: 357: /* 358: * Return successfully. 359: */ 360: _XMErrorCode = XME_NO_ERROR; 361: return(p_ptr); 362: } 363: 364: 365: 366: /* 367: * _XMGetSelectionPtr - Given pane pointer and a selection index number, 368: * return a selection pointer that points to the 369: * indexed selection. 370: */ 371: XMSelect * 372: _XMGetSelectionPtr(p_ptr, s_num) 373: register XMPane *p_ptr; /* Pane to find the selection in. */ 374: register int s_num; /* Index number of the selection to find. */ 375: { 376: register XMSelect *s_ptr; /* Selection pointer to be returned. */ 377: register int i; /* Loop counter. *./ 378: 379: /* 380: * Is the selection number out of range? 381: */ 382: if ((s_num < 0) || (s_num > (p_ptr->s_count - 1))) { 383: _XMErrorCode = XME_S_NOT_FOUND; 384: return(NULL); 385: } 386: 387: /* 388: * Find the right selection. 389: */ 390: s_ptr = p_ptr->s_list->next; 391: for (i = 0; i < s_num; i++) s_ptr = s_ptr->next; 392: 393: /* 394: * Return successfully. 395: */ 396: _XMErrorCode = XME_NO_ERROR; 397: return(s_ptr); 398: } 399: 400: 401: 402: /* 403: * _XMRecomputeGlobals - Internal subroutine to recompute menu wide 404: * global values. 405: */ 406: _XMRecomputeGlobals(menu) 407: register XMenu *menu; /* Menu object to compute from. */ 408: { 409: register XMPane *p_ptr; /* Pane pointer. */ 410: register XMSelect *s_ptr; /* Selection pointer. */ 411: 412: register int max_p_label = 0; /* Maximum pane label width. */ 413: register int max_s_label = 0; /* Maximum selection label width. */ 414: register int s_count = 0; /* Maximum selection count. */ 415: 416: int p_s_pad; /* Pane <-> selection padding. */ 417: int p_s_diff; /* Pane <-> selection seperation. */ 418: 419: int p_height; /* Pane window height. */ 420: int p_width; /* Pane window width. */ 421: int s_width; /* Selection window width. */ 422: 423: int seperation; /* Pane window, selection window seperation. */ 424: 425: /* 426: * For each pane... 427: */ 428: for ( 429: p_ptr = menu->p_list->next; 430: p_ptr != menu->p_list; 431: p_ptr = p_ptr->next 432: ){ 433: /* 434: * Recompute maximum pane label width. 435: */ 436: max_p_label = max(max_p_label, p_ptr->label_width); 437: 438: /* 439: * Recompute maximum selection count. 440: */ 441: s_count = max(s_count, p_ptr->s_count); 442: 443: /* 444: * For each selection in the current pane... 445: */ 446: for ( 447: s_ptr = p_ptr->s_list->next; 448: s_ptr != p_ptr->s_list; 449: s_ptr = s_ptr->next 450: ){ 451: /* 452: * Recompute maximum selection label width. 453: */ 454: max_s_label = max(max_s_label, s_ptr->label_width); 455: } 456: } 457: 458: /* 459: * Recompute pane height. 460: */ 461: p_height = (menu->flag_height << 1) + (menu->s_y_off * s_count); 462: 463: /* 464: * Recompute horizontal padding between the pane window and the 465: * selection windows. 466: */ 467: p_s_pad = menu->p_x_off << 1; 468: 469: /* 470: * Recompute pane and selection window widths. 471: * This is done by first computing the window sizes from the maximum 472: * label widths. If the spacing between the selection window and the 473: * containing pane window is less than the pane selection padding value 474: * (twice the pane X offset) then change the size of the pane to be 475: * the size of the selection window plus the padding. If, however the 476: * spacing between the selection window and the containing pane window 477: * is more than the pane selection padding value increase the size of 478: * the selection to its maximum possible value (the pane width minus 479: * the pane selection padding value). 480: */ 481: p_width = max_p_label + p_s_pad; 482: s_width = max_s_label + (menu->s_fnt_pad << 1) + (menu->s_bdr_width << 1); 483: p_s_diff = p_width - s_width; 484: if (p_s_diff < p_s_pad) { 485: p_width = s_width + p_s_pad; 486: } 487: else if (p_s_diff > p_s_pad) { 488: s_width = p_width - p_s_pad; 489: } 490: 491: /* 492: * Reset menu wide global values. 493: */ 494: menu->s_count = s_count; 495: menu->p_height = p_height; 496: menu->p_width = p_width; 497: menu->s_width = s_width; 498: } 499: 500: 501: 502: /* 503: * _XMRecomputePane - Internal subroutine to recompute pane 504: * window dependencies. 505: */ 506: int 507: _XMRecomputePane(menu, p_ptr, p_num) 508: register XMenu *menu; /* Menu object being recomputed. */ 509: register XMPane *p_ptr; /* Pane pointer. */ 510: register int p_num; /* Pane sequence number. */ 511: { 512: register int window_x; /* Recomputed window X coordinate. */ 513: register int window_y; /* Recomputed window Y coordinate. */ 514: 515: register Bool config_p = FALSE; /* Reconfigure pane window? */ 516: 517: /* 518: * Update the pane serial number. 519: */ 520: p_ptr->serial = p_num; 521: 522: /* 523: * Recompute window X and Y coordinates. 524: */ 525: switch (menu->menu_style) { 526: case LEFT: 527: window_x = menu->p_x_off * ((menu->p_count - 1) - p_num); 528: window_y = menu->p_y_off * ((menu->p_count - 1) - p_num); 529: break; 530: case RIGHT: 531: window_x = menu->p_x_off * p_num; 532: window_y = menu->p_y_off * ((menu->p_count - 1) - p_num); 533: break; 534: case CENTER: 535: window_x = 0; 536: window_y = menu->p_y_off * ((menu->p_count - 1) - p_num); 537: break; 538: default: 539: /* Error! Invalid style parameter. */ 540: _XMErrorCode = XME_STYLE_PARAM; 541: return(_FAILURE); 542: } 543: 544: /* 545: * If the newly compute pane coordinates differ from the 546: * current coordinates, reset the current coordinates and 547: * reconfigure the pane. 548: */ 549: if ( 550: (window_x != p_ptr->window_x) || 551: (window_y != p_ptr->window_y) 552: ){ 553: /* 554: * Reset the coordinates and schedule 555: * the pane for reconfiguration. 556: */ 557: p_ptr->window_x = window_x; 558: p_ptr->window_y = window_y; 559: config_p = TRUE; 560: } 561: 562: /* 563: * If the local pane width and height differs from the 564: * menu pane width and height, reset the local values. 565: */ 566: if ( 567: (p_ptr->window_w != menu->p_width) || 568: (p_ptr->window_h != menu->p_height) 569: ){ 570: /* 571: * Reset window width and height and schedule 572: * the pane for reconfiguration. 573: */ 574: p_ptr->window_w = menu->p_width; 575: p_ptr->window_h = menu->p_height; 576: config_p = TRUE; 577: } 578: 579: /* 580: * If we need to reconfigure the pane window do it now. 581: */ 582: if (config_p == TRUE) { 583: /* 584: * If the pane window has already been created then 585: * reconfigure the existing window, otherwise queue 586: * it for creation with the new configuration. 587: */ 588: if (p_ptr->window) { 589: XConfigureWindow( 590: p_ptr->window, 591: p_ptr->window_x, p_ptr->window_y, 592: p_ptr->window_w, p_ptr->window_h 593: ); 594: } 595: else { 596: if (_XMWinQueAddPane(menu, p_ptr) == _FAILURE) { 597: return(_FAILURE); 598: } 599: } 600: } 601: 602: /* 603: * Recompute label X position. 604: */ 605: switch (menu->p_style) { 606: case LEFT: 607: p_ptr->label_x = menu->p_x_off + menu->p_fnt_pad; 608: break; 609: case RIGHT: 610: p_ptr->label_x = menu->p_width - 611: (p_ptr->label_width + menu->p_x_off + menu->p_fnt_pad); 612: break; 613: case CENTER: 614: p_ptr->label_x = (menu->p_width - p_ptr->label_width) >> 1; 615: break; 616: default: 617: /* Error! Invalid style parameter. */ 618: _XMErrorCode = XME_STYLE_PARAM; 619: return(_FAILURE); 620: } 621: /* 622: * Recompute label Y positions. 623: */ 624: p_ptr->label_uy = menu->p_fnt_pad; 625: p_ptr->label_ly = (menu->p_height - menu->flag_height) + menu->p_fnt_pad; 626: 627: /* 628: * All went well, return successfully. 629: */ 630: _XMErrorCode = XME_NO_ERROR; 631: return(_SUCCESS); 632: } 633: 634: 635: 636: /* 637: * _XMRecomputeSelection - Internal subroutine to recompute 638: * selection window dependencies. 639: */ 640: int 641: _XMRecomputeSelection(menu, s_ptr, s_num) 642: register XMenu *menu; /* Menu object being recomputed. */ 643: register XMSelect *s_ptr; /* Selection pointer. */ 644: register int s_num; /* Selection sequence number. */ 645: { 646: register Bool config_s = FALSE; /* Reconfigure selection window? */ 647: 648: /* 649: * If the selection serial numbers are out of order, begin 650: * resequencing selections. Recompute selection window coordinates 651: * and serial number. 652: * 653: * When selections are created they are given a serial number of 654: * -1, this causes this routine to give a new selection 655: * its initial coordinates and serial number. 656: */ 657: if (s_ptr->serial != s_num) { 658: /* 659: * Fix the sequence number. 660: */ 661: s_ptr->serial = s_num; 662: /* 663: * Recompute window X and Y coordinates. 664: */ 665: s_ptr->window_x = menu->s_x_off; 666: s_ptr->window_y = menu->flag_height + (menu->s_y_off * s_num); 667: /* 668: * We must reconfigure the window. 669: */ 670: config_s = TRUE; 671: } 672: 673: /* 674: * If the local selection width and height differs from the 675: * menu selection width and height, reset the local values. 676: */ 677: if ( 678: (s_ptr->window_w != menu->s_width) || 679: (s_ptr->window_h != menu->s_height) 680: ){ 681: /* 682: * We must reconfigure the window. 683: */ 684: config_s = TRUE; 685: /* 686: * Reset window width and height. 687: */ 688: s_ptr->window_w = menu->s_width; 689: s_ptr->window_h = menu->s_height; 690: } 691: 692: /* 693: * If we need to reconfigure the selection window do it now. 694: */ 695: if (config_s == TRUE) { 696: /* 697: * If the selection window has already been created then 698: * reconfigure the existing window, otherwise queue it 699: * for creation with the new configuration. 700: */ 701: if (s_ptr->window) { 702: XConfigureWindow( 703: s_ptr->window, 704: s_ptr->window_x, s_ptr->window_y, 705: s_ptr->window_w, s_ptr->window_h 706: ); 707: } 708: else { 709: if (_XMWinQueAddSelection(menu, s_ptr) == _FAILURE) { 710: return(_FAILURE); 711: } 712: } 713: } 714: 715: /* 716: * Recompute label X position. 717: */ 718: switch (menu->s_style) { 719: case LEFT: 720: s_ptr->label_x = menu->s_bdr_width + menu->s_fnt_pad; 721: break; 722: case RIGHT: 723: s_ptr->label_x = menu->s_width - 724: (s_ptr->label_width + menu->s_bdr_width + menu->s_fnt_pad); 725: break; 726: case CENTER: 727: s_ptr->label_x = (menu->s_width - s_ptr->label_width) >> 1; 728: break; 729: default: 730: /* Error! Invaild style parameter. */ 731: _XMErrorCode = XME_STYLE_PARAM; 732: return(_FAILURE); 733: } 734: /* 735: * Recompute label Y position. 736: */ 737: s_ptr->label_y = menu->s_fnt_pad + menu->s_bdr_width; 738: 739: /* 740: * All went well, return successfully. 741: */ 742: _XMErrorCode = XME_NO_ERROR; 743: return(_SUCCESS); 744: } 745: 746: 747: 748: /* 749: * _XMTransToOrigin - Internal subroutine to translate the point at 750: * the center of the current pane and selection to the 751: * the menu origin. 752: * 753: * WARNING! ****** Be certain that all menu depencies have been 754: * recomputed before calling this routine or 755: * unpredicable results will follow. 756: */ 757: _XMTransToOrigin(menu, p_ptr, s_ptr, x_pos, y_pos, orig_x, orig_y) 758: register XMenu *menu; /* Menu being computed against. */ 759: register XMPane *p_ptr; /* Current pane pointer. */ 760: register XMSelect *s_ptr; /* Current selection pointer. */ 761: int x_pos; /* X coordinate of point to translate. */ 762: int y_pos; /* Y coordinate of point to translate. */ 763: int *orig_x; /* Return value X coord. of the menu origin. */ 764: int *orig_y; /* Return value Y coord. of the menu origin. */ 765: { 766: register int l_orig_x; /* Local X coordinate of the menu origin. */ 767: register int l_orig_y; /* local Y coordinate of the menu origin. */ 768: 769: /* 770: * Translate the menu origin such that the cursor hot point will be in the 771: * center of the desired current selection and pane. 772: */ 773: 774: /* 775: * First translate to the upper left of the current selection window. 776: */ 777: l_orig_x = x_pos - (menu->s_width >> 1); 778: l_orig_y = y_pos - (menu->s_height >> 1); 779: 780: /* 781: * Then translate to the upper left of the current pane window. 782: */ 783: l_orig_x -= (s_ptr->window_x + menu->p_bdr_width); 784: l_orig_y -= (s_ptr->window_y + menu->p_bdr_width); 785: 786: /* 787: * Finally translate to the upper left of the menu. 788: */ 789: l_orig_x -= p_ptr->window_x; 790: l_orig_y -= p_ptr->window_y; 791: 792: /* 793: * Set the return values. 794: */ 795: *orig_x = l_orig_x; 796: *orig_y = l_orig_y; 797: } 798: 799: 800: 801: /* 802: * _XMRefreshPaneLabels - Internal subroutine that refreshes 803: * the labels in a menu pane. 804: */ 805: _XMRefreshPaneText(menu, pane) 806: register XMenu *menu; 807: register XMPane *pane; 808: { 809: /* 810: * First clear the pane. 811: */ 812: XClear(pane->window); 813: /* 814: * Then redraw the label text. 815: */ 816: XTextMask( 817: pane->window, 818: pane->label_x, pane->label_uy, 819: pane->label, pane->label_length, 820: menu->p_fnt_info->id, 821: menu->p_frg_color 822: ); 823: XTextMask( 824: pane->window, 825: pane->label_x, pane->label_ly, 826: pane->label, pane->label_length, 827: menu->p_fnt_info->id, 828: menu->p_frg_color 829: ); 830: } 831: 832: 833: 834: /* 835: * _XMRefreshPane - Internal subroutine to completely refresh 836: * the contents of a pane. 837: */ 838: _XMRefreshPane(menu,pane) 839: register XMenu *menu; 840: register XMPane *pane; 841: { 842: register XMSelect *s_list = pane->s_list; 843: register XMSelect *s_ptr; 844: 845: /* 846: * First clear the pane. 847: */ 848: XClear(pane->window); 849: /* 850: * Then redraw the label text. 851: */ 852: XTextMask( 853: pane->window, 854: pane->label_x, pane->label_uy, 855: pane->label, pane->label_length, 856: menu->p_fnt_info->id, 857: menu->p_frg_color 858: ); 859: XTextMask( 860: pane->window, 861: pane->label_x, pane->label_ly, 862: pane->label, pane->label_length, 863: menu->p_fnt_info->id, 864: menu->p_frg_color 865: ); 866: /* 867: * Finally refresh each selection. 868: */ 869: for (s_ptr = s_list->next; s_ptr != s_list; s_ptr = s_ptr->next){ 870: _XMRefreshSelection(menu, s_ptr); 871: } 872: } 873: 874: 875: 876: /* 877: * _XMRefreshSelection - Internal subroutine that refreshes 878: * a single selection window. 879: */ 880: _XMRefreshSelection(menu, select) 881: register XMenu *menu; 882: register XMSelect *select; 883: { 884: register int width = select->window_w; 885: register int height = select->window_h; 886: register int bdr_width = menu->s_bdr_width; 887: 888: if (select->activated) { 889: if (menu->menu_mode == INVERT) { 890: XPixSet(select->window, 0, 0, width, height, menu->s_frg_color); 891: XTextMask( 892: select->window, 893: select->label_x, select->label_y, 894: select->label, select->label_length, 895: menu->s_fnt_info->id, 896: menu->bkgnd_color 897: ); 898: } 899: else { 900: /* 901: * Since most drawing routines with arbitrary width lines 902: * are slow compared to raster-ops lets use a raster-op to 903: * draw the boxes. 904: */ 905: XPixSet(select->window, 0, 0, width, height, menu->bkgnd_color); 906: XPixSet( 907: select->window, 908: 0, 0, 909: (width - bdr_width), bdr_width, 910: menu->s_bdr_color 911: ); 912: XPixSet( 913: select->window, 914: (0 + (width - bdr_width)), 0, 915: bdr_width, (height - bdr_width), 916: menu->s_bdr_color 917: ); 918: XPixSet( 919: select->window, 920: (0 + bdr_width), (0 + (height - bdr_width)), 921: (width - bdr_width), bdr_width, 922: menu->s_bdr_color 923: ); 924: XPixSet( 925: select->window, 926: 0, (0 + bdr_width), 927: bdr_width, (height - bdr_width), 928: menu->s_bdr_color 929: ); 930: XTextMask( 931: select->window, 932: select->label_x, select->label_y, 933: select->label, select->label_length, 934: menu->s_fnt_info->id, 935: menu->s_frg_color 936: ); 937: } 938: } 939: else { 940: XClear(select->window); 941: XTextMask( 942: select->window, 943: select->label_x, select->label_y, 944: select->label, select->label_length, 945: menu->s_fnt_info->id, 946: menu->s_frg_color 947: ); 948: } 949: }