1 /* Copyright Massachusetts Institute of Technology 1985 */
6 Copyright (C) 1993-1994, 2001-2018 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 <https://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
36 #ifdef EMACS_BITMAP_FILES
37 #include "../src/bitmaps/dimple1.xbm"
38 #include "../src/bitmaps/dimple3.xbm"
39 #include "../src/bitmaps/gray1.xbm"
40 #include "../src/bitmaps/gray3.xbm"
41 #include "../src/bitmaps/crosswv.xbm"
43 #include "../src/bitmaps/leftptr.xbm"
44 #include "../src/bitmaps/leftpmsk.xbm"
45 #include "../src/bitmaps/rtptr.xbm"
46 #include "../src/bitmaps/rtpmsk.xbm"
47 #include "../src/bitmaps/cntrptr.xbm"
48 #include "../src/bitmaps/cntrpmsk.xbm"
49 #include "../src/bitmaps/stipple.xbm"
53 #include <X11/bitmaps/dimple1>
54 #include <X11/bitmaps/dimple3>
55 #include <X11/bitmaps/gray1>
56 #include <X11/bitmaps/gray3>
57 #include <X11/bitmaps/cross_weave>
59 #include <X11/bitmaps/left_ptr>
60 #include <X11/bitmaps/left_ptrmsk>
61 #include <X11/bitmaps/right_ptr>
62 #include <X11/bitmaps/right_ptrmsk>
63 #include <X11/bitmaps/cntr_ptr>
64 #include <X11/bitmaps/cntr_ptrmsk>
65 #include <X11/bitmaps/stipple>
67 #endif /* not EMACS_BITMAP_FILES */
71 #define DEF_MENU_STYLE LEFT
72 #define DEF_MENU_MODE BOX
73 #define DEF_INACT_PNUM 3
75 #define DEF_P_STYLE CENTER
77 #define DEF_P_EVENTS (EnterWindowMask | ExposureMask)
78 #define DEF_P_FNT_NAME "fixed"
79 #define DEF_P_SPREAD 0.5
80 #define DEF_P_BDR_WIDTH 2
82 #define DEF_S_STYLE LEFT
83 #define DEF_S_EVENTS (EnterWindowMask | LeaveWindowMask)
84 #define DEF_S_FNT_NAME "fixed"
85 #define DEF_S_SPREAD 0.10
86 #define DEF_S_BDR_WIDTH 1
88 #define XASSOC_TABLE_SIZE 64
90 char *x_get_resource_string (char const *, char const *);
95 XAllocDisplayColor(Display
*display
, Colormap map
, char const *colorName
,
96 XColor
*color
, XColor
*junk
)
98 return (colorName
!=0 &&
99 XParseColor(display
, map
, colorName
, color
) &&
100 XAllocColor(display
, map
, color
));
105 XMenuCreate(Display
*display
, Window parent
, register char const *def_env
)
106 /* ID of previously opened display */
107 /* Window ID of the menu's parent window. */
108 /* X Defaults program environment name. */
110 register char *def_val
; /* X Default value temp variable. */
112 register XMenu
*menu
; /* Pointer to the new menu. */
113 XMStyle menu_style
; /* Menu display style. */
114 XMMode menu_mode
; /* Menu display mode. */
115 XMPane
*pane
; /* Pane list header. */
116 XAssocTable
*assoc_tab
; /* XAssocTable pointer. */
118 int freeze
; /* Freeze server mode. */
119 int reverse
; /* Reverse video mode. */
121 XMStyle p_style
; /* Pane display style. */
122 char const *p_fnt_name
; /* Flag font name. */
123 XFontStruct
*p_fnt_info
; /* Flag font structure */
124 int p_fnt_pad
; /* Flag font padding in pixels. */
125 double p_spread
; /* Pane spread in flag height fractions. */
126 int p_fnt_height
; /* Pane character height. */
127 int p_bdr_width
; /* Pane border width. */
128 int flag_height
; /* Flag window height. */
129 int p_height
; /* Pane window height. */
130 int p_x_off
; /* Pane X offset. */
131 int p_y_off
; /* Pane Y offset. */
132 GC pane_GC
; /* Pane graphics context. */
134 XMStyle s_style
; /* Selection display style. */
135 char const *s_fnt_name
; /* Selection font name. */
136 XFontStruct
*s_fnt_info
; /* Selection font structure. */
137 int s_fnt_pad
; /* Selection font padding in pixels. */
138 int s_fnt_height
; /* Selection font character height */
139 double s_spread
; /* Select spread in line height fractions. */
140 int s_bdr_width
; /* Highlight border width. */
141 int s_height
; /* Selection window height. */
142 int s_x_off
; /* Selection window X offset. */
143 int s_y_off
; /* Selection window Y offset. */
144 GC normal_select_GC
; /* GC used for normal video selection. */
145 GC inverse_select_GC
; /* GC used for inverse video selection. */
146 GC inact_GC
; /* GC for inactive pane header and */
149 XColor color_def
; /* Temp color definition holder. */
150 XColor p_bdr_color
; /* Color of border. */
151 XColor s_bdr_color
; /* Color of highlight. */
152 XColor p_frg_color
; /* Color of pane foreground color. */
153 XColor s_frg_color
; /* Color of selection foreground. */
154 XColor bkgnd_color
; /* Color of background.. */
155 XColor mouse_color
; /* Color of mouse cursor. */
156 Cursor mouse_cursor
; /* Mouse cursor. */
157 Pixmap inact_bitmap
; /* Menu inactive pixmap. */
159 int inact_pnum
; /* Inactive background pattern number. */
161 Pixmap cursor
; /* Cursor pixmap holder. */
162 Pixmap cursor_mask
; /* Cursor mask pixmap holder. */
163 Pixmap stipple_pixmap
; /* Stipple mask for half-tone text. */
164 unsigned long valuemask
;
167 Window root
= RootWindow (display
, DefaultScreen (display
));
170 * Calloc the XMenu structure and the initial pane.
172 menu
= (XMenu
*)calloc(1, sizeof(XMenu
));
174 _XMErrorCode
= XME_CALLOC
;
177 pane
= (XMPane
*)calloc(1, sizeof(XMPane
));
179 _XMErrorCode
= XME_CALLOC
;
184 * Create the XAssocTable
186 assoc_tab
= (XAssocTable
*)XCreateAssocTable(XASSOC_TABLE_SIZE
);
187 if(assoc_tab
== NULL
) {
188 _XMErrorCode
= XME_CREATE_ASSOC
;
193 * Set up the default environment name.
195 if (def_env
== NULL
|| *def_env
== '\0') def_env
= "XMenu";
198 * Set up internal fail-safe defaults.
201 reverse
= DEF_REVERSE
;
202 menu_style
= DEF_MENU_STYLE
;
203 menu_mode
= DEF_MENU_MODE
;
204 inact_pnum
= DEF_INACT_PNUM
;
206 p_style
= DEF_P_STYLE
;
207 p_spread
= DEF_P_SPREAD
;
208 p_fnt_name
= DEF_P_FNT_NAME
;
209 p_bdr_width
= DEF_P_BDR_WIDTH
;
211 s_style
= DEF_S_STYLE
;
212 s_spread
= DEF_S_SPREAD
;
213 s_fnt_name
= DEF_S_FNT_NAME
;
214 s_bdr_width
= DEF_S_BDR_WIDTH
;
217 * Get default values from X.
219 def_val
= x_get_resource_string ("menuFreeze", "MenuFreeze");
220 if (def_val
!= NULL
) {
221 if (strcmp(def_val
, "on") == 0) freeze
= 1;
222 else if (strcmp(def_val
, "off") == 0) freeze
= 0;
225 def_val
= x_get_resource_string ("menuReverseVideo", "MenuReverseVideo");
226 if (def_val
!= NULL
) {
227 if (strcmp(def_val
, "on") == 0) reverse
= 1;
228 else if (strcmp(def_val
, "off") == 0) reverse
= 0;
231 def_val
= x_get_resource_string ("menuStyle", "MenuStyle");
232 if (def_val
!= NULL
) {
233 if (strcmp(def_val
, "right_hand") == 0) menu_style
= RIGHT
;
234 else if (strcmp(def_val
, "left_hand") == 0) menu_style
= LEFT
;
235 else if (strcmp(def_val
, "center") == 0) menu_style
= CENTER
;
238 def_val
= x_get_resource_string ("menuMode", "MenuMode");
239 if (def_val
!= NULL
) {
240 if (strcmp(def_val
, "box") == 0) menu_mode
= BOX
;
241 else if (strcmp(def_val
, "invert") == 0) menu_mode
= INVERT
;
244 def_val
= x_get_resource_string ("menuMouse", "MenuMouse");
247 DisplayCells(display
, DefaultScreen(display
)) > 2 &&
248 XAllocDisplayColor(display
,
249 DefaultColormap(display
, DefaultScreen(display
)),
251 &mouse_color
, &color_def
)
254 XAllocDisplayColor(display
,
255 DefaultColormap(display
, DefaultScreen(display
)),
257 &mouse_color
, &color_def
)
260 else if (XAllocDisplayColor(display
,
261 DefaultColormap(display
, DefaultScreen(display
)),
263 &mouse_color
, &color_def
)
268 def_val
= x_get_resource_string ("menuBackground", "MenuBackground");
271 DisplayCells(display
, DefaultScreen(display
)) > 2 &&
272 XAllocDisplayColor(display
,
273 DefaultColormap(display
, DefaultScreen(display
)),
275 &bkgnd_color
, &color_def
)
278 XAllocDisplayColor(display
,
279 DefaultColormap(display
, DefaultScreen(display
)),
281 &bkgnd_color
, &color_def
)
283 else if (XAllocDisplayColor(display
,
284 DefaultColormap(display
, DefaultScreen(display
)),
286 &bkgnd_color
, &color_def
)
290 def_val
= x_get_resource_string ("menuInactivePattern", "MenuInactivePattern");
291 if (def_val
!= NULL
) {
292 if (strcmp(def_val
, "dimple1") == 0) inact_pnum
= 0;
293 else if (strcmp(def_val
, "dimple3") == 0) inact_pnum
= 1;
294 else if (strcmp(def_val
, "gray1") == 0) inact_pnum
= 2;
295 else if (strcmp(def_val
, "gray3") == 0) inact_pnum
= 3;
296 else if (strcmp(def_val
, "cross_weave") == 0) inact_pnum
= 4;
299 def_val
= x_get_resource_string ("paneStyle", "PaneStyle");
300 if (def_val
!= NULL
) {
301 if (strcmp(def_val
, "flush_left") == 0) p_style
= LEFT
;
302 else if (strcmp(def_val
, "flush_right") == 0) p_style
= RIGHT
;
303 else if (strcmp(def_val
, "center") == 0) p_style
= CENTER
;
306 def_val
= x_get_resource_string ("paneFont", "PaneFont");
307 if (def_val
!= NULL
) p_fnt_name
= def_val
;
309 def_val
= x_get_resource_string ("paneForeground", "PaneForeground");
312 DisplayCells(display
, DefaultScreen(display
)) > 2
314 XAllocDisplayColor(display
, DefaultColormap(display
,
315 DefaultScreen(display
)),
317 &p_frg_color
, &color_def
);
319 else if (reverse
) XAllocDisplayColor(display
,
320 DefaultColormap(display
,
321 DefaultScreen(display
)),
323 &p_frg_color
, &color_def
);
324 else XAllocDisplayColor(display
,
325 DefaultColormap(display
, DefaultScreen(display
)),
327 &p_frg_color
, &color_def
);
329 def_val
= x_get_resource_string ("paneBorder", "PaneBorder");
332 DisplayCells(display
, DefaultScreen(display
)) > 2 &&
333 XAllocDisplayColor(display
,
334 DefaultColormap(display
, DefaultScreen(display
)),
336 &p_bdr_color
, &color_def
)
339 XAllocDisplayColor(display
,
340 DefaultColormap(display
, DefaultScreen(display
)),
342 &p_bdr_color
, &color_def
)
344 else XAllocDisplayColor(display
,
345 DefaultColormap(display
, DefaultScreen(display
)),
347 &p_bdr_color
, &color_def
);
349 def_val
= x_get_resource_string ("paneBorderWidth", "PaneBorderWidth");
350 if (def_val
!= NULL
) p_bdr_width
= atoi(def_val
);
352 def_val
= x_get_resource_string ("paneSpread", "PaneSpread");
353 if (def_val
!= NULL
) p_spread
= atof(def_val
);
355 def_val
= x_get_resource_string ("selectionStyle", "SelectionStyle");
356 if (def_val
!= NULL
) {
357 if (strcmp(def_val
, "flush_left") == 0) s_style
= LEFT
;
358 else if (strcmp(def_val
, "flush_right") == 0) s_style
= RIGHT
;
359 else if (strcmp(def_val
, "center") == 0) s_style
= CENTER
;
362 def_val
= x_get_resource_string ("selectionFont", "SelectionFont");
363 if (def_val
!= NULL
) s_fnt_name
= def_val
;
365 def_val
= x_get_resource_string ("selectionForeground", "SelectionForeground");
368 DisplayCells(display
, DefaultScreen(display
)) > 2 &&
369 XAllocDisplayColor(display
,
370 DefaultColormap(display
, DefaultScreen(display
)),
372 &s_frg_color
, &color_def
)
375 XAllocDisplayColor(display
,
376 DefaultColormap(display
, DefaultScreen(display
)),
378 &s_frg_color
, &color_def
)
380 else if (XAllocDisplayColor(display
,
381 DefaultColormap(display
, DefaultScreen(display
)),
383 &s_frg_color
, &color_def
)
388 def_val
= x_get_resource_string ("selectionBorder", "SelectionBorder");
391 DisplayCells(display
, DefaultScreen(display
)) > 2 &&
392 XAllocDisplayColor(display
,
393 DefaultColormap(display
, DefaultScreen(display
)),
395 &s_bdr_color
, &color_def
)
398 XAllocDisplayColor(display
,
399 DefaultColormap(display
, DefaultScreen(display
)),
401 &s_bdr_color
, &color_def
)
403 else if (XAllocDisplayColor(display
,
404 DefaultColormap(display
, DefaultScreen(display
)),
406 &s_bdr_color
, &color_def
)
410 def_val
= x_get_resource_string ("selectionBorderWidth", "SelectionBorderWidth");
411 if (def_val
!= NULL
) s_bdr_width
= atoi(def_val
);
413 def_val
= x_get_resource_string ("selectionSpread", "SelectionSpread");
414 if (def_val
!= NULL
) s_spread
= atof(def_val
);
417 * Create and store the inactive pattern pixmap.
426 data
= (char *)dimple1_bits
;
427 width
= dimple1_width
;
428 height
= dimple1_height
;
432 data
= (char *)dimple3_bits
;
433 width
= dimple3_width
;
434 height
= dimple3_height
;
438 data
= (char *)gray1_bits
;
440 height
= gray1_height
;
444 data
= (char *)gray3_bits
;
446 height
= gray3_height
;
450 data
= (char *)cross_weave_bits
;
451 width
= cross_weave_width
;
452 height
= cross_weave_height
;
458 _XMErrorCode
= XME_STORE_BITMAP
;
463 XCreatePixmapFromBitmapData
464 (display
, root
, data
, width
, height
,
465 p_frg_color
.pixel
, bkgnd_color
.pixel
,
466 DisplayPlanes (display
, DefaultScreen (display
)));
470 * Load the mouse cursor.
473 switch (menu_style
) {
475 cursor
= XCreateBitmapFromData(display
,
480 cursor_mask
= XCreateBitmapFromData(display
,
485 mouse_cursor
= XCreatePixmapCursor(
488 &mouse_color
, &bkgnd_color
,
492 XFreePixmap(display
, cursor
);
493 XFreePixmap(display
, cursor_mask
);
496 cursor
= XCreateBitmapFromData(display
,
501 cursor_mask
= XCreateBitmapFromData(display
,
505 right_ptrmsk_height
);
506 mouse_cursor
= XCreatePixmapCursor(
509 &mouse_color
, &bkgnd_color
,
513 XFreePixmap(display
, cursor
);
514 XFreePixmap(display
, cursor_mask
);
517 cursor
= XCreateBitmapFromData(display
,
522 cursor_mask
= XCreateBitmapFromData(display
,
527 mouse_cursor
= XCreatePixmapCursor(
530 &mouse_color
, &bkgnd_color
,
534 XFreePixmap(display
, cursor
);
535 XFreePixmap(display
, cursor_mask
);
538 /* Error! Invalid style parameter. */
539 _XMErrorCode
= XME_STYLE_PARAM
;
542 if (mouse_cursor
== _X_FAILURE
) {
543 _XMErrorCode
= XME_CREATE_CURSOR
;
548 * Open the pane and selection fonts.
551 p_fnt_info
= XLoadQueryFont(display
, p_fnt_name
);
552 if (p_fnt_info
== NULL
) {
553 _XMErrorCode
= XME_OPEN_FONT
;
558 s_fnt_info
= XLoadQueryFont(display
, s_fnt_name
);
559 if (s_fnt_info
== NULL
) {
560 _XMErrorCode
= XME_OPEN_FONT
;
564 * Calculate the fixed padding value in pixels for each font.
566 p_fnt_height
= p_fnt_info
->max_bounds
.ascent
+ p_fnt_info
->max_bounds
.descent
;
567 s_fnt_height
= s_fnt_info
->max_bounds
.ascent
+ s_fnt_info
->max_bounds
.descent
;
568 p_fnt_pad
= s_spread
* p_fnt_height
;
569 s_fnt_pad
= s_spread
* s_fnt_height
;
572 * Calculate fixed height and offset requirements.
574 flag_height
= p_fnt_height
+ (p_fnt_pad
<< 1);
577 p_y_off
= flag_height
+ p_bdr_width
;
578 p_x_off
= p_y_off
* p_spread
;
580 s_height
= s_fnt_height
+ (s_fnt_pad
<< 1) + (s_bdr_width
<< 1);
585 * Set up the pane list header.
589 pane
->type
= PL_HEADER
;
593 * Initialize the internal pane and selection creation queues.
598 * Create pane, active, and inactive GC's.
600 values
= (XGCValues
*)malloc(sizeof(XGCValues
));
601 valuemask
= (GCForeground
| GCBackground
| GCFont
| GCLineWidth
);
607 values
->foreground
= p_frg_color
.pixel
;
608 values
->background
= bkgnd_color
.pixel
;
609 values
->font
= p_fnt_info
->fid
;
610 values
->line_width
= p_bdr_width
;
618 * Then normal video selection.
621 values
->foreground
= s_frg_color
.pixel
;
622 values
->background
= bkgnd_color
.pixel
;
623 values
->font
= s_fnt_info
->fid
;
624 values
->line_width
= s_bdr_width
;
625 normal_select_GC
= XCreateGC(display
,
630 * Inverse video selection.
633 values
->foreground
= bkgnd_color
.pixel
;
634 values
->background
= s_frg_color
.pixel
;
635 values
->font
= s_fnt_info
->fid
;
636 values
->line_width
= s_bdr_width
;
637 inverse_select_GC
= XCreateGC(display
,
641 stipple_pixmap
= XCreateBitmapFromData(display
,
648 * Finally, inactive pane header and selections
650 valuemask
|= (GCFillStyle
| GCStipple
);
651 values
->foreground
= s_frg_color
.pixel
;
652 values
->background
= bkgnd_color
.pixel
;
653 values
->font
= s_fnt_info
->fid
;
654 values
->line_width
= s_bdr_width
;
655 values
->fill_style
= FillStippled
;
656 values
->stipple
= stipple_pixmap
;
658 inact_GC
= XCreateGC(display
,
663 valuemask
|= (GCGraphicsExposures
);
664 values
->graphics_exposures
= False
;
668 * Construct the XMenu object.
670 /* -------------------- Menu data -------------------- */
671 menu
->menu_style
= menu_style
;
672 menu
->menu_mode
= menu_mode
;
673 menu
->freeze
= freeze
;
676 menu
->parent
= parent
;
679 menu
->mouse_cursor
= mouse_cursor
;
680 menu
->assoc_tab
= assoc_tab
;
682 /* -------------------- Pane window data -------------------- */
683 menu
->p_style
= p_style
;
684 menu
->p_events
= DEF_P_EVENTS
;
685 menu
->p_fnt_info
= p_fnt_info
;
686 menu
->p_fnt_pad
= p_fnt_pad
;
687 menu
->p_spread
= p_spread
;
688 menu
->p_bdr_width
= p_bdr_width
;
689 menu
->flag_height
= flag_height
;
691 menu
->p_height
= p_height
;
692 menu
->p_x_off
= p_x_off
;
693 menu
->p_y_off
= p_y_off
;
695 menu
->pane_GC
= pane_GC
;
698 /* -------------------- Selection window data -------------------- */
699 menu
->s_style
= s_style
;
700 menu
->s_events
= DEF_S_EVENTS
;
701 menu
->s_fnt_info
= s_fnt_info
;
702 menu
->s_fnt_pad
= s_fnt_pad
;
703 menu
->s_spread
= s_spread
;
704 menu
->s_bdr_width
= s_bdr_width
; /* unnecessary */
706 menu
->s_height
= s_height
;
707 menu
->s_x_off
= s_x_off
;
708 menu
->s_y_off
= s_y_off
;
710 menu
->normal_select_GC
= normal_select_GC
;
711 menu
->inverse_select_GC
= inverse_select_GC
;
712 menu
->inact_GC
= inact_GC
;
713 /* -------------------- Color data -------------------- */
714 menu
->p_bdr_color
= p_bdr_color
.pixel
;
715 menu
->s_bdr_color
= s_bdr_color
.pixel
;
716 menu
->p_frg_color
= p_frg_color
.pixel
;
717 menu
->s_frg_color
= s_frg_color
.pixel
;
718 menu
->bkgnd_color
= bkgnd_color
.pixel
;
719 /* -------------------- Pixmap data -------------------- */
720 menu
->p_bdr_pixmap
= None
;
721 menu
->s_bdr_pixmap
= None
;
722 menu
->p_frg_pixmap
= None
;
723 menu
->s_frg_pixmap
= None
;
724 menu
->bkgnd_pixmap
= None
;
725 menu
->inact_pixmap
= inact_bitmap
;
728 * Return the completed XMenu.
730 _XMErrorCode
= XME_NO_ERROR
;