|
|
1.1 ! root 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.