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