1: #include <X/mit-copyright.h>
2:
3: /* $Header: XMenuCreate.c,v 10.9 86/02/01 16:14:36 tony Rel $ */
4: /* Copyright Massachusetts Institute of Technology 1985 */
5:
6: /*
7: * XMenu: MIT Project Athena, X Window system menu package
8: *
9: * XMenuCreate - Creates an X window system menu object.
10: *
11: * Author: Tony Della Fera, DEC
12: * January 23, 1986
13: *
14: */
15:
16: #include "XMenuInternal.h"
17:
18: #include "../bitmaps/dimple1.bitmap"
19: #include "../bitmaps/dimple3.bitmap"
20: #include "../bitmaps/gray1.bitmap"
21: #include "../bitmaps/gray3.bitmap"
22: #include "../bitmaps/cross_weave.bitmap"
23:
24: #include "../cursors/left_ptr.cursor"
25: #include "../cursors/left_ptr_mask.cursor"
26: #include "../cursors/right_ptr.cursor"
27: #include "../cursors/right_ptr_mask.cursor"
28: #include "../cursors/center_ptr.cursor"
29: #include "../cursors/center_ptr_mask.cursor"
30:
31: #define DEF_FREEZE 0
32: #define RIGHT
33: #define INVERT
34: #define DEF_INACT_PNUM 3
35: #define MAX_INACT_PNUM 4
36:
37: #define DEF_P_STYLE CENTER
38: #define DEF_P_EVENTS (EnterWindow | ExposeWindow)
39: #define DEF_P_FNT_NAME "8x13"
40: #define DEF_P_SPREAD 0.5
41: #define DEF_P_BDR_WIDTH 2
42:
43: #define DEF_S_STYLE LEFT
44: #define DEF_S_EVENTS (EnterWindow | LeaveWindow)
45: #define DEF_S_FNT_NAME "6x10"
46: #define DEF_S_SPREAD 0.10
47: #define DEF_S_BDR_WIDTH 1
48:
49: #define DEF_P_BDR_COLOR BlackPixel
50: #define DEF_S_BDR_COLOR BlackPixel
51: #define DEF_P_FRG_COLOR BlackPixel
52: #define DEF_S_FRG_COLOR BlackPixel
53: #define DEF_BKGND_COLOR WhitePixel
54: #define DEF_MOUSE_COLOR BlackPixel
55:
56: #define XASSOC_TABLE_SIZE 64
57:
58: #define TILE_BUF_SIZE 5
59:
60: int atoi();
61: double atof();
62:
63: *
64: XMenuCreate(parent, def_env)
65: Window parent; /* Window ID of the menu's parent window. */
66: register char *def_env; /* X Defaults program environment name. */
67: {
68: register int i; /* Loop counter. */
69: register int j; /* Loop counter. */
70: register char *def_val; /* X Default value temp variable. */
71:
72: register XMenu *menu; /* Pointer to the new menu. */
73: XMStyle menu_style; /* Menu display style. */
74: XMMode menu_mode; /* Menu display mode. */
75: XMPane *pane; /* Pane list header. */
76: XAssocTable *assoc_tab; /* XAssocTable pointer. */
77: Cursor mouse_cursor; /* Mouse cursor. */
78: int freeze; /* Freeze server mode. */
79: int tile_count; /* Number of tiles created by XMakeTiles. */
80:
81: XMStyle p_style; /* Pane display style. */
82: char *p_fnt_name; /* Flag font name. */
83: FontInfo *p_fnt_info; /* Flag font information. */
84: int p_fnt_pad; /* Flag font padding in pixels. */
85: double p_spread; /* Pane spread in flag height fractions. */
86: int p_bdr_width; /* Pane border width. */
87: int flag_height; /* Flag window height. */
88: int p_height; /* Pane window height. */
89: int p_x_off; /* Pane X offset. */
90: int p_y_off; /* Pane Y offset. */
91:
92: XMStyle s_style; /* Selection display style. */
93: char *s_fnt_name; /* Selection font name. */
94: FontInfo *s_fnt_info; /* Selection font information. */
95: int s_fnt_pad; /* Selection font padding in pixels. */
96: double s_spread; /* Select spread in line height fractions. */
97: int s_bdr_width; /* Highlight border width. */
98: int s_height; /* Selection window height. */
99: int s_x_off; /* Selection window X offset. */
100: int s_y_off; /* Selection window Y offset. */
101:
102: Color color_def; /* Color definition holder. */
103: int p_bdr_color; /* Color of border pixmap. */
104: int s_bdr_color; /* Color of highlight pixmap. */
105: int p_frg_color; /* Color of pane foreground pixmap. */
106: int s_frg_color; /* Color of selection foreground pixmap. */
107: int bkgnd_color; /* Color of background pixmap. */
108: int mouse_color; /* Color of mouse cursor. */
109:
110: Bitmap inact_bitmap; /* Inactive background pattern bitmap. */
111: int inact_pnum; /* Inactive background pattern number. */
112:
113: Pixmap p_bdr_pixmap; /* Pane border pixmap. */
114: Pixmap s_bdr_pixmap; /* Selection border pixmap. */
115: Pixmap p_frg_pixmap; /* Pane forground pixmap. */
116: Pixmap s_frg_pixmap; /* Selection forground pixmap. */
117: Pixmap bkgnd_pixmap; /* Menu background pixmap. */
118: Pixmap inact_pixmap; /* Menu inactive pixmap. */
119:
120: TileFrame tile_buf[TILE_BUF_SIZE]; /* XMakeTiles buffer. */
121:
122: /*
123: * Calloc the XMenu structure and the initial pane.
124: */
125: menu = (XMenu *)calloc(1, sizeof(XMenu));
126: if (menu == NULL) {
127: _XMErrorCode = XME_CALLOC;
128: return(NULL);
129: }
130: pane = (XMPane *)calloc(1, sizeof(XMPane));
131: if (pane == NULL) {
132: _XMErrorCode = XME_CALLOC;
133: return(NULL);
134: }
135:
136: /*
137: * Create the XAssocTable.
138: */
139: assoc_tab = (XAssocTable *)XCreateAssocTable(XASSOC_TABLE_SIZE);
140: if (assoc_tab == NULL) {
141: _XMErrorCode = XME_CREATE_ASSOC;
142: return(NULL);
143: }
144:
145: /*
146: * Set up the default environment name.
147: */
148: if (def_env == NULL || *def_env == '\0') def_env = "XMenu";
149:
150: /*
151: * Set up internal fail-safe defaults.
152: */
153: freeze = DEF_FREEZE;
154: menu_style = DEF_MENU_STYLE;
155: menu_mode = DEF_MENU_MODE;
156: inact_pnum = DEF_INACT_PNUM;
157:
158: p_style = DEF_P_STYLE;
159: p_spread = DEF_P_SPREAD;
160: p_fnt_name = DEF_P_FNT_NAME;
161: p_bdr_width = DEF_P_BDR_WIDTH;
162:
163: s_style = DEF_S_STYLE;
164: s_spread = DEF_S_SPREAD;
165: s_fnt_name = DEF_S_FNT_NAME;
166: s_bdr_width = DEF_S_BDR_WIDTH;
167:
168: p_bdr_color = DEF_P_BDR_COLOR;
169: s_bdr_color = DEF_S_BDR_COLOR;
170: p_frg_color = DEF_P_FRG_COLOR;
171: s_frg_color = DEF_S_FRG_COLOR;
172: bkgnd_color = DEF_BKGND_COLOR;
173: mouse_color = DEF_MOUSE_COLOR;
174:
175: /*
176: * Get default values from X.
177: */
178: def_val = XGetDefault(def_env, "MenuFreeze");
179: if (def_val != NULL) {
180: if (strcmp(def_val, "on") == 0) freeze = 1;
181: else if (strcmp(def_val, "off") == 0) freeze = 0;
182: }
183:
184: def_val = XGetDefault(def_env, "MenuStyle");
185: if (def_val != NULL) {
186: if (strcmp(def_val, "right_hand") == 0) menu_style = RIGHT;
187: else if (strcmp(def_val, "left_hand") == 0) menu_style = LEFT;
188: else if (strcmp(def_val, "center") == 0) menu_style = CENTER;
189: }
190:
191: def_val = XGetDefault(def_env, "MenuMode");
192: if (def_val != NULL) {
193: if (strcmp(def_val, "box") == 0) menu_mode = BOX;
194: else if (strcmp(def_val, "invert") == 0) menu_mode = INVERT;
195: }
196:
197: def_val = XGetDefault(def_env, "MenuMouse");
198: if (def_val != NULL) {
199: if (DisplayCells() > 2) {
200: if (
201: XParseColor(def_val, &color_def) &&
202: XGetHardwareColor(&color_def)
203: ) mouse_color = color_def.pixel;
204: else mouse_color = DEF_S_BDR_COLOR;
205: }
206: else if (strcmp(def_val, "black") == 0) mouse_color = BlackPixel;
207: else if (strcmp(def_val, "white") == 0) mouse_color = WhitePixel;
208: }
209:
210: def_val = XGetDefault(def_env, "MenuBackground");
211: if (def_val != NULL) {
212: if (DisplayCells() > 2) {
213: if (
214: XParseColor(def_val, &color_def) &&
215: XGetHardwareColor(&color_def)
216: ) bkgnd_color = color_def.pixel;
217: else bkgnd_color = DEF_BKGND_COLOR;
218: }
219: else if (strcmp(def_val, "black") == 0) bkgnd_color = BlackPixel;
220: else if (strcmp(def_val, "white") == 0) bkgnd_color = WhitePixel;
221: }
222:
223: def_val = XGetDefault(def_env, "MenuInactivePattern");
224: if (def_val != NULL) {
225: if (strcmp(def_val, "dimple1") == 0) inact_pnum = 0;
226: else if (strcmp(def_val, "dimple3") == 0) inact_pnum = 1;
227: else if (strcmp(def_val, "gray1") == 0) inact_pnum = 2;
228: else if (strcmp(def_val, "gray3") == 0) inact_pnum = 3;
229: else if (strcmp(def_val, "cross_weave") == 0) inact_pnum = 4;
230: }
231:
232: def_val = XGetDefault(def_env, "PaneStyle");
233: if (def_val != NULL) {
234: if (strcmp(def_val, "flush_left") == 0) p_style = LEFT;
235: else if (strcmp(def_val, "flush_right") == 0) p_style = RIGHT;
236: else if (strcmp(def_val, "center") == 0) p_style = CENTER;
237: }
238:
239: def_val = XGetDefault(def_env, "PaneFont");
240: if (def_val != NULL) p_fnt_name = def_val;
241:
242: def_val = XGetDefault(def_env, "PaneForeground");
243: if (def_val != NULL) {
244: if (DisplayCells() > 2) {
245: if (
246: XParseColor(def_val, &color_def) &&
247: XGetHardwareColor(&color_def)
248: ) p_frg_color = color_def.pixel;
249: else p_frg_color = DEF_P_FRG_COLOR;
250: }
251: else if (strcmp(def_val, "black") == 0) p_frg_color = BlackPixel;
252: else if (strcmp(def_val, "white") == 0) p_frg_color = WhitePixel;
253: }
254:
255: def_val = XGetDefault(def_env, "PaneBorder");
256: if (def_val != NULL) {
257: if (DisplayCells() > 2) {
258: if (
259: XParseColor(def_val, &color_def) &&
260: XGetHardwareColor(&color_def)
261: ) p_bdr_color = color_def.pixel;
262: else p_bdr_color = DEF_P_BDR_COLOR;
263: }
264: else if (strcmp(def_val, "black") == 0) p_bdr_color = BlackPixel;
265: else if (strcmp(def_val, "white") == 0) p_bdr_color = WhitePixel;
266: }
267:
268: def_val = XGetDefault(def_env, "PaneBorderWidth");
269: if (def_val != NULL) p_bdr_width = atoi(def_val);
270:
271: def_val = XGetDefault(def_env, "PaneSpread");
272: if (def_val != NULL) p_spread = atof(def_val);
273:
274: def_val = XGetDefault(def_env, "SelectionStyle");
275: if (def_val != NULL) {
276: if (strcmp(def_val, "flush_left") == 0) s_style = LEFT;
277: else if (strcmp(def_val, "flush_right") == 0) s_style = RIGHT;
278: else if (strcmp(def_val, "center") == 0) s_style = CENTER;
279: }
280:
281: def_val = XGetDefault(def_env, "SelectionFont");
282: if (def_val != NULL) s_fnt_name = def_val;
283:
284: def_val = XGetDefault(def_env, "SelectionForeground");
285: if (def_val != NULL) {
286: if (DisplayCells() > 2) {
287: if (
288: XParseColor(def_val, &color_def) &&
289: XGetHardwareColor(&color_def)
290: ) s_frg_color = color_def.pixel;
291: else s_frg_color = DEF_S_FRG_COLOR;
292: }
293: else if (strcmp(def_val, "black") == 0) s_frg_color = BlackPixel;
294: else if (strcmp(def_val, "white") == 0) s_frg_color = WhitePixel;
295: }
296:
297: def_val = XGetDefault(def_env, "SelectionBorder");
298: if (def_val != NULL) {
299: if (DisplayCells() > 2) {
300: if (
301: XParseColor(def_val, &color_def) &&
302: XGetHardwareColor(&color_def)
303: ) s_bdr_color = color_def.pixel;
304: else s_bdr_color = DEF_S_BDR_COLOR;
305: }
306: else if (strcmp(def_val, "black") == 0) s_bdr_color = BlackPixel;
307: else if (strcmp(def_val, "white") == 0) s_bdr_color = WhitePixel;
308: }
309:
310: def_val = XGetDefault(def_env, "SelectionBorderWidth");
311: if (def_val != NULL) s_bdr_width = atoi(def_val);
312:
313: def_val = XGetDefault(def_env, "SelectionSpread");
314: if (def_val != NULL) s_spread = atof(def_val);
315:
316: /*
317: * Create and store the inactive pattern pixmap.
318: */
319: switch (inact_pnum) {
320: case 0:
321: inact_bitmap = XStoreBitmap(16, 16, dimple1_bits);
322: break;
323: case 1:
324: inact_bitmap = XStoreBitmap(16, 16, dimple3_bits);
325: break;
326: case 2:
327: inact_bitmap = XStoreBitmap(16, 16, gray1_bits);
328: break;
329: case 3:
330: inact_bitmap = XStoreBitmap(16, 16, gray3_bits);
331: break;
332: case 4:
333: inact_bitmap = XStoreBitmap(16, 16, cross_weave_bits);
334: break;
335: }
336: if (inact_bitmap == _X_FAILURE) {
337: _XMErrorCode = XME_STORE_BITMAP;
338: return(NULL);
339: }
340:
341: /*
342: * Generate the pixmaps from the background and forground colors.
343: */
344: tile_buf[0].pixel = p_bdr_color;
345: tile_buf[1].pixel = s_bdr_color;
346: tile_buf[2].pixel = p_frg_color;
347: tile_buf[3].pixel = s_frg_color;
348: tile_buf[4].pixel = bkgnd_color;
349:
350: tile_count = XMakeTiles(tile_buf, TILE_BUF_SIZE);
351: if (tile_count != TILE_BUF_SIZE) {
352: _XMErrorCode = XME_MAKE_TILES;
353: return(NULL);
354: }
355:
356: p_bdr_pixmap = tile_buf[0].pixmap;
357: s_bdr_pixmap = tile_buf[1].pixmap;
358: p_frg_pixmap = tile_buf[2].pixmap;
359: s_frg_pixmap = tile_buf[3].pixmap;
360: bkgnd_pixmap = tile_buf[4].pixmap;
361:
362: /*
363: * Generate the inactive pixmap.
364: */
365: inact_pixmap = XMakePixmap(inact_bitmap, p_frg_color, bkgnd_color);
366: if (inact_pixmap == _X_FAILURE) {
367: _XMErrorCode = XME_MAKE_PIXMAP;
368: return(NULL);
369: }
370:
371: /*
372: * Free the inactive pattern bitmap since we no longer need it.
373: */
374: XFreeBitmap(inact_bitmap);
375:
376: /*
377: * Load the mouse cursor.
378: */
379: switch (menu_style) {
380: case :
381: mouse_cursor = XCreateCursor(
382: right_ptr_width, right_ptr_height,
383: right_ptr_bits, right_ptr_mask_bits,
384: right_ptr_x_hot, right_ptr_y_hot,
385: mouse_color, bkgnd_color,
386: GXcopy
387: );
388: break;
389: case :
390: mouse_cursor = XCreateCursor(
391: left_ptr_width, left_ptr_height,
392: left_ptr_bits, left_ptr_mask_bits,
393: left_ptr_x_hot, left_ptr_y_hot,
394: mouse_color, bkgnd_color,
395: GXcopy
396: );
397: break;
398: case :
399: mouse_cursor = XCreateCursor(
400: center_ptr_width, center_ptr_height,
401: center_ptr_bits, center_ptr_mask_bits,
402: center_ptr_x_hot, center_ptr_y_hot,
403: mouse_color, bkgnd_color,
404: GXcopy
405: );
406: break;
407: default:
408: /* Error! Invalid style parameter. */
409: _XMErrorCode = XME_STYLE_PARAM;
410: return(NULL);
411: }
412: if (mouse_cursor == _X_FAILURE) {
413: _XMErrorCode = XME_CREATE_CURSOR;
414: return(NULL);
415: }
416:
417: /*
418: * Open the pane and selection fonts.
419: */
420: p_fnt_info = XOpenFont(p_fnt_name);
421: if (p_fnt_info == NULL) {
422: _XMErrorCode = XME_OPEN_FONT;
423: return(NULL);
424: }
425: s_fnt_info = XOpenFont(s_fnt_name);
426: if (s_fnt_info == NULL) {
427: _XMErrorCode = XME_OPEN_FONT;
428: return(NULL);
429: }
430:
431: /*
432: * Calculate the fixed padding value in pixels for each font.
433: */
434: p_fnt_pad = s_spread * p_fnt_info->height;
435: s_fnt_pad = s_spread * s_fnt_info->height;
436:
437: /*
438: * Calculate fixed height and offset requirements.
439: */
440: flag_height = p_fnt_info->height + (p_fnt_pad << 1);
441:
442: p_height = 0;
443: p_y_off = flag_height + p_bdr_width;
444: p_x_off = p_y_off * p_spread;
445:
446: s_height = s_fnt_info->height + (s_fnt_pad << 1) + (s_bdr_width << 1);
447: s_y_off = s_height;
448: s_x_off = p_x_off;
449:
450: /*
451: * Set up the pane list header.
452: */
453: pane->next = pane;
454: pane->prev = pane;
455: pane->type = PL_HEADER;
456: pane->serial = -1;
457:
458: /*
459: * Initialize the internal pane and selection creation queues.
460: */
461: _XMWinQueInit();
462:
463: /*
464: * Construct the XMenu object.
465: */
466: /* -------------------- Menu data -------------------- */
467: menu->menu_style = menu_style;
468: menu->menu_mode = menu_mode;
469: menu->freeze = freeze;
470: menu->recompute = 1;
471: menu->parent = parent;
472: menu->height = 0;
473: menu->width = 0;
474: menu->mouse_cursor = mouse_cursor;
475: menu->assoc_tab = assoc_tab;
476: menu->p_list = pane;
477: /* -------------------- Pane window data -------------------- */
478: menu->p_style = p_style;
479: menu->p_events = DEF_P_EVENTS;
480: menu->p_fnt_info = p_fnt_info;
481: menu->p_fnt_pad = p_fnt_pad;
482: menu->p_spread = p_spread;
483: menu->p_bdr_width = p_bdr_width;
484: menu->flag_height = flag_height;
485: menu->p_width = 0;
486: menu->p_height = p_height;
487: menu->p_x_off = p_x_off;
488: menu->p_y_off = p_y_off;
489: menu->p_count = 0;
490: /* -------------------- Selection window data -------------------- */
491: menu->s_style = s_style;
492: menu->s_events = DEF_S_EVENTS;
493: menu->s_fnt_info = s_fnt_info;
494: menu->s_fnt_pad = s_fnt_pad;
495: menu->s_spread = s_spread;
496: menu->s_bdr_width = s_bdr_width;
497: menu->s_width = 0;
498: menu->s_height = s_height;
499: menu->s_x_off = s_x_off;
500: menu->s_y_off = s_y_off;
501: menu->s_count = 0;
502: /* -------------------- Color data -------------------- */
503: menu->p_bdr_color = p_bdr_color;
504: menu->s_bdr_color = s_bdr_color;
505: menu->p_frg_color = p_frg_color;
506: menu->s_frg_color = s_frg_color;
507: menu->bkgnd_color = bkgnd_color;
508: /* -------------------- Pixmap data -------------------- */
509: menu->p_bdr_pixmap = p_bdr_pixmap;
510: menu->s_bdr_pixmap = s_bdr_pixmap;
511: menu->p_frg_pixmap = p_frg_pixmap;
512: menu->s_frg_pixmap = s_frg_pixmap;
513: menu->bkgnd_pixmap = bkgnd_pixmap;
514: menu->inact_pixmap = inact_pixmap;
515:
516: /*
517: * Return the completed XMenu.
518: */
519: _XMErrorCode = XME_NO_ERROR;
520: return(menu);
521: }