|
|
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.