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