1 /* Copyright (C) 1993, 1992 Nathan Sidwell */ 2 /* RCS $Id: dialogs.c,v 4.6 1994/01/25 18:33:03 nathan Stable $ */ 3 /*{{{ includes*/ 4 #include "xmred.h" 5 #include <X11/Xaw/Dialog.h> 6 #include <X11/Shell.h> 7 #include <X11/StringDefs.h> 8 #include <X11/Xaw/Text.h> 9 #include <X11/Xaw/Label.h> 10 /*}}}*/ 11 /*{{{ structs*/ 12 /*{{{ typedef struct Dialog*/ 13 typedef struct Dialog 14 { 15 char CONST *name; /* shell name */ 16 char CONST *prompt; /* dialog label */ 17 unsigned input; /* input permitted */ 18 unsigned options; /* selections permitted */ 19 unsigned selection; /* selection made */ 20 unsigned up; /* popped up */ 21 Widget shell; /* shell widget */ 22 Widget dialog; /* dialog widget */ 23 int x; /* warp back point */ 24 int y; /* warp back point */ 25 Widget warp; /* warp back widget */ 26 } DIALOG; 27 /*}}}*/ 28 /*{{{ typedef struct Dialog_Option*/ 29 typedef struct Dialog_Option 30 { 31 char CONST *text; /* button text */ 32 unsigned option; /* option mask */ 33 } DIALOG_OPTION; 34 /*}}}*/ 35 /*}}}*/ 36 /*{{{ tables*/ 37 /*{{{ DIALOG_OPTION CONST dialog_options[] =*/ 38 static DIALOG_OPTION CONST dialog_options[] = 39 { 40 {"ok", DIALOG_OK}, 41 {"retry", DIALOG_RETRY}, 42 {"continue", DIALOG_CONTINUE}, 43 {"default", DIALOG_DEFAULT}, 44 {"cancel", DIALOG_CANCEL}, 45 {"abort", DIALOG_ABORT}, 46 {"agree", DIALOG_AGREE}, 47 {"disagree", DIALOG_DISAGREE}, 48 {"clear", DIALOG_CLEAR}, 49 {NULL} 50 }; 51 /*}}}*/ 52 /*{{{ DIALOG dialogs[DIALOGS] =*/ 53 static DIALOG dialogs[DIALOGS] = 54 { 55 {"file", "Enter filename", 1, DIALOG_OK | DIALOG_CANCEL | DIALOG_CLEAR}, 56 {"altered", "Changes not saved", 0, DIALOG_CONTINUE | DIALOG_ABORT}, 57 {"error", NULL, 1, DIALOG_RETRY | DIALOG_ABORT}, 58 {"load", "Format errors", 1, DIALOG_OK}, 59 {"comment", "Enter comment", 1, DIALOG_OK | DIALOG_CANCEL | DIALOG_CLEAR}, 60 {"include", "Enter filename", 1, 61 DIALOG_OK | DIALOG_DEFAULT | DIALOG_CANCEL | DIALOG_CLEAR}, 62 {"failed", "Operation failed", 1, DIALOG_OK}, 63 }; 64 /*}}}*/ 65 /*}}}*/ 66 /*{{{ prototypes*/ 67 static VOIDFUNC dialog_action 68 PROTOARG((Widget, XEvent *, String *, Cardinal *)); 69 static VOIDFUNC dialog_option PROTOARG((Widget, XtPointer, XtPointer)); 70 /*}}}*/ 71 /*{{{ void dialog_action(widget, event, argv, argc)*/ 72 static VOIDFUNC dialog_action 73 FUNCARG((widget, event, argv, argc), 74 Widget widget 75 ARGSEP XEvent *event 76 ARGSEP String *argv 77 ARGSEP Cardinal *argc 78 ) 79 /* action routine for the dialog buttons, 80 * presses all the dialog buttons matching the given arguments 81 */ 82 { 83 DIALOG_OPTION CONST *optr; 84 unsigned count; 85 86 for(count = *argc; count--; argv++) 87 for(optr = dialog_options; optr->text; optr ++) 88 if(!strcmp(optr->text, *argv)) 89 { 90 dialog_option(widget, (XtPointer)optr->option, (XtPointer)NULL); 91 break; 92 } 93 return; 94 } 95 /*}}}*/ 96 /*{{{ void dialog_append(dialog, string)*/ 97 extern VOIDFUNC dialog_append 98 FUNCARG((dialog, string), 99 unsigned dialog 100 ARGSEP char CONST *string /* string to append */ 101 ) 102 /* appends a string to a dialog's text box 103 */ 104 { 105 XawTextBlock text; 106 Widget widget; 107 108 widget = XtNameToWidget(dialogs[dialog].dialog, "*value"); 109 assert(widget); 110 text.firstPos = 0; 111 text.length = strlen(string); 112 text.ptr = (char *)string; 113 text.format = FMT8BIT; 114 XawTextReplace(widget, (XawTextPosition)32767, 115 (XawTextPosition)32767, &text); 116 return; 117 } 118 /*}}}*/ 119 /*{{{ void dialog_option(widget, client, call)*/ 120 static VOIDFUNC dialog_option 121 FUNCARG((widget, client, call), 122 Widget widget 123 ARGSEP XtPointer client 124 ARGSEP XtPointer call 125 ) 126 /* callback on the dialog buttons. 127 * most of these just set an appropriate bit in the select mask 128 * For thos on the dialogs selection list, the dialog is popped down 129 * and the pointer unwarped 130 * The clear button, finds the dialog's text widget, and 131 * removes all the text from it. 132 */ 133 { 134 while(widget && strcmp(XtName(widget), "dialog")) 135 widget = XtParent(widget); 136 if(!widget) 137 /* EMPTY */; 138 else if((unsigned)client == DIALOG_CLEAR) 139 { 140 Widget text; 141 142 text = XtNameToWidget(widget, "*value"); 143 if(text) 144 { 145 XawTextBlock block; 146 147 block.firstPos = 0; 148 block.length = 0; 149 block.ptr = NULL; 150 block.format = FMT8BIT; 151 XawTextReplace(text, 0, 32767, &block); 152 } 153 } 154 else 155 { 156 unsigned count; 157 DIALOG *dptr; 158 159 for(dptr = dialogs, count = DIALOGS; count--; dptr++) 160 if(dptr->dialog == widget) 161 { 162 dptr->selection |= 163 (unsigned)client & dptr->options; 164 if(dptr->selection && dptr->up) 165 { 166 dptr->up = 0; 167 if(dptr->warp) 168 XWarpPointer(XtDisplay(dptr->shell), XtWindow(dptr->shell), 169 XtWindow(dptr->warp), 0, 0, 0, 0, dptr->x, dptr->y); 170 XtPopdown(dptr->shell); 171 } 172 break; 173 } 174 } 175 return; 176 } 177 /*}}}*/ 178 /*{{{ void dialog_popup(dialog, title, suggestion, anchor, grab)*/ 179 extern VOIDFUNC dialog_popup 180 FUNCARG((dialog, title, suggestion, anchor, grab), 181 unsigned dialog /* dialog to popup */ 182 ARGSEP char CONST *title /* title or NULL */ 183 ARGSEP char CONST *suggestion /* suggested text or NULL */ 184 ARGSEP Widget anchor /* widget to anchor the popup from */ 185 ARGSEP XtGrabKind grab /* grab mode */ 186 ) 187 /* pops up a dialog widget 1/4 in from the top left corner of 188 * the anchor widget. 189 * Sets the warp return values if within the anchor widget, and 190 * warps the pointer to the bottom of the dialog 191 */ 192 { 193 DIALOG *dptr; 194 Position topx, topy; 195 Dimension topw, toph; 196 Dimension w, h; 197 198 dptr = &dialogs[dialog]; 199 dptr->selection = 0; 200 dptr->warp = anchor; 201 if(anchor) 202 XtVaGetValues(anchor, XtNx, (XtArgVal)&topx, XtNy, (XtArgVal)&topy, 203 XtNwidth, (XtArgVal)&topw, XtNheight, (XtArgVal)&toph, NULL); 204 /*{{{ setup for warp back*/ 205 if(anchor) 206 { 207 Boolean warp; 208 Window root; 209 Window child; 210 unsigned mask; 211 int rx, ry; 212 213 warp = XQueryPointer(display.display, XtWindow(anchor), 214 &root, &child, &rx, &ry, &dptr->x, &dptr->y, &mask); 215 if(warp == False || dptr->x < 0 || dptr->y < 0 || 216 dptr->x >= topw || dptr->y >= toph) 217 dptr->warp = NULL; 218 } 219 /*}}}*/ 220 if(title) 221 XtVaSetValues(dptr->shell, XtNtitle, (XtArgVal)title, NULL); 222 assert(dptr->input ? !!suggestion : !suggestion); 223 XtVaSetValues(dptr->dialog, XtNvalue, (XtArgVal)suggestion, NULL); 224 XtRealizeWidget(dptr->shell); 225 if(!dptr->up) 226 { 227 if(anchor) 228 { 229 XtVaGetValues(dptr->shell, XtNwidth, &w, XtNheight, &h, NULL); 230 topx = topx + (topw - w) / 4; 231 topy = topy + (toph - h) / 4; 232 XtVaSetValues(dptr->shell, XtNx, (XtArgVal)topx, 233 XtNy, (XtArgVal)topy, NULL); 234 } 235 XtPopup(dptr->shell, grab); 236 dptr->up = 1; 237 } 238 if(dptr->warp) 239 XWarpPointer(XtDisplay(dptr->shell), XtWindow(dptr->warp), 240 XtWindow(dptr->shell), 0, 0, 0, 0, w / 2, h - 8); 241 return; 242 } 243 /*}}}*/ 244 /*{{{ unsigned dialog_wait(dialog, title, label, suggestion, result)*/ 245 extern unsigned dialog_wait 246 FUNCARG((dialog, title, label, suggestion, result), 247 unsigned dialog /* dialog to use */ 248 ARGSEP char CONST *title /* title or NULL */ 249 ARGSEP char CONST *label /* label or NULL */ 250 ARGSEP char CONST *suggestion /* initial text or NULL */ 251 ARGSEP char CONST **result /* returned text buffer or NULL */ 252 ) 253 /* popup a dialog and wait for a reply. 254 * returns the text selection, this must be copied to a safe 255 * place, if you want to keep it. 256 */ 257 { 258 DIALOG *dptr; 259 unsigned option; 260 261 dptr = &dialogs[dialog]; 262 if(label) 263 XtVaSetValues(dptr->dialog, XtNlabel, label, NULL); 264 dialog_popup(dialog, title, suggestion || !result ? suggestion : "", 265 display.toplevel, XtGrabExclusive); 266 while(!dptr->selection) 267 { 268 XEvent event; 269 270 XtAppNextEvent(display.context, &event); 271 #ifdef DEBUGEVENTLOOP 272 fprintf(stderr, "Event %lu, Window 0x%lx\n", 273 (long)event.xany.type, (long)event.xany.window); 274 #endif /* DEBUGEVENTLOOP */ 275 XtDispatchEvent(&event); 276 } 277 option = dptr->selection; 278 if(result) 279 { 280 char CONST *ptr; 281 282 ptr = XawDialogGetValueString(dptr->dialog); 283 *result = ptr && *ptr ? ptr : NULL; 284 } 285 return option; 286 } 287 /*}}}*/ 288 /*{{{ void install_dialogs(root)*/ 289 extern VOIDFUNC install_dialogs 290 FUNCARG((root), 291 Widget root 292 ) 293 /* install the dialog popup widgets 294 */ 295 { 296 /*{{{ static XtActionsRec actions[] =*/ 297 static XtActionsRec actions[] = 298 { 299 {"set-dialog-button", dialog_action}, 300 }; 301 /*}}}*/ 302 unsigned ix; 303 DIALOG *dptr; 304 305 XtAppAddActions(display.context, actions, XtNumber(actions)); 306 for(dptr = &dialogs[DIALOGS - 1], ix = DIALOGS; ix--; dptr--) 307 { 308 unsigned count; 309 310 dptr->shell = XtVaCreatePopupShell(dptr->name, 311 transientShellWidgetClass, root, NULL); 312 dptr->dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass, 313 dptr->shell, NULL); 314 for(count = 0; count != 8; count++) 315 if(dptr->options & (1 << count)) 316 { 317 DIALOG_OPTION CONST *optr; 318 319 for(optr = dialog_options; optr->text; optr++) 320 if(optr->option & (1 << count)) 321 { 322 XawDialogAddButton(dptr->dialog, optr->text, 323 dialog_option, (XtPointer)(1 << count)); 324 break; 325 } 326 } 327 if(dptr->input) 328 XtVaSetValues(dptr->dialog, XtNvalue, (XtArgVal)"", NULL); 329 nadger_widget_colors(dptr->shell, (WidgetClass)NULL); 330 if(dptr->prompt) 331 XtVaSetValues(dptr->dialog, 332 XtNlabel, (XtArgVal)dptr->prompt, NULL); 333 } 334 return; 335 } 336 /*}}}*/ 337