|
|
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.