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