1 /* Copyright Massachusetts Institute of Technology 1985 */
6 Copyright (C) 1993, 1994, 2001, 2002, 2003, 2004, 2005, 2006,
7 2007, 2008 Free Software Foundation, Inc.
9 This program is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
24 * XMenu: MIT Project Athena, X Window system menu package
26 * XMenuCreate - Creates an X window system menu object.
28 * Author: Tony Della Fera, DEC
37 #ifdef EMACS_BITMAP_FILES
38 #include "../src/bitmaps/dimple1.xbm"
39 #include "../src/bitmaps/dimple3.xbm"
40 #include "../src/bitmaps/gray1.xbm"
41 #include "../src/bitmaps/gray3.xbm"
42 #include "../src/bitmaps/crosswv.xbm"
44 #include "../src/bitmaps/leftptr.xbm"
45 #include "../src/bitmaps/leftpmsk.xbm"
46 #include "../src/bitmaps/rtptr.xbm"
47 #include "../src/bitmaps/rtpmsk.xbm"
48 #include "../src/bitmaps/cntrptr.xbm"
49 #include "../src/bitmaps/cntrpmsk.xbm"
50 #include "../src/bitmaps/stipple.xbm"
55 #include <X11/bitmaps/dimple1>
56 #include <X11/bitmaps/dimple3>
57 #include <X11/bitmaps/gray1>
58 #include <X11/bitmaps/gray3>
59 #include <X11/bitmaps/cross_weave>
61 #include <X11/bitmaps/left_ptr>
62 #include <X11/bitmaps/left_ptrmsk>
63 #include <X11/bitmaps/right_ptr>
64 #include <X11/bitmaps/right_ptrmsk>
65 #include <X11/bitmaps/cntr_ptr>
66 #include <X11/bitmaps/cntr_ptrmsk>
67 #include <X11/bitmaps/stipple>
71 #include "[-.src.bitmaps]dimple1.xbm"
72 #include "[-.src.bitmaps]dimple3.xbm"
73 #include "[-.src.bitmaps]gray1.xbm"
74 #include "[-.src.bitmaps]gray3.xbm"
75 #include "[-.src.bitmaps]crosswv.xbm"
77 #include "[-.src.bitmaps]leftptr.xbm"
78 #include "[-.src.bitmaps]leftpmsk.xbm"
79 #include "[-.src.bitmaps]rtptr.xbm"
80 #include "[-.src.bitmaps]rtpmsk.xbm"
81 #include "[-.src.bitmaps]cntrptr.xbm"
82 #include "[-.src.bitmaps]cntrpmsk.xbm"
83 #include "[-.src.bitmaps]stipple.xbm"
86 #endif /* not EMACS_BITMAP_FILES */
90 #define DEF_MENU_STYLE LEFT
91 #define DEF_MENU_MODE BOX
92 #define DEF_INACT_PNUM 3
93 #define MAX_INACT_PNUM 4
95 #define DEF_P_STYLE CENTER
97 #define DEF_P_EVENTS (EnterWindowMask | ExposureMask)
98 #define DEF_P_FNT_NAME "fixed"
99 #define DEF_P_SPREAD 0.5
100 #define DEF_P_BDR_WIDTH 2
102 #define DEF_S_STYLE LEFT
103 #define DEF_S_EVENTS (EnterWindowMask | LeaveWindowMask)
104 #define DEF_S_FNT_NAME "fixed"
105 #define DEF_S_SPREAD 0.10
106 #define DEF_S_BDR_WIDTH 1
108 #define XASSOC_TABLE_SIZE 64
110 #define TILE_BUF_SIZE 5
114 char *x_get_resource_string ();
119 XAllocDisplayColor(display
, map
, colorName
, color
, junk
)
126 return (colorName
!=0 &&
127 XParseColor(display
, map
, colorName
, color
) &&
128 XAllocColor(display
, map
, color
));
133 XMenuCreate(display
, parent
, def_env
)
134 Display
*display
; /* ID of previously opened display */
135 Window parent
; /* Window ID of the menu's parent window. */
136 register char *def_env
; /* X Defaults program environment name. */
138 register int i
; /* Loop counter. */
139 register int j
; /* Loop counter. */
140 register char *def_val
; /* X Default value temp variable. */
142 register XMenu
*menu
; /* Pointer to the new menu. */
143 XMStyle menu_style
; /* Menu display style. */
144 XMMode menu_mode
; /* Menu display mode. */
145 XMPane
*pane
; /* Pane list header. */
146 XAssocTable
*assoc_tab
; /* XAssocTable pointer. */
148 int freeze
; /* Freeze server mode. */
149 int reverse
; /* Reverse video mode. */
151 XMStyle p_style
; /* Pane display style. */
152 char *p_fnt_name
; /* Flag font name. */
153 XFontStruct
*p_fnt_info
; /* Flag font structure */
154 int p_fnt_pad
; /* Flag font padding in pixels. */
155 double p_spread
; /* Pane spread in flag height fractions. */
156 int p_fnt_height
; /* Pane character height. */
157 int p_bdr_width
; /* Pane border width. */
158 int flag_height
; /* Flag window height. */
159 int p_height
; /* Pane window height. */
160 int p_x_off
; /* Pane X offset. */
161 int p_y_off
; /* Pane Y offset. */
162 GC pane_GC
; /* Pane graphics context. */
164 XMStyle s_style
; /* Selection display style. */
165 char *s_fnt_name
; /* Selection font name. */
166 XFontStruct
*s_fnt_info
; /* Selection font structure. */
167 int s_fnt_pad
; /* Selection font padding in pixels. */
168 int s_fnt_height
; /* Selection font character height */
169 double s_spread
; /* Select spread in line height fractions. */
170 int s_bdr_width
; /* Highlight border width. */
171 int s_height
; /* Selection window height. */
172 int s_x_off
; /* Selection window X offset. */
173 int s_y_off
; /* Selection window Y offset. */
174 GC normal_select_GC
; /* GC used for normal video selection. */
175 GC inverse_select_GC
; /* GC used for inverse video selection. */
176 GC inact_GC
; /* GC for inactive pane header and */
178 GC inact_GC_noexpose
;
180 XColor color_def
; /* Temp color definition holder. */
181 XColor screen_def
; /* Temp screen color definition holder */
182 XColor p_bdr_color
; /* Color of border. */
183 XColor s_bdr_color
; /* Color of highlight. */
184 XColor p_frg_color
; /* Color of pane foreground color. */
185 XColor s_frg_color
; /* Color of selection foreground. */
186 XColor bkgnd_color
; /* Color of background.. */
187 XColor mouse_color
; /* Color of mouse cursor. */
188 Cursor mouse_cursor
; /* Mouse cursor. */
189 Pixmap inact_bitmap
; /* Menu inactive pixmap. */
191 int inact_pnum
; /* Inactive background pattern number. */
193 Pixel p_bdr_pixel
; /* Pane border pixel. */
194 Pixel s_bdr_pixel
; /* Selection border pixel. */
195 Pixel p_frg_pixel
; /* Pane foreground pixel. */
196 Pixel s_frg_pixel
; /* Selection foreground pixel. */
197 Pixel bkgnd_pixel
; /* Menu background pixel. */
202 int status
; /* Return code from XReadBitmapFile. */
204 Pixmap cursor
; /* Cursor pixmap holder. */
205 Pixmap cursor_mask
; /* Cursor mask pixmap holder. */
206 Pixmap stipple_pixmap
; /* Stipple mask for half-tone text. */
207 unsigned long valuemask
;
210 Window root
= RootWindow (display
, DefaultScreen (display
));
213 * Calloc the XMenu structure and the initial pane.
215 menu
= (XMenu
*)calloc(1, sizeof(XMenu
));
217 _XMErrorCode
= XME_CALLOC
;
220 pane
= (XMPane
*)calloc(1, sizeof(XMPane
));
222 _XMErrorCode
= XME_CALLOC
;
227 * Create the XAssocTable
229 assoc_tab
= (XAssocTable
*)XCreateAssocTable(XASSOC_TABLE_SIZE
);
230 if(assoc_tab
== NULL
) {
231 _XMErrorCode
= XME_CREATE_ASSOC
;
236 * Set up the default environment name.
238 if (def_env
== NULL
|| *def_env
== '\0') def_env
= "XMenu";
241 * Set up internal fail-safe defaults.
244 reverse
= DEF_REVERSE
;
245 menu_style
= DEF_MENU_STYLE
;
246 menu_mode
= DEF_MENU_MODE
;
247 inact_pnum
= DEF_INACT_PNUM
;
249 p_style
= DEF_P_STYLE
;
250 p_spread
= DEF_P_SPREAD
;
251 p_fnt_name
= DEF_P_FNT_NAME
;
252 p_bdr_width
= DEF_P_BDR_WIDTH
;
254 s_style
= DEF_S_STYLE
;
255 s_spread
= DEF_S_SPREAD
;
256 s_fnt_name
= DEF_S_FNT_NAME
;
257 s_bdr_width
= DEF_S_BDR_WIDTH
;
260 * Get default values from X.
262 def_val
= x_get_resource_string ("menuFreeze", "MenuFreeze");
263 if (def_val
!= NULL
) {
264 if (strcmp(def_val
, "on") == 0) freeze
= 1;
265 else if (strcmp(def_val
, "off") == 0) freeze
= 0;
268 def_val
= x_get_resource_string ("menuReverseVideo", "MenuReverseVideo");
269 if (def_val
!= NULL
) {
270 if (strcmp(def_val
, "on") == 0) reverse
= 1;
271 else if (strcmp(def_val
, "off") == 0) reverse
= 0;
274 def_val
= x_get_resource_string ("menuStyle", "MenuStyle");
275 if (def_val
!= NULL
) {
276 if (strcmp(def_val
, "right_hand") == 0) menu_style
= RIGHT
;
277 else if (strcmp(def_val
, "left_hand") == 0) menu_style
= LEFT
;
278 else if (strcmp(def_val
, "center") == 0) menu_style
= CENTER
;
281 def_val
= x_get_resource_string ("menuMode", "MenuMode");
282 if (def_val
!= NULL
) {
283 if (strcmp(def_val
, "box") == 0) menu_mode
= BOX
;
284 else if (strcmp(def_val
, "invert") == 0) menu_mode
= INVERT
;
287 def_val
= x_get_resource_string ("menuMouse", "MenuMouse");
290 DisplayCells(display
, DefaultScreen(display
)) > 2 &&
291 XAllocDisplayColor(display
,
292 DefaultColormap(display
, DefaultScreen(display
)),
294 &mouse_color
, &color_def
)
297 XAllocDisplayColor(display
,
298 DefaultColormap(display
, DefaultScreen(display
)),
300 &mouse_color
, &color_def
)
303 else if (XAllocDisplayColor(display
,
304 DefaultColormap(display
, DefaultScreen(display
)),
306 &mouse_color
, &color_def
)
311 def_val
= x_get_resource_string ("menuBackground", "MenuBackground");
314 DisplayCells(display
, DefaultScreen(display
)) > 2 &&
315 XAllocDisplayColor(display
,
316 DefaultColormap(display
, DefaultScreen(display
)),
318 &bkgnd_color
, &color_def
)
321 XAllocDisplayColor(display
,
322 DefaultColormap(display
, DefaultScreen(display
)),
324 &bkgnd_color
, &color_def
)
326 else if (XAllocDisplayColor(display
,
327 DefaultColormap(display
, DefaultScreen(display
)),
329 &bkgnd_color
, &color_def
)
333 def_val
= x_get_resource_string ("menuInactivePattern", "MenuInactivePattern");
334 if (def_val
!= NULL
) {
335 if (strcmp(def_val
, "dimple1") == 0) inact_pnum
= 0;
336 else if (strcmp(def_val
, "dimple3") == 0) inact_pnum
= 1;
337 else if (strcmp(def_val
, "gray1") == 0) inact_pnum
= 2;
338 else if (strcmp(def_val
, "gray3") == 0) inact_pnum
= 3;
339 else if (strcmp(def_val
, "cross_weave") == 0) inact_pnum
= 4;
342 def_val
= x_get_resource_string ("paneStyle", "PaneStyle");
343 if (def_val
!= NULL
) {
344 if (strcmp(def_val
, "flush_left") == 0) p_style
= LEFT
;
345 else if (strcmp(def_val
, "flush_right") == 0) p_style
= RIGHT
;
346 else if (strcmp(def_val
, "center") == 0) p_style
= CENTER
;
349 def_val
= x_get_resource_string ("paneFont", "PaneFont");
350 if (def_val
!= NULL
) p_fnt_name
= def_val
;
352 def_val
= x_get_resource_string ("paneForeground", "PaneForeground");
355 DisplayCells(display
, DefaultScreen(display
)) > 2
357 XAllocDisplayColor(display
, DefaultColormap(display
,
358 DefaultScreen(display
)),
360 &p_frg_color
, &color_def
);
362 else if (reverse
) XAllocDisplayColor(display
,
363 DefaultColormap(display
,
364 DefaultScreen(display
)),
366 &p_frg_color
, &color_def
);
367 else XAllocDisplayColor(display
,
368 DefaultColormap(display
, DefaultScreen(display
)),
370 &p_frg_color
, &color_def
);
372 def_val
= x_get_resource_string ("paneBorder", "PaneBorder");
375 DisplayCells(display
, DefaultScreen(display
)) > 2 &&
376 XAllocDisplayColor(display
,
377 DefaultColormap(display
, DefaultScreen(display
)),
379 &p_bdr_color
, &color_def
)
382 XAllocDisplayColor(display
,
383 DefaultColormap(display
, DefaultScreen(display
)),
385 &p_bdr_color
, &color_def
)
387 else XAllocDisplayColor(display
,
388 DefaultColormap(display
, DefaultScreen(display
)),
390 &p_bdr_color
, &color_def
);
392 def_val
= x_get_resource_string ("paneBorderWidth", "PaneBorderWidth");
393 if (def_val
!= NULL
) p_bdr_width
= atoi(def_val
);
395 def_val
= x_get_resource_string ("paneSpread", "PaneSpread");
396 if (def_val
!= NULL
) p_spread
= atof(def_val
);
398 def_val
= x_get_resource_string ("selectionStyle", "SelectionStyle");
399 if (def_val
!= NULL
) {
400 if (strcmp(def_val
, "flush_left") == 0) s_style
= LEFT
;
401 else if (strcmp(def_val
, "flush_right") == 0) s_style
= RIGHT
;
402 else if (strcmp(def_val
, "center") == 0) s_style
= CENTER
;
405 def_val
= x_get_resource_string ("selectionFont", "SelectionFont");
406 if (def_val
!= NULL
) s_fnt_name
= def_val
;
408 def_val
= x_get_resource_string ("selectionForeground", "SelectionForeground");
411 DisplayCells(display
, DefaultScreen(display
)) > 2 &&
412 XAllocDisplayColor(display
,
413 DefaultColormap(display
, DefaultScreen(display
)),
415 &s_frg_color
, &color_def
)
418 XAllocDisplayColor(display
,
419 DefaultColormap(display
, DefaultScreen(display
)),
421 &s_frg_color
, &color_def
)
423 else if (XAllocDisplayColor(display
,
424 DefaultColormap(display
, DefaultScreen(display
)),
426 &s_frg_color
, &color_def
)
431 def_val
= x_get_resource_string ("selectionBorder", "SelectionBorder");
434 DisplayCells(display
, DefaultScreen(display
)) > 2 &&
435 XAllocDisplayColor(display
,
436 DefaultColormap(display
, DefaultScreen(display
)),
438 &s_bdr_color
, &color_def
)
441 XAllocDisplayColor(display
,
442 DefaultColormap(display
, DefaultScreen(display
)),
444 &s_bdr_color
, &color_def
)
446 else if (XAllocDisplayColor(display
,
447 DefaultColormap(display
, DefaultScreen(display
)),
449 &s_bdr_color
, &color_def
)
453 def_val
= x_get_resource_string ("selectionBorderWidth", "SelectionBorderWidth");
454 if (def_val
!= NULL
) s_bdr_width
= atoi(def_val
);
456 def_val
= x_get_resource_string ("selectionSpread", "SelectionSpread");
457 if (def_val
!= NULL
) s_spread
= atof(def_val
);
460 * Create and store the inactive pattern pixmap.
469 data
= (char *)dimple1_bits
;
470 width
= dimple1_width
;
471 height
= dimple1_height
;
475 data
= (char *)dimple3_bits
;
476 width
= dimple3_width
;
477 height
= dimple3_height
;
481 data
= (char *)gray1_bits
;
483 height
= gray1_height
;
487 data
= (char *)gray3_bits
;
489 height
= gray3_height
;
493 data
= (char *)cross_weave_bits
;
494 width
= cross_weave_width
;
495 height
= cross_weave_height
;
501 _XMErrorCode
= XME_STORE_BITMAP
;
506 XCreatePixmapFromBitmapData
507 (display
, root
, data
, width
, height
,
508 p_frg_color
.pixel
, bkgnd_color
.pixel
,
509 DisplayPlanes (display
, DefaultScreen (display
)));
513 * Load the mouse cursor.
516 switch (menu_style
) {
518 cursor
= XCreateBitmapFromData(display
,
523 cursor_mask
= XCreateBitmapFromData(display
,
528 mouse_cursor
= XCreatePixmapCursor(
531 &mouse_color
, &bkgnd_color
,
535 XFreePixmap(display
, cursor
);
536 XFreePixmap(display
, cursor_mask
);
539 cursor
= XCreateBitmapFromData(display
,
544 cursor_mask
= XCreateBitmapFromData(display
,
548 right_ptrmsk_height
);
549 mouse_cursor
= XCreatePixmapCursor(
552 &mouse_color
, &bkgnd_color
,
556 XFreePixmap(display
, cursor
);
557 XFreePixmap(display
, cursor_mask
);
560 cursor
= XCreateBitmapFromData(display
,
565 cursor_mask
= XCreateBitmapFromData(display
,
570 mouse_cursor
= XCreatePixmapCursor(
573 &mouse_color
, &bkgnd_color
,
577 XFreePixmap(display
, cursor
);
578 XFreePixmap(display
, cursor_mask
);
581 /* Error! Invalid style parameter. */
582 _XMErrorCode
= XME_STYLE_PARAM
;
585 if (mouse_cursor
== _X_FAILURE
) {
586 _XMErrorCode
= XME_CREATE_CURSOR
;
591 * Open the pane and selection fonts.
594 p_fnt_info
= XLoadQueryFont(display
, p_fnt_name
);
595 if (p_fnt_info
== NULL
) {
596 _XMErrorCode
= XME_OPEN_FONT
;
601 s_fnt_info
= XLoadQueryFont(display
, s_fnt_name
);
602 if (s_fnt_info
== NULL
) {
603 _XMErrorCode
= XME_OPEN_FONT
;
607 * Calculate the fixed padding value in pixels for each font.
609 p_fnt_height
= p_fnt_info
->max_bounds
.ascent
+ p_fnt_info
->max_bounds
.descent
;
610 s_fnt_height
= s_fnt_info
->max_bounds
.ascent
+ s_fnt_info
->max_bounds
.descent
;
611 p_fnt_pad
= s_spread
* p_fnt_height
;
612 s_fnt_pad
= s_spread
* s_fnt_height
;
615 * Calculate fixed height and offset requirements.
617 flag_height
= p_fnt_height
+ (p_fnt_pad
<< 1);
620 p_y_off
= flag_height
+ p_bdr_width
;
621 p_x_off
= p_y_off
* p_spread
;
623 s_height
= s_fnt_height
+ (s_fnt_pad
<< 1) + (s_bdr_width
<< 1);
628 * Set up the pane list header.
632 pane
->type
= PL_HEADER
;
636 * Initialize the internal pane and selection creation queues.
641 * Create pane, active, and inactive GC's.
643 values
= (XGCValues
*)malloc(sizeof(XGCValues
));
644 valuemask
= (GCForeground
| GCBackground
| GCFont
| GCLineWidth
);
650 values
->foreground
= p_frg_color
.pixel
;
651 values
->background
= bkgnd_color
.pixel
;
652 values
->font
= p_fnt_info
->fid
;
653 values
->line_width
= p_bdr_width
;
661 * Then normal video selection.
664 values
->foreground
= s_frg_color
.pixel
;
665 values
->background
= bkgnd_color
.pixel
;
666 values
->font
= s_fnt_info
->fid
;
667 values
->line_width
= s_bdr_width
;
668 normal_select_GC
= XCreateGC(display
,
673 * Inverse video selection.
676 values
->foreground
= bkgnd_color
.pixel
;
677 values
->background
= s_frg_color
.pixel
;
678 values
->font
= s_fnt_info
->fid
;
679 values
->line_width
= s_bdr_width
;
680 inverse_select_GC
= XCreateGC(display
,
684 stipple_pixmap
= XCreateBitmapFromData(display
,
691 * Finally, inactive pane header and selections
693 valuemask
|= (GCFillStyle
| GCStipple
);
694 values
->foreground
= s_frg_color
.pixel
;
695 values
->background
= bkgnd_color
.pixel
;
696 values
->font
= s_fnt_info
->fid
;
697 values
->line_width
= s_bdr_width
;
698 values
->fill_style
= FillStippled
;
699 values
->stipple
= stipple_pixmap
;
701 inact_GC
= XCreateGC(display
,
706 valuemask
|= (GCGraphicsExposures
);
707 values
->graphics_exposures
= False
;
708 inact_GC_noexpose
= XCreateGC (display
,
714 * Construct the XMenu object.
716 /* -------------------- Menu data -------------------- */
717 menu
->menu_style
= menu_style
;
718 menu
->menu_mode
= menu_mode
;
719 menu
->freeze
= freeze
;
722 menu
->parent
= parent
;
725 menu
->mouse_cursor
= mouse_cursor
;
726 menu
->assoc_tab
= assoc_tab
;
728 /* -------------------- Pane window data -------------------- */
729 menu
->p_style
= p_style
;
730 menu
->p_events
= DEF_P_EVENTS
;
731 menu
->p_fnt_info
= p_fnt_info
;
732 menu
->p_fnt_pad
= p_fnt_pad
;
733 menu
->p_spread
= p_spread
;
734 menu
->p_bdr_width
= p_bdr_width
;
735 menu
->flag_height
= flag_height
;
737 menu
->p_height
= p_height
;
738 menu
->p_x_off
= p_x_off
;
739 menu
->p_y_off
= p_y_off
;
741 menu
->pane_GC
= pane_GC
;
744 /* -------------------- Selection window data -------------------- */
745 menu
->s_style
= s_style
;
746 menu
->s_events
= DEF_S_EVENTS
;
747 menu
->s_fnt_info
= s_fnt_info
;
748 menu
->s_fnt_pad
= s_fnt_pad
;
749 menu
->s_spread
= s_spread
;
750 menu
->s_bdr_width
= s_bdr_width
; /* unnecessary */
752 menu
->s_height
= s_height
;
753 menu
->s_x_off
= s_x_off
;
754 menu
->s_y_off
= s_y_off
;
756 menu
->normal_select_GC
= normal_select_GC
;
757 menu
->inverse_select_GC
= inverse_select_GC
;
758 menu
->inact_GC
= inact_GC
;
759 /* -------------------- Color data -------------------- */
760 menu
->p_bdr_color
= p_bdr_color
.pixel
;
761 menu
->s_bdr_color
= s_bdr_color
.pixel
;
762 menu
->p_frg_color
= p_frg_color
.pixel
;
763 menu
->s_frg_color
= s_frg_color
.pixel
;
764 menu
->bkgnd_color
= bkgnd_color
.pixel
;
765 /* -------------------- Pixmap data -------------------- */
766 menu
->p_bdr_pixmap
= None
;
767 menu
->s_bdr_pixmap
= None
;
768 menu
->p_frg_pixmap
= None
;
769 menu
->s_frg_pixmap
= None
;
770 menu
->bkgnd_pixmap
= None
;
771 menu
->inact_pixmap
= inact_bitmap
;
774 * Return the completed XMenu.
776 _XMErrorCode
= XME_NO_ERROR
;
780 /* arch-tag: 6945b7d2-3b13-40b9-8b6e-56b1b20f3463
781 (do not change this comment) */