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