root/branches/2.1/oldXMenu/Internal.c

Revision 3207, 26.3 kB (checked in by miyoshi, 5 years ago)

Sync up with Emacs-21.2.

  • Property svn:eol-style set to native
Line 
1 #include "copyright.h"
2
3 /* $Header: /cvsroot/emacs/emacs/oldXMenu/Internal.c,v 1.1 1999/10/03 19:35:07 fx 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 visible) routines.
10  *
11  *      Author:         Tony Della Fera, DEC
12  *                      November, 1985
13  *
14  */
15
16 #include <config.h>
17 #include "XMenuInt.h"
18
19 /*
20  * Toggle color macro.
21  */
22 #define toggle_color(x) \
23         ((x) == menu->bkgnd_color ? menu->s_frg_color : menu->bkgnd_color)
24
25 /*
26  * Internal Window creation queue sizes.
27  */
28 #define S_QUE_SIZE      300
29 #define P_QUE_SIZE      20
30 #define BUFFER_SIZE     (S_QUE_SIZE >= P_QUE_SIZE ? S_QUE_SIZE : P_QUE_SIZE)
31
32
33 /*
34  * XMWinQue - Internal window creation queue datatype.
35  */
36 typedef struct _xmwinquedef {
37     int sq_size;
38     XMSelect *sq[S_QUE_SIZE];
39     XMSelect **sq_ptr;
40     int pq_size;
41     XMPane *pq[P_QUE_SIZE];
42     XMPane **pq_ptr;
43 } XMWinQue;
44
45 /*
46  * _XMWinQue - Internal static window creation queue.
47  */
48 static Bool _XMWinQueIsInit = False;
49 static XMWinQue _XMWinQue;
50
51 /*
52  * _XMErrorCode - Global XMenu error code.
53  */
54 int _XMErrorCode = XME_NO_ERROR;
55 /*
56  * _XMErrorList - Global XMenu error code description 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         register int i;
100
101         for (i = 0; i < S_QUE_SIZE; i++)
102           _XMWinQue.sq[i] = 0;
103
104         for (i = 0; i < P_QUE_SIZE; i++)
105           _XMWinQue.pq[i] = 0;
106
107         _XMWinQue.sq_size = _XMWinQue.pq_size = 0;
108
109         /*
110          * Initialize the next free location pointers.
111          */
112         _XMWinQue.sq_ptr = _XMWinQue.sq;
113         _XMWinQue.pq_ptr = _XMWinQue.pq;
114     }
115 }
116
117
118
119 /*
120  * _XMWinQueAddPane - Internal routine to add a pane to the pane
121  *                    window queue.
122  */
123 int
124 _XMWinQueAddPane(display, menu, p_ptr)
125     register Display *display;
126     register XMenu *menu;       /* Menu being manipulated. */
127     register XMPane *p_ptr;     /* XMPane being queued. */
128 {
129     /*
130      * If the queue is currently full then flush it.
131      */
132     if (_XMWinQue.pq_size == P_QUE_SIZE) {
133         if (_XMWinQueFlush(display, menu, 0, 0) == _FAILURE) return(_FAILURE);
134     }
135
136     /*
137      * Insert the new XMPane pointer and increment the queue pointer
138      * and the queue size.
139      */
140     *_XMWinQue.pq_ptr = p_ptr;
141     _XMWinQue.pq_ptr++;
142     _XMWinQue.pq_size++;
143
144     /*
145      * All went well, return successfully.
146      */
147     _XMErrorCode = XME_NO_ERROR;
148     return(_SUCCESS);
149 }
150
151
152
153 /*
154  * _XMWinQueAddSelection - Internal routine to add a selection to
155  *                         the selection window queue.
156  */
157 int
158 _XMWinQueAddSelection(display, menu, s_ptr)
159     register Display *display;
160     register XMenu *menu;       /* Menu being manipulated. */
161     register XMSelect *s_ptr;   /* XMSelection being queued. */
162 {
163     /*
164      * If this entry will overflow the queue then flush it.
165      */
166     if (_XMWinQue.sq_size == S_QUE_SIZE) {
167         if (_XMWinQueFlush(display, menu, 0, 0) == _FAILURE) return(_FAILURE);
168     }
169
170     /*
171      * Insert the new XMSelect pointer and increment the queue pointer
172      * and the queue size.
173      */
174     *_XMWinQue.sq_ptr = s_ptr;
175     _XMWinQue.sq_ptr++;
176     _XMWinQue.sq_size++;
177
178     /*
179      * All went well, return successfully.
180      */
181     _XMErrorCode = XME_NO_ERROR;
182     return(_SUCCESS);
183 }
184
185
186
187 /*
188  * _XMWinQueFlush - Internal routine to flush the pane and
189  *                  selection window queues.
190  */
191 int
192 _XMWinQueFlush(display, menu, pane, select)
193     register Display *display;
194     register XMenu *menu;               /* Menu being manipulated. */
195     register XMPane *pane;              /* Current pane. */
196 {
197     register int pq_index;              /* Pane queue index. */
198     register int sq_index;              /* Selection queue index. */
199     register XMPane *p_ptr;             /* XMPane pointer. */
200     register XMSelect *s_ptr;           /* XMSelect pointer. */
201     unsigned long valuemask;            /* Which attributes to set. */
202     XSetWindowAttributes *attributes;   /* Attributes to be set. */
203
204     /*
205      * If the pane window queue is not empty...
206      */
207    
208     if (_XMWinQue.pq_size > 0) {
209         /*
210          * set up attributes for pane window to be created.
211          */
212         valuemask = (CWBackPixmap | CWBorderPixel | CWOverrideRedirect);
213         attributes = (XSetWindowAttributes *)malloc(sizeof(XSetWindowAttributes));
214         attributes->border_pixel = menu->p_bdr_color;
215         attributes->background_pixmap = menu->inact_pixmap;
216         attributes->override_redirect = True;
217        
218         /*
219          * Create all the pending panes in order, so that the
220          * current pane will be on top, with the others
221          * stacked appropriately under it.
222          */
223         for (pq_index = _XMWinQue.pq_size - 1;
224              pq_index >= 0;
225              pq_index--)
226           {
227               p_ptr = _XMWinQue.pq[pq_index];  /* Retrieve next pane. */
228               if (p_ptr == pane) break;
229               p_ptr->window = XCreateWindow(display,
230                                             menu->parent,
231                                             p_ptr->window_x,
232                                             p_ptr->window_y,
233                                             p_ptr->window_w,
234                                             p_ptr->window_h,
235                                             menu->p_bdr_width,
236                                             CopyFromParent,
237                                             InputOutput,
238                                             CopyFromParent,
239                                             valuemask,
240                                             attributes);
241               XMakeAssoc(display, menu->assoc_tab, p_ptr->window, p_ptr);
242               XSelectInput(display, p_ptr->window, menu->p_events);
243           }
244         for (pq_index = 0;
245              pq_index < _XMWinQue.pq_size;
246              pq_index++)
247           {
248               p_ptr = _XMWinQue.pq[pq_index];   /* Retrieve next pane. */
249               p_ptr->window = XCreateWindow(display,
250                                             menu->parent,
251                                             p_ptr->window_x,
252                                             p_ptr->window_y,
253                                             p_ptr->window_w,
254                                             p_ptr->window_h,
255                                             menu->p_bdr_width,
256                                             CopyFromParent,
257                                             InputOutput,
258                                             CopyFromParent,
259                                             valuemask,
260                                             attributes);
261               XMakeAssoc(display, menu->assoc_tab, p_ptr->window, p_ptr);
262               XSelectInput(display, p_ptr->window, menu->p_events);
263               if (p_ptr == pane) break;
264         }
265
266         /*
267          * Reset the pane queue pointer and size.
268          */
269         _XMWinQue.pq_size = 0;
270         _XMWinQue.pq_ptr = _XMWinQue.pq;
271     }
272
273     /*
274      * If the selection window queue is not empty...
275      */
276    
277     if (_XMWinQue.sq_size > 0) {
278
279         for (sq_index = 0; sq_index < _XMWinQue.sq_size; sq_index++) {
280             /*
281              * Retrieve the XMSelect pointer.
282              */
283             s_ptr = _XMWinQue.sq[sq_index];
284             s_ptr->window = XCreateWindow(display,
285                                    s_ptr->parent_p->window,
286                                    s_ptr->window_x,
287                                    s_ptr->window_y,
288                                    s_ptr->window_w,
289                                    s_ptr->window_h,
290                                    0,                /* border width*/
291                                    CopyFromParent,
292                                    InputOnly,
293                                    CopyFromParent,
294                                    0,
295                                    attributes);
296            
297             /*
298              * Insert the new window id and its
299              * associated XMSelect structure into the
300              * association table.
301              */
302             XMakeAssoc(display, menu->assoc_tab, s_ptr->window, s_ptr);
303             XSelectInput(display, s_ptr->window, menu->s_events);
304         }
305
306         /*
307          * Reset the selection queue pointer and size.
308          */
309         _XMWinQue.sq_size = 0;
310         _XMWinQue.sq_ptr = _XMWinQue.sq;
311     }
312
313     /*
314      * Flush X's internal queues.
315      */
316     XFlush(display);
317
318     /*
319      * All went well, return successfully.
320      */
321     _XMErrorCode = XME_NO_ERROR;
322     return(_SUCCESS);
323 }
324
325
326
327 /*
328  * _XMGetPanePtr -      Given a menu pointer and a pane index number, return
329  *                      a pane pointer that points to the indexed pane.
330  */
331 XMPane *
332 _XMGetPanePtr(menu, p_num)
333     register XMenu *menu;       /* Menu to find the pane in. */
334     register int p_num;         /* Index number of pane to find. */
335 {
336     register XMPane *p_ptr;     /* Pane pointer to be returned. */
337     register int i;             /* Loop counter. */
338
339     /*
340      * Is the pane number out of range?
341      */
342     if ((p_num < 0) || (p_num > (menu->p_count - 1))) {
343         _XMErrorCode = XME_P_NOT_FOUND;
344         return(NULL);
345     }
346
347     /*
348      * Find the right pane.
349      */
350     p_ptr = menu->p_list->next;
351     for (i = 0; i < p_num; i++) p_ptr = p_ptr->next;
352
353     /*
354      * Return successfully.
355      */
356     _XMErrorCode = XME_NO_ERROR;
357     return(p_ptr);
358 }
359
360
361
362 /*
363  * _XMGetSelectionPtr - Given pane pointer and a selection index number,
364  *                      return a selection pointer that points to the
365  *                      indexed selection.
366  */
367 XMSelect *
368 _XMGetSelectionPtr(p_ptr, s_num)
369     register XMPane *p_ptr;     /* Pane to find the selection in. */
370     register int s_num;         /* Index number of the selection to find. */
371 {
372     register XMSelect *s_ptr;   /* Selection pointer to be returned. */
373     register int i;             /* Loop counter. */
374    
375     /*
376      * Is the selection number out of range?
377      */
378     if ((s_num < 0) || (s_num > (p_ptr->s_count - 1))) {
379         _XMErrorCode = XME_S_NOT_FOUND;
380         return(NULL);
381     }
382
383     /*
384      * Find the right selection.
385      */
386     s_ptr = p_ptr->s_list->next;
387     for (i = 0; i < s_num; i++) s_ptr = s_ptr->next;
388
389     /*
390      * Return successfully.
391      */
392     _XMErrorCode = XME_NO_ERROR;
393     return(s_ptr);
394 }
395
396
397
398 /*
399  * _XMRecomputeGlobals - Internal subroutine to recompute menu wide
400  *                       global values.
401  */
402 _XMRecomputeGlobals(display, menu)
403     register Display *display; /*X11 display variable. */       
404     register XMenu *menu;       /* Menu object to compute from. */
405 {
406     register XMPane *p_ptr;     /* Pane pointer. */
407     register XMSelect *s_ptr;   /* Selection pointer. */
408
409     register int max_p_label = 0;       /* Maximum pane label width. */
410     register int max_s_label = 0;       /* Maximum selection label width. */
411     register int s_count = 0;           /* Maximum selection count. */
412
413     int p_s_pad;                /* Pane <-> selection padding. */
414     int p_s_diff;               /* Pane <-> selection separation. */
415
416     int p_height;               /* Pane window height. */
417     int p_width;                /* Pane window width. */
418     int s_width;                /* Selection window width. */
419
420     int screen;                 /* DefaultScreen holder. */
421    
422     /*
423      * For each pane...
424      */
425     for (
426         p_ptr = menu->p_list->next;
427         p_ptr != menu->p_list;
428         p_ptr = p_ptr->next
429     ){
430        
431         /*
432          * Recompute maximum pane label width.
433          */
434         max_p_label = max(max_p_label, p_ptr->label_width);
435
436         /*
437          * Recompute maximum selection count.
438          */
439         s_count = max(s_count, p_ptr->s_count);
440
441         /*
442          * For each selection in the current pane...
443          */
444         for (
445             s_ptr = p_ptr->s_list->next;
446             s_ptr != p_ptr->s_list;
447             s_ptr = s_ptr->next
448         ){
449
450             /*
451              * Recompute maximum selection label width.
452              */
453             max_s_label = max(max_s_label, s_ptr->label_width);
454         }
455     }
456
457     /*
458      * Recompute pane height.
459      */
460     p_height = (menu->flag_height << 1) + (menu->s_y_off * s_count);
461
462     /*
463      * Recompute horizontal padding between the pane window and the
464      * selection windows.
465      */
466     p_s_pad = menu->p_x_off << 1;
467
468     /*
469      * Recompute pane and selection window widths.
470      * This is done by first computing the window sizes from the maximum
471      * label widths.  If the spacing between the selection window and the
472      * containing pane window is less than the pane selection padding value
473      * (twice the pane X offset) then change the size of the pane to be
474      * the size of the selection window plus the padding.  If, however the
475      * spacing between the selection window and the containing pane window
476      * is more than the pane selection padding value increase the size of
477      * the selection to its maximum possible value (the pane width minus
478      * the pane selection padding value).
479      */
480     p_width = max_p_label + p_s_pad;
481     s_width = max_s_label + (menu->s_fnt_pad << 1) + (menu->s_bdr_width << 1);
482     p_s_diff = p_width - s_width;
483     if (p_s_diff < p_s_pad) {
484         p_width = s_width + p_s_pad;
485     }
486     else if (p_s_diff > p_s_pad) {
487         s_width = p_width - p_s_pad;
488     }
489
490     /*
491      * Reset menu wide global values.
492      */
493     menu->s_count = s_count;
494     menu->p_height = p_height;
495     menu->p_width = p_width;
496     menu->s_width = s_width;
497
498     /*
499      * Ensure that the origin of the menu is placed so that
500      * None of the panes ore selections are off the screen.
501      */
502     screen = DefaultScreen(display);
503     if (menu->x_pos + menu->width > DisplayWidth(display, screen))
504             menu->x_pos = DisplayWidth(display, screen) - menu->width;
505     else if (menu->x_pos < 0) menu->x_pos = 0;
506     if(menu->y_pos + menu->height > DisplayHeight(display, screen))
507             menu->y_pos = DisplayHeight(display, screen) - menu->height;
508     else if (menu->y_pos < 0) menu->y_pos = 0;
509 }
510
511
512 /*
513  * _XMRecomputePane - Internal subroutine to recompute pane
514  *                    window dependencies.
515  */
516 int
517 _XMRecomputePane(display, menu, p_ptr, p_num)
518     register Display *display;  /* Standard X display variable. */
519     register XMenu *menu;       /* Menu object being recomputed. */
520     register XMPane *p_ptr;     /* Pane pointer. */
521     register int p_num;         /* Pane sequence number. */
522 {
523     register int window_x;      /* Recomputed window X coordinate. */
524     register int window_y;      /* Recomputed window Y coordinate. */
525    
526     unsigned long change_mask;  /* Value mask to reconfigure window. */
527     XWindowChanges *changes;    /* Values to use in configure window. */
528    
529     register Bool config_p = False;     /* Reconfigure pane window? */
530
531     /*
532      * Update the pane serial number.
533      */
534     p_ptr->serial = p_num;
535
536     /*
537      * Recompute window X and Y coordinates.
538      */
539     switch (menu->menu_style) {
540         case LEFT:
541             window_x = menu->p_x_off * ((menu->p_count - 1) - p_num);
542             window_y = menu->p_y_off * ((menu->p_count - 1) - p_num);
543             break;
544         case RIGHT:
545             window_x = menu->p_x_off * p_num;
546             window_y = menu->p_y_off * ((menu->p_count - 1) - p_num);
547             break;
548         case CENTER:
549             window_x = 0;
550             window_y = menu->p_y_off * ((menu->p_count - 1) - p_num);
551             break;
552         default:
553             /* Error! Invalid style parameter. */
554             _XMErrorCode = XME_STYLE_PARAM;
555             return(_FAILURE);
556     }
557     window_x += menu->x_pos;
558     window_y += menu->y_pos;
559
560     /*
561      * If the newly compute pane coordinates differ from the
562      * current coordinates, reset the current coordinates and
563      * reconfigure the pane.
564      */
565     if (
566         (window_x != p_ptr->window_x) ||
567         (window_y != p_ptr->window_y)
568     ){
569         /*
570          * Reset the coordinates and schedule
571          * the pane for reconfiguration.
572          */
573         p_ptr->window_x = window_x;
574         p_ptr->window_y = window_y;
575         config_p = True;
576     }
577
578     /*
579      * If the local pane width and height differs from the
580      * menu pane width and height, reset the local values.
581      */
582     if (
583         (p_ptr->window_w != menu->p_width) ||
584