|
|
1.1 root 1: #include <X/mit-copyright.h>
2:
3: /* Copyright 1985, Massachusetts Institute of Technology */
4: #include <X/Xlib.h>
5:
6: #ifndef lint
7: static char *rcsid_dialog_c = "$Header: dialog.c,v 10.4 86/02/01 15:18:29 tony Rel $";
8: #endif
9:
10: extern int foreground;
11: extern int background;
12: extern Pixmap backmap;
13: extern Pixmap border;
14: extern int borderwidth;
15: extern int invertplane;
16: extern int mousepix;
17:
18: #define NULL 0
19: #define MIN_BETWEEN_COMMANDS 10
20: #define BETWEEN_LINES 10
21: #define TOP_MARGIN 10
22: #define BOTTOM_MARGIN 10
23: #define MSG_RIGHT_MARGIN 7
24: #define MSG_LEFT_MARGIN 7
25: #define COMMAND_WIDTH_FUDGE 8
26:
27: #define max(a,b) ((a > b) ? a : b)
28:
29: #include "../cursors/cross.cursor"
30: #include "../cursors/cross_mask.cursor"
31: static Cursor cross_cursor;
32:
33: static struct dialog_data {
34: Window w;
35: Font font;
36: int font_height;
37: char *msg1, *msg2;
38: int msg1_length, msg2_length;
39: struct command_data *command_info;
40: };
41:
42: static struct command_data {
43: Window window;
44: char *name;
45: int name_length;
46: int name_width; /* in pixels */
47: int x_offset;
48: };
49:
50: int dialog (w, font, font_height,
51: msg1, msg2, command_names, n_commands, input_handler)
52: Window w;
53: Font font;
54: int font_height;
55: char *msg1, *msg2;
56: char **command_names;
57: int n_commands;
58: int (*input_handler) ();
59: {
60: struct dialog_data data;
61: static int initialized = 0;
62: int msg1_width = XQueryWidth (msg1, font);
63: int msg2_width = XQueryWidth (msg2, font);
64: int command_width = 0;
65: int result;
66: register int i;
67:
68: if (!initialized) {
69: Initialize ();
70: initialized = 1;
71: }
72:
73: data.font = font;
74: data.font_height = font_height;
75: data.msg1 = msg1;
76: data.msg2 = msg2;
77: data.msg1_length = strlen (msg1);
78: data.msg2_length = strlen (msg2);
79: data.command_info = (struct command_data *) malloc
80: (n_commands*sizeof (struct command_data));
81:
82: for (i=0;i<n_commands;i++) {
83: data.command_info[i].name = command_names[i];
84: data.command_info[i].name_length = strlen (command_names[i]);
85: data.command_info[i].name_width = XQueryWidth (command_names[i], font);
86: if (data.command_info[i].name_width > command_width)
87: command_width = data.command_info[i].name_width;
88: }
89: command_width += COMMAND_WIDTH_FUDGE;
90:
91: {
92: int between_commands;
93: {
94: int height =
95: 3*font_height + 2*BETWEEN_LINES + TOP_MARGIN + BOTTOM_MARGIN;
96: int width = max (msg1_width, msg2_width)
97: + MSG_LEFT_MARGIN + MSG_RIGHT_MARGIN;
98: int min_width =
99: n_commands*command_width + (n_commands+1)*MIN_BETWEEN_COMMANDS;
100: int x, y;
101: DeterminePlace (w, &x, &y);
102: width = max (width, min_width);
103: between_commands =
104: (width - n_commands*command_width)/(n_commands+1);
105: data.w = XCreateWindow (RootWindow, x, y, width, height,
106: borderwidth, border, backmap);
107: }
108:
109: {
110: int xx = between_commands;
111: OpaqueFrame *frames = (OpaqueFrame *)malloc(n_commands*sizeof(OpaqueFrame));
112: for (i=0;i<n_commands;i++) {
113: register OpaqueFrame *frame = &frames[i];
114: register struct command_data *command = &data.command_info[i];
115: command->x_offset = (command_width - command->name_width)/2;
116: frame->x = xx;
117: frame->y = TOP_MARGIN + 2*(font_height+BETWEEN_LINES);
118: frame->width = command_width;
119: frame->height = font_height;
120: frame->bdrwidth = 1;
121: frame->border = border;
122: frame->background = backmap;
123: xx += (between_commands + command_width);
124: }
125: XCreateWindows (data.w, frames, n_commands);
126: for (i=0;i<n_commands;i++)
127: data.command_info[i].window = frames[i].self;
128: free (frames);
129: }}
130:
131: XSelectInput (data.w,
132: ButtonPressed | ButtonReleased | ExposeWindow | LeaveWindow);
133:
134: XDefineCursor (data.w, cross_cursor);
135: XMapWindow (data.w);
136: XMapSubwindows (data.w);
137:
138: while (1) {
139: struct command_data *command = NULL;
140: XEvent event;
141: XNextEvent (&event);
142: if (event.window != data.w) {
143: (*input_handler) (&event);
144: continue; /* back around the loop */
145: }
146: if (event.subwindow == 0) {
147: ProcessDialogWindowEvent (&data, &event);
148: continue;
149: }
150: for (i=0;i<n_commands;i++)
151: if (event.subwindow == data.command_info[i].window) {
152: command = &data.command_info[i];
153: break;
154: }
155: if (command == NULL)
156: continue; /* really shouldn't happen, but what can you do? */
157: result = ProcessCommandEvent (&data, command, &event);
158: if (result >= 0)
159: break;
160: }
161:
162: XDestroyWindow (data.w);
163:
164: free (data.command_info);
165: return (result);
166: } /* end of dialog procedure */
167:
168:
169: Initialize ()
170: {
171: cross_cursor = XCreateCursor (cross_width, cross_height, cross_bits,
172: cross_mask_bits, cross_x_hot, cross_y_hot,
173: mousepix, background, GXcopy);
174: }
175:
176:
177: /* ProcessCommandEvent returns -1 unless a command was actually invoked,
178: in which case it returns the command number. */
179:
180: static int ProcessCommandEvent (data, command, event)
181: struct dialog_data *data;
182: struct command_data *command;
183: XEvent *event;
184: {
185: static struct command_data *button_down_command = NULL;
186:
187: switch (event->type) {
188:
189: case ExposeWindow:
190: XTextMask (command->window, command->x_offset,
191: 0, command->name, command->name_length, data->font, foreground);
192: break;
193:
194: case ButtonPressed:
195: if (button_down_command != NULL)
196: break; /* must be second button press; ignore it */
197: button_down_command = command;
198: InvertCommand (data, command);
199: break;
200:
201: case LeaveWindow:
202: if (command == button_down_command) {
203: InvertCommand (data, command);
204: button_down_command = NULL;
205: }
206: break;
207:
208: case ButtonReleased:
209: if (command == button_down_command) {
210: button_down_command = NULL;
211: return (command - data->command_info);
212: }
213: break;
214:
215: }
216:
217: return (-1);
218: }
219:
220:
221: static ProcessDialogWindowEvent (data, event)
222: struct dialog_data *data;
223: XEvent *event;
224: {
225: if (event->type == ExposeWindow) {
226: XTextMask (
227: data->w, MSG_LEFT_MARGIN,
228: TOP_MARGIN, data->msg1, data->msg1_length, data->font, foreground);
229: XTextMask (
230: data->w, MSG_LEFT_MARGIN,
231: TOP_MARGIN + data->font_height + BETWEEN_LINES,
232: data->msg2, data->msg2_length, data->font, foreground);
233: }
234: }
235:
236:
237: static InvertCommand (data, command)
238: struct dialog_data *data;
239: struct command_data *command;
240: {
241: XPixFill (command->window, 0, 0, 400, data->font_height, 1, NULL,
242: GXinvert, invertplane);
243: }
244:
245:
246: static DeterminePlace (w, px, py)
247: Window w;
248: int *px, *py;
249: {
250: WindowInfo info;
251: XQueryWindow (w, &info);
252: /* max (0,...) is to make sure dialog window is on screen, even
253: if "parent" window is partially off screen (negative x or y) */
254: *px = max (0, info.x + 10);
255: *py = max (0, info.y + 10);
256: }
257:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.