1 /* Copyright Massachusetts Institute of Technology 1985 */
6 Copyright (C) 1993-1994, 2001-2017 Free Software Foundation, Inc.
8 This program is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or (at
11 your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
23 * XMenu: MIT Project Athena, X Window system menu package
25 * XMenuCreate - Creates an X window system menu object.
27 * Author: Tony Della Fera, DEC
35 #ifdef EMACS_BITMAP_FILES
36 #include "../src/bitmaps/dimple1.xbm"
37 #include "../src/bitmaps/dimple3.xbm"
38 #include "../src/bitmaps/gray1.xbm"
39 #include "../src/bitmaps/gray3.xbm"
40 #include "../src/bitmaps/crosswv.xbm"
42 #include "../src/bitmaps/leftptr.xbm"
43 #include "../src/bitmaps/leftpmsk.xbm"
44 #include "../src/bitmaps/rtptr.xbm"
45 #include "../src/bitmaps/rtpmsk.xbm"
46 #include "../src/bitmaps/cntrptr.xbm"
47 #include "../src/bitmaps/cntrpmsk.xbm"
48 #include "../src/bitmaps/stipple.xbm"
52 #include <X11/bitmaps/dimple1>
53 #include <X11/bitmaps/dimple3>
54 #include <X11/bitmaps/gray1>
55 #include <X11/bitmaps/gray3>
56 #include <X11/bitmaps/cross_weave>
58 #include <X11/bitmaps/left_ptr>
59 #include <X11/bitmaps/left_ptrmsk>
60 #include <X11/bitmaps/right_ptr>
61 #include <X11/bitmaps/right_ptrmsk>
62 #include <X11/bitmaps/cntr_ptr>
63 #include <X11/bitmaps/cntr_ptrmsk>
64 #include <X11/bitmaps/stipple>
66 #endif /* not EMACS_BITMAP_FILES */
70 #define DEF_MENU_STYLE LEFT
71 #define DEF_MENU_MODE BOX
72 #define DEF_INACT_PNUM 3
74 #define DEF_P_STYLE CENTER
76 #define DEF_P_EVENTS (EnterWindowMask | ExposureMask)
77 #define DEF_P_FNT_NAME "fixed"
78 #define DEF_P_SPREAD 0.5
79 #define DEF_P_BDR_WIDTH 2
81 #define DEF_S_STYLE LEFT
82 #define DEF_S_EVENTS (EnterWindowMask | LeaveWindowMask)
83 #define DEF_S_FNT_NAME "fixed"
84 #define DEF_S_SPREAD 0.10
85 #define DEF_S_BDR_WIDTH 1
87 #define XASSOC_TABLE_SIZE 64
89 char *x_get_resource_string (char const *, char const *);
94 XAllocDisplayColor(Display
*display
, Colormap map
, char const *colorName
,
95 XColor
*color
, XColor
*junk
)
97 return (colorName
!=0 &&
98 XParseColor(display
, map
, colorName
, color
) &&
99 XAllocColor(display
, map
, color
));
104 XMenuCreate(Display
*display
, Window parent
, register char const *def_env
)
105 /* ID of previously opened display */
106 /* Window ID of the menu's parent window. */
107 /* X Defaults program environment name. */
109 register char *def_val
; /* X Default value temp variable. */
111 register XMenu
*menu
; /* Pointer to the new menu. */
112 XMStyle menu_style
; /* Menu display style. */
113 XMMode menu_mode
; /* Menu display mode. */
114 XMPane
*pane
; /* Pane list header. */
115 XAssocTable
*assoc_tab
; /* XAssocTable pointer. */
117 int freeze
; /* Freeze server mode. */
118 int reverse
; /* Reverse video mode. */
120 XMStyle p_style
; /* Pane display style. */
121 char const *p_fnt_name
; /* Flag font name. */
122 XFontStruct
*p_fnt_info
; /* Flag font structure */
123 int p_fnt_pad
; /* Flag font padding in pixels. */
124 double p_spread
; /* Pane spread in flag height fractions. */
125 int p_fnt_height
; /* Pane character height. */
126 int p_bdr_width
; /* Pane border width. */
127 int flag_height
; /* Flag window height. */
128 int p_height
; /* Pane window height. */
129 int p_x_off
; /* Pane X offset. */
130 int p_y_off
; /* Pane Y offset. */
131 GC pane_GC
; /* Pane graphics context. */
133 XMStyle s_style
; /* Selection display style. */
134 char const *s_fnt_name
; /* Selection font name. */
135 XFontStruct
*s_fnt_info
; /* Selection font structure. */
136 int s_fnt_pad
; /* Selection font padding in pixels. */
137 int s_fnt_height
; /* Selection font character height */
138 double s_spread
; /* Select spread in line height fractions. */
139 int s_bdr_width
; /* Highlight border width. */
140 int s_height
; /* Selection window height. */
141 int s_x_off
; /* Selection window X offset. */
142 int s_y_off
; /* Selection window Y offset. */
143 GC normal_select_GC
; /* GC used for normal video selection. */
144 GC inverse_select_GC
; /* GC used for inverse video selection. */
145 GC inact_GC
; /* GC for inactive pane header and */
148 XColor color_def
; /* Temp color definition holder. */
149 XColor p_bdr_color
; /* Color of border. */
150 XColor s_bdr_color
; /* Color of highlight. */
151 XColor p_frg_color
; /* Color of pane foreground color. */
152 XColor s_frg_color
; /* Color of selection foreground. */
153 XColor bkgnd_color
; /* Color of background.. */
154 XColor mouse_color
; /* Color of mouse cursor. */
155 Cursor mouse_cursor
; /* Mouse cursor. */
156 Pixmap inact_bitmap
; /* Menu inactive pixmap. */
158 int inact_pnum
; /* Inactive background pattern number. */
160 Pixmap cursor
; /* Cursor pixmap holder. */
161 Pixmap cursor_mask
; /* Cursor mask pixmap holder. */
162 Pixmap stipple_pixmap
; /* Stipple mask for half-tone text. */
163 unsigned long valuemask
;
166 Window root
= RootWindow (display
, DefaultScreen (display
));
169 * Calloc the XMenu structure and the initial pane.
171 menu
= (XMenu
*)calloc(1, sizeof(XMenu
));
173 _XMErrorCode
= XME_CALLOC
;
176 pane
= (XMPane
*)calloc(1, sizeof(XMPane
));
178 _XMErrorCode
= XME_CALLOC
;
183 * Create the XAssocTable
185 assoc_tab
= (XAssocTable
*)XCreateAssocTable(XASSOC_TABLE_SIZE
);
186 if(assoc_tab
== NULL
) {
187 _XMErrorCode
= XME_CREATE_ASSOC
;
192 * Set up the default environment name.
194 if (def_env
== NULL
|| *def_env
== '\0') def_env
= "XMenu";
197 * Set up internal fail-safe defaults.
200 reverse
= DEF_REVERSE
;
201 menu_style
= DEF_MENU_STYLE
;
202 menu_mode
= DEF_MENU_MODE
;
203 inact_pnum
= DEF_INACT_PNUM
;
205 p_style
= DEF_P_STYLE
;
206 p_spread
= DEF_P_SPREAD
;
207 p_fnt_name
= DEF_P_FNT_NAME
;
208 p_bdr_width
= DEF_P_BDR_WIDTH
;
210 s_style
= DEF_S_STYLE
;
211 s_spread
= DEF_S_SPREAD
;
212 s_fnt_name
= DEF_S_FNT_NAME
;
213 s_bdr_width
= DEF_S_BDR_WIDTH
;
216 * Get default values from X.
218 def_val
= x_get_resource_string ("menuFreeze", "MenuFreeze");
219 if (def_val
!= NULL
) {
220 if (strcmp(def_val
, "on") == 0) freeze
= 1;
221 else if (strcmp(def_val
, "off") == 0) freeze
= 0;
224 def_val
= x_get_resource_string ("menuReverseVideo", "MenuReverseVideo");
225 if (def_val
!= NULL
) {
226 if (strcmp(def_val
, "on") == 0) reverse
= 1;
227 else if (strcmp(def_val
, "off") == 0) reverse
= 0;
230 def_val
= x_get_resource_string ("menuStyle", "MenuStyle");
231 if (def_val
!= NULL
) {
232 if (strcmp(def_val
, "right_hand") == 0) menu_style
= RIGHT
;
233 else if (strcmp(def_val
, "left_hand") == 0) menu_style
= LEFT
;
234 else if (strcmp(def_val
, "center") == 0) menu_style
= CENTER
;
237 def_val
= x_get_resource_string ("menuMode", "MenuMode");
238 if (def_val
!= NULL
) {
239 if (strcmp(def_val
, "box") == 0) menu_mode
= BOX
;
240 else if (strcmp(def_val
, "invert") == 0) menu_mode
= INVERT
;
243 def_val
= x_get_resource_string ("menuMouse", "MenuMouse");
246 DisplayCells(display
, DefaultScreen(display
)) > 2 &&
247 XAllocDisplayColor(display
,
248 DefaultColormap(display
, DefaultScreen(display
)),
250 &mouse_color
, &color_def
)
253 XAllocDisplayColor(display
,
254 DefaultColormap(display
, DefaultScreen(display
)),
256 &mouse_color
, &color_def
)
259 else if (XAllocDisplayColor(display
,
260 DefaultColormap(display
, DefaultScreen(display
)),
262 &mouse_color
, &color_def
)
267 def_val
= x_get_resource_string ("menuBackground", "MenuBackground");
270 DisplayCells(display
, DefaultScreen(display
)) > 2 &&
271 XAllocDisplayColor(display
,
272 DefaultColormap(display
, DefaultScreen(display
)),
274 &bkgnd_color
, &color_def
)
277 XAllocDisplayColor(display
,
278 DefaultColormap(display
, DefaultScreen(display
)),
280 &bkgnd_color
, &color_def
)
282 else if (XAllocDisplayColor(display
,
283 DefaultColormap(display
, DefaultScreen(display
)),
285 &bkgnd_color
, &color_def
)
289 def_val
= x_get_resource_string ("menuInactivePattern", "MenuInactivePattern");
290 if (def_val
!= NULL
) {
291 if (strcmp(def_val
, "dimple1") == 0) inact_pnum
= 0;
292 else if (strcmp(def_val
, "dimple3") == 0) inact_pnum
= 1;
293 else if (strcmp(def_val
, "gray1") == 0) inact_pnum
= 2;
294 else if (strcmp(def_val
, "gray3") == 0) inact_pnum
= 3;
295 else if (strcmp(def_val
, "cross_weave") == 0) inact_pnum
= 4;
298 def_val
= x_get_resource_string ("paneStyle", "PaneStyle");
299 if (def_val
!= NULL
) {
300 if (strcmp(def_val
, "flush_left") == 0) p_style
= LEFT
;
301 else if (strcmp(def_val
, "flush_right") == 0) p_style
= RIGHT
;
302 else if (strcmp(def_val
, "center") == 0) p_style
= CENTER
;
305 def_val
= x_get_resource_string ("paneFont", "PaneFont");
306 if (def_val
!= NULL
) p_fnt_name
= def_val
;
308 def_val
= x_get_resource_string ("paneForeground", "PaneForeground");
311 DisplayCells(display
, DefaultScreen(display
)) > 2
313 XAllocDisplayColor(display
, DefaultColormap(display
,
314 DefaultScreen(display
)),
316 &p_frg_color
, &color_def
);
318 else if (reverse
) XAllocDisplayColor(display
,
319 DefaultColormap(display
,
320 DefaultScreen(display
)),
322 &p_frg_color
, &color_def
);
323 else XAllocDisplayColor(display
,
324 DefaultColormap(display
, DefaultScreen(display
)),
326 &p_frg_color
, &color_def
);
328 def_val
= x_get_resource_string ("paneBorder", "PaneBorder");
331 DisplayCells(display
, DefaultScreen(display
)) > 2 &&
332 XAllocDisplayColor(display
,
333 DefaultColormap(display
, DefaultScreen(display
)),
335 &p_bdr_color
, &color_def
)
338 XAllocDisplayColor(display
,
339 DefaultColormap(display
, DefaultScreen(display
)),
341 &p_bdr_color
, &color_def
)
343 else XAllocDisplayColor(display
,
344 DefaultColormap(display
, DefaultScreen(display
)),
346 &p_bdr_color
, &color_def
);
348 def_val
= x_get_resource_string ("paneBorderWidth", "PaneBorderWidth");
349 if (def_val
!= NULL
) p_bdr_width
= atoi(def_val
);
351 def_val
= x_get_resource_string ("paneSpread", "PaneSpread");
352 if (def_val
!= NULL
) p_spread
= atof(def_val
);
354 def_val
= x_get_resource_string ("selectionStyle", "SelectionStyle");
355 if (def_val
!= NULL
) {
356 if (strcmp(def_val
, "flush_left") == 0) s_style
= LEFT
;
357 else if (strcmp(def_val
, "flush_right") == 0) s_style
= RIGHT
;
358 else if (strcmp(def_val
, "center") == 0) s_style
= CENTER
;
361 def_val
= x_get_resource_string ("selectionFont", "SelectionFont");
362 if (def_val
!= NULL
) s_fnt_name
= def_val
;
364 def_val
= x_get_resource_string ("selectionForeground", "SelectionForeground");
367 DisplayCells(display
, DefaultScreen(display
)) > 2 &&
368 XAllocDisplayColor(display
,
369 DefaultColormap(display
, DefaultScreen(display
)),
371 &s_frg_color
, &color_def
)
374 XAllocDisplayColor(display
,
375 DefaultColormap(display
, DefaultScreen(display
)),
377 &s_frg_color
, &color_def
)
379 else if (XAllocDisplayColor(display
,
380 DefaultColormap(display
, DefaultScreen(display
)),
382 &s_frg_color
, &color_def
)
387 def_val
= x_get_resource_string ("selectionBorder", "SelectionBorder");
390 DisplayCells(display
, DefaultScreen(display
)) > 2 &&
391 XAllocDisplayColor(display
,
392 DefaultColormap(display
, DefaultScreen(display
)),
394 &s_bdr_color
, &color_def
)
397 XAllocDisplayColor(display
,
398 DefaultColormap(display
, DefaultScreen(display
)),
400 &s_bdr_color
, &color_def
)
402 else if (XAllocDisplayColor(display
,
403 DefaultColormap(display
, DefaultScreen(display
)),
405 &s_bdr_color
, &color_def
)
409 def_val
= x_get_resource_string ("selectionBorderWidth", "SelectionBorderWidth");
410 if (def_val
!= NULL
) s_bdr_width
= atoi(def_val
);
412 def_val
= x_get_resource_string ("selectionSpread", "SelectionSpread");
413 if (def_val
!= NULL
) s_spread
= atof(def_val
);
416 * Create and store the inactive pattern pixmap.
425 data
= (char *)dimple1_bits
;
426 width
= dimple1_width
;
427 height
= dimple1_height
;
431 data
= (char *)dimple3_bits
;
432 width
= dimple3_width
;
433 height
= dimple3_height
;
437 data
= (char *)gray1_bits
;
439 height
= gray1_height
;
443 data
= (char *)gray3_bits
;
445 height
= gray3_height
;
449 data
= (char *)cross_weave_bits
;
450 width
= cross_weave_width
;
451 height
= cross_weave_height
;
457 _XMErrorCode
= XME_STORE_BITMAP
;
462 XCreatePixmapFromBitmapData
463 (display
, root
, data
, width
, height
,
464 p_frg_color
.pixel
, bkgnd_color
.pixel
,
465 DisplayPlanes (display
, DefaultScreen (display
)));
469 * Load the mouse cursor.
472 switch (menu_style
) {
474 cursor
= XCreateBitmapFromData(display
,
479 cursor_mask
= XCreateBitmapFromData(display
,
484 mouse_cursor
= XCreatePixmapCursor(
487 &mouse_color
, &bkgnd_color
,
491 XFreePixmap(display
, cursor
);
492 XFreePixmap(display
, cursor_mask
);
495 cursor
= XCreateBitmapFromData(display
,
500 cursor_mask
= XCreateBitmapFromData(display
,
504 right_ptrmsk_height
);
505 mouse_cursor
= XCreatePixmapCursor(
508 &mouse_color
, &bkgnd_color
,
512 XFreePixmap(display
, cursor
);
513 XFreePixmap(display
, cursor_mask
);
516 cursor
= XCreateBitmapFromData(display
,
521 cursor_mask
= XCreateBitmapFromData(display
,
526 mouse_cursor
= XCreatePixmapCursor(
529 &mouse_color
, &bkgnd_color
,
533 XFreePixmap(display
, cursor
);
534 XFreePixmap(display
, cursor_mask
);
537 /* Error! Invalid style parameter. */
538 _XMErrorCode
= XME_STYLE_PARAM
;
541 if (mouse_cursor
== _X_FAILURE
) {
542 _XMErrorCode
= XME_CREATE_CURSOR
;
547 * Open the pane and selection fonts.
550 p_fnt_info
= XLoadQueryFont(display
, p_fnt_name
);
551 if (p_fnt_info
== NULL
) {
552 _XMErrorCode
= XME_OPEN_FONT
;
557 s_fnt_info
= XLoadQueryFont(display
, s_fnt_name
);
558 if (s_fnt_info
== NULL
) {
559 _XMErrorCode
= XME_OPEN_FONT
;
563 * Calculate the fixed padding value in pixels for each font.
565 p_fnt_height
= p_fnt_info
->max_bounds
.ascent
+ p_fnt_info
->max_bounds
.descent
;
566 s_fnt_height
= s_fnt_info
->max_bounds
.ascent
+ s_fnt_info
->max_bounds
.descent
;
567 p_fnt_pad
= s_spread
* p_fnt_height
;
568 s_fnt_pad
= s_spread
* s_fnt_height
;
571 * Calculate fixed height and offset requirements.
573 flag_height
= p_fnt_height
+ (p_fnt_pad
<< 1);
576 p_y_off
= flag_height
+ p_bdr_width
;
577 p_x_off
= p_y_off
* p_spread
;
579 s_height
= s_fnt_height
+ (s_fnt_pad
<< 1) + (s_bdr_width
<< 1);
584 * Set up the pane list header.
588 pane
->type
= PL_HEADER
;
592 * Initialize the internal pane and selection creation queues.
597 * Create pane, active, and inactive GC's.
599 values
= (XGCValues
*)malloc(sizeof(XGCValues
));
600 valuemask
= (GCForeground
| GCBackground
| GCFont
| GCLineWidth
);
606 values
->foreground
= p_frg_color
.pixel
;
607 values
->background
= bkgnd_color
.pixel
;
608 values
->font
= p_fnt_info
->fid
;
609 values
->line_width
= p_bdr_width
;
617 * Then normal video selection.
620 values
->foreground
= s_frg_color
.pixel
;
621 values
->background
= bkgnd_color
.pixel
;
622 values
->font
= s_fnt_info
->fid
;
623 values
->line_width
= s_bdr_width
;
624 normal_select_GC
= XCreateGC(display
,
629 * Inverse video selection.
632 values
->foreground
= bkgnd_color
.pixel
;
633 values
->background
= s_frg_color
.pixel
;
634 values
->font
= s_fnt_info
->fid
;
635 values
->line_width
= s_bdr_width
;
636 inverse_select_GC
= XCreateGC(display
,
640 stipple_pixmap
= XCreateBitmapFromData(display
,
647 * Finally, inactive pane header and selections
649 valuemask
|= (GCFillStyle
| GCStipple
);
650 values
->foreground
= s_frg_color
.pixel
;
651 values
->background
= bkgnd_color
.pixel
;
652 values
->font
= s_fnt_info
->fid
;
653 values
->line_width
= s_bdr_width
;
654 values
->fill_style
= FillStippled
;
655 values
->stipple
= stipple_pixmap
;
657 inact_GC
= XCreateGC(display
,
662 valuemask
|= (GCGraphicsExposures
);
663 values
->graphics_exposures
= False
;
667 * Construct the XMenu object.
669 /* -------------------- Menu data -------------------- */
670 menu
->menu_style
= menu_style
;
671 menu
->menu_mode
= menu_mode
;
672 menu
->freeze
= freeze
;
675 menu
->parent
= parent
;
678 menu
->mouse_cursor
= mouse_cursor
;
679 menu
->assoc_tab
= assoc_tab
;
681 /* -------------------- Pane window data -------------------- */
682 menu
->p_style
= p_style
;
683 menu
->p_events
= DEF_P_EVENTS
;
684 menu
->p_fnt_info
= p_fnt_info
;
685 menu
->p_fnt_pad
= p_fnt_pad
;
686 menu
->p_spread
= p_spread
;
687 menu
->p_bdr_width
= p_bdr_width
;
688 menu
->flag_height
= flag_height
;
690 menu
->p_height
= p_height
;
691 menu
->p_x_off
= p_x_off
;
692 menu
->p_y_off
= p_y_off
;
694 menu
->pane_GC
= pane_GC
;
697 /* -------------------- Selection window data -------------------- */
698 menu
->s_style
= s_style
;
699 menu
->s_events
= DEF_S_EVENTS
;
700 menu
->s_fnt_info
= s_fnt_info
;
701 menu
->s_fnt_pad
= s_fnt_pad
;
702 menu
->s_spread
= s_spread
;
703 menu
->s_bdr_width
= s_bdr_width
; /* unnecessary */
705 menu
->s_height
= s_height
;
706 menu
->s_x_off
= s_x_off
;
707 menu
->s_y_off
= s_y_off
;
709 menu
->normal_select_GC
= normal_select_GC
;
710 menu
->inverse_select_GC
= inverse_select_GC
;
711 menu
->inact_GC
= inact_GC
;
712 /* -------------------- Color data -------------------- */
713 menu
->p_bdr_color
= p_bdr_color
.pixel
;
714 menu
->s_bdr_color
= s_bdr_color
.pixel
;
715 menu
->p_frg_color
= p_frg_color
.pixel
;
716 menu
->s_frg_color
= s_frg_color
.pixel
;
717 menu
->bkgnd_color
= bkgnd_color
.pixel
;
718 /* -------------------- Pixmap data -------------------- */
719 menu
->p_bdr_pixmap
= None
;
720 menu
->s_bdr_pixmap
= None
;
721 menu
->p_frg_pixmap
= None
;
722 menu
->s_frg_pixmap
= None
;
723 menu
->bkgnd_pixmap
= None
;
724 menu
->inact_pixmap
= inact_bitmap
;
727 * Return the completed XMenu.
729 _XMErrorCode
= XME_NO_ERROR
;