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