|
|
1.1 root 1:
2: #include <X11/Xlib.h>
3: #include <X11/cursorfont.h>
4:
5: #ifndef lint
6: static char *rcsid_dialog_c = "$Header: dialog.c,v 1.2 87/09/04 19:14:52 newman Exp $";
7: #endif
8:
9: char *malloc();
10:
11: extern Display *d;
12: extern int screen;
13: extern GC gc;
14: extern unsigned long foreground;
15: extern unsigned long background;
16: extern unsigned long border;
17: extern int borderwidth;
18: extern int invertplane;
19:
20: #define NULL 0
21: #define MIN_BETWEEN_COMMANDS 10
22: #define BETWEEN_LINES 10
23: #define TOP_MARGIN 10
24: #define BOTTOM_MARGIN 10
25: #define MSG_RIGHT_MARGIN 7
26: #define MSG_LEFT_MARGIN 7
27: #define COMMAND_WIDTH_FUDGE 8
28:
29: #define max(a,b) ((a > b) ? a : b)
30:
31: static Cursor cross_cursor;
32:
33: static struct dialog_data {
34: Window w;
35: XFontStruct *font;
36: char *msg1, *msg2;
37: int msg1_length, msg2_length;
38: struct command_data *command_info;
39: };
40:
41: static struct command_data {
42: Window window;
43: char *name;
44: int name_length;
45: int name_width; /* in pixels */
46: int x_offset;
47: };
48:
49: int dialog (w, font,
50: msg1, msg2, command_names, n_commands, input_handler)
51: Window w;
52: XFontStruct *font;
53: char *msg1, *msg2;
54: char **command_names;
55: unsigned int n_commands;
56: int (*input_handler) ();
57: {
58: struct dialog_data data;
59: static int initialized = 0;
60: int msg1_width = XTextWidth (font, msg1, strlen(msg1));
61: int msg2_width = XTextWidth (font, msg2, strlen(msg2));
62: int command_width = 0;
63: int font_height = font->ascent + font->descent;
64: int result;
65: register int i;
66:
67: if (!initialized) {
68: Initialize ();
69: initialized = 1;
70: }
71:
72: data.font = font;
73: data.msg1 = msg1;
74: data.msg2 = msg2;
75: data.msg1_length = strlen (msg1);
76: data.msg2_length = strlen (msg2);
77: data.command_info = (struct command_data *) malloc
78: (n_commands*sizeof (struct command_data));
79:
80: for (i=0;i<n_commands;i++) {
81: struct command_data *cmd = &data.command_info[i];
82: cmd->name = command_names[i];
83: cmd->name_length = strlen (cmd->name);
84: cmd->name_width = XTextWidth (font, cmd->name, cmd->name_length);
85: if (cmd->name_width > command_width)
86: command_width = cmd->name_width;
87: }
88: command_width += COMMAND_WIDTH_FUDGE;
89:
90: {
91: int between_commands;
92: {
93: int height = 3*font_height + 2*BETWEEN_LINES + TOP_MARGIN + BOTTOM_MARGIN;
94: int width = max (msg1_width, msg2_width)
95: + MSG_LEFT_MARGIN + MSG_RIGHT_MARGIN;
96: int min_width =
97: n_commands*command_width + (n_commands+1)*MIN_BETWEEN_COMMANDS;
98: int x, y;
99: XSetWindowAttributes attrs;
100: attrs.border_pixel = border;
101: attrs.background_pixel = background;
102: attrs.cursor = cross_cursor;
103: attrs.event_mask = ExposureMask;
104: attrs.override_redirect = 1;
105:
106: DeterminePlace (w, &x, &y);
107: width = max (width, min_width);
108: between_commands =
109: (width - n_commands*command_width)/(n_commands+1);
110: data.w = XCreateWindow (d, RootWindow(d, screen), x, y, width, height,
111: borderwidth, CopyFromParent, CopyFromParent, CopyFromParent,
112: CWBorderPixel | CWBackPixel | CWOverrideRedirect | CWCursor | CWEventMask, &attrs);
113: }
114:
115: {
116: int x = between_commands;
117: int y = TOP_MARGIN + 2*(font_height + BETWEEN_LINES);
118: for (i=0;i<n_commands;i++) {
119: register struct command_data *command = &data.command_info[i];
120: command->x_offset = (command_width - command->name_width)/2;
121: command->window = XCreateSimpleWindow (d, data.w, x, y, command_width,
122: font_height, 1, border, background);
123: XSelectInput (d, command->window,
124: ButtonPressMask | ButtonReleaseMask | ExposureMask | LeaveWindowMask);
125: x += (between_commands + command_width);
126: }
127: }}
128:
129: XMapWindow (d, data.w);
130: XMapSubwindows (d, data.w);
131:
132: while (1) {
133: struct command_data *command = NULL;
134: XEvent event;
135: XNextEvent (d, &event);
136: if (event.xany.window == data.w) {
137: ProcessDialogWindowEvent (&data, &event);
138: continue;
139: }
140: for (i=0;i<n_commands;i++)
141: if (event.xany.window == data.command_info[i].window) {
142: command = &data.command_info[i];
143: break;
144: }
145: if (command) {
146: result = ProcessCommandEvent (&data, command, &event);
147: if (result >= 0)
148: break;
149: }
150: else
151: /* event doesn't belong to any of the dialog box's windows.
152: Send it back to the calling application. */
153: (*input_handler) (&event);
154: }
155:
156: XDestroyWindow (d, data.w);
157:
158: free ((char *)data.command_info);
159: return (result);
160: } /* end of dialog procedure */
161:
162:
163: Initialize ()
164: {
165: cross_cursor = XCreateFontCursor (d, XC_crosshair);
166: }
167:
168:
169: /* ProcessCommandEvent returns -1 unless a command was actually invoked,
170: in which case it returns the command number. */
171:
172: static int ProcessCommandEvent (data, command, event)
173: struct dialog_data *data;
174: struct command_data *command;
175: XEvent *event;
176: {
177: static struct command_data *button_down_command = NULL;
178:
179: switch (event->type) {
180:
181: case Expose:
182: if (event->xexpose.count == 0) {
183: XSetState (d, gc, foreground, background, GXcopy, AllPlanes);
184: XDrawString (d, command->window, gc, command->x_offset,
185: data->font->ascent, command->name, command->name_length);
186: }
187: break;
188:
189: case ButtonPress:
190: if (button_down_command != NULL)
191: break; /* must be second button press; ignore it */
192: button_down_command = command;
193: InvertCommand (command);
194: break;
195:
196: case LeaveNotify:
197: if (command == button_down_command) {
198: InvertCommand (command);
199: button_down_command = NULL;
200: }
201: break;
202:
203: case ButtonRelease:
204: if (command == button_down_command) {
205: button_down_command = NULL;
206: return (command - data->command_info);
207: }
208: break;
209:
210: }
211:
212: return (-1);
213: }
214:
215:
216: static ProcessDialogWindowEvent (data, event)
217: struct dialog_data *data;
218: XEvent *event;
219: {
220: if (event->type == Expose && event->xexpose.count == 0) {
221: int y = TOP_MARGIN + data->font->ascent;
222: XSetState (d, gc, foreground, background, GXcopy, AllPlanes);
223: XDrawString (d, data->w, gc, MSG_LEFT_MARGIN, y,
224: data->msg1, data->msg1_length);
225: y += data->font->descent + BETWEEN_LINES + data->font->ascent;
226: XDrawString (d, data->w, gc, MSG_LEFT_MARGIN, y,
227: data->msg2, data->msg2_length);
228: }
229: }
230:
231:
232: static InvertCommand (command)
233: struct command_data *command;
234: {
235: XSetState (d, gc, 1L, 0L, GXinvert, invertplane);
236: XFillRectangle (d, command->window, gc, 0, 0, 400, 400);
237: }
238:
239:
240: static DeterminePlace (w, px, py)
241: Window w;
242: int *px, *py;
243: {
244: int x, y;
245: long trash;
246: XGetGeometry (d, w, &trash, &x, &y, &trash, &trash, &trash, &trash);
247: /* max (0,...) is to make sure dialog window is on screen, even
248: if "parent" window is partially off screen (negative x or y) */
249: *px = max (0, x + 10);
250: *py = max (0, y + 10);
251: }
252:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.