1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 #ifdef HAVE_CONFIG_H
30 #include "../config.h"
31 #endif
32
33 #include "DialogF.h"
34 #include "misc.h"
35 #include "nedit_malloc.h"
36
37 #include <stdio.h>
38 #include <stdarg.h>
39 #include <string.h>
40 #include <ctype.h>
41 #include <limits.h>
42
43 #include <Xm/Xm.h>
44 #include <Xm/MessageB.h>
45 #include <Xm/DialogS.h>
46 #include <Xm/PushB.h>
47 #include <Xm/PushBG.h>
48 #include <Xm/SelectioB.h>
49 #include <X11/StringDefs.h>
50 #include <X11/Intrinsic.h>
51 #include <X11/keysym.h>
52
53 #ifdef HAVE_DEBUG_H
54 #include "../debug.h"
55 #endif
56
57 #define NUM_DIALOGS_SUPPORTED 6
58 #define NUM_BUTTONS_SUPPORTED 3
59 #define NUM_BUTTONS_MAXPROMPT 4
60 #define MAX_TITLE_LEN 256
61
62 enum dialogBtnIndecies {
OK_BTN,
APPLY_BTN,
CANCEL_BTN,
HELP_BTN};
63
64 struct dfcallbackstruct {
65 unsigned button;
66 Boolean done_with_dialog;
67 unsigned apply_up;
68 Boolean destroyed;
69 };
70
71 static char **PromptHistory =
NULL;
72 static int NPromptHistoryItems = -
1;
73
74 static void apply_callback (Widget w,
struct dfcallbackstruct *client_data,
75 caddr_t call_data);
76 static void help_callback (Widget w,
struct dfcallbackstruct *client_data,
77 caddr_t call_data);
78 static void cancel_callback (Widget w,
struct dfcallbackstruct *client_data,
79 caddr_t call_data);
80 static void ok_callback (Widget w,
struct dfcallbackstruct *client_data,
81 caddr_t call_data);
82 static void destroy_callback (Widget w,
struct dfcallbackstruct *client_data,
83 caddr_t call_data);
84 static void focusCB(Widget w, Widget dialog,
caddr_t call_data);
85 static void addEscapeHandler(Widget dialog,
struct dfcallbackstruct *df,
86 int whichBtn);
87 static void escapeHelpCB(Widget w, XtPointer callData, XEvent *event,
88 Boolean *cont);
89 static void escapeApplyCB(Widget w, XtPointer callData, XEvent *event,
90 Boolean *cont);
91 static void createMnemonics(Widget w);
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147 unsigned DialogF(
int dialog_type, Widget parent,
unsigned n,
const char* title,
148 const char* msgstr, ...)
149 {
150 va_list var;
151
152 Widget dialog, dialog_shell;
153 unsigned dialog_num, prompt;
154 XmString but_lbl_xms[
NUM_BUTTONS_MAXPROMPT];
155 XmString msgstr_xms, input_string_xms, titstr_xms;
156 char msgstr_vsp[
DF_MAX_MSG_LENGTH+
1];
157 char *but_lbl, *input_string =
NULL, *input_string_ptr;
158 int argcount, num_but_lbls =
0, i, but_index, cancel_index = -
1;
159 Arg args[
256];
160 char titleCopy[
MAX_TITLE_LEN];
161
162 struct dfcallbackstruct df;
163
164 static int dialog_types[] = {
165 XmDIALOG_ERROR,
166 XmDIALOG_INFORMATION,
167 XmDIALOG_MESSAGE,
168 XmDIALOG_QUESTION,
169 XmDIALOG_WARNING,
170 XmDIALOG_PROMPT
171 };
172 static char *dialog_name[] = {
173 "Error",
174 "Information",
175 "Message",
176 "Question",
177 "Warning",
178 "Prompt"
179 };
180
181 static unsigned char selectionButton_id[] =
182 {
183 XmDIALOG_OK_BUTTON,
184 XmDIALOG_APPLY_BUTTON,
185 XmDIALOG_CANCEL_BUTTON,
186 XmDIALOG_HELP_BUTTON
187 };
188 Cardinal
N_SELECTION_BUTTONS = XtNumber(selectionButton_id);
189
190 static unsigned char messageButton_id[] =
191 {
192 XmDIALOG_OK_BUTTON,
193 XmDIALOG_CANCEL_BUTTON,
194 XmDIALOG_HELP_BUTTON
195 };
196 Cardinal
N_MESSAGE_BUTTONS = XtNumber(messageButton_id);
197
198 static char *button_name[] = {
199 XmNokLabelString,
200 XmNapplyLabelString,
201 XmNcancelLabelString,
202 XmNhelpLabelString
203 };
204
205
206 if ((dialog_type >
NUM_DIALOGS_SUPPORTED) || (dialog_type <=
0)) {
207 printf (
"\nError calling DialogF - Unsupported dialog type\n");
208 return (
0);
209 }
210 dialog_num = dialog_type -
1;
211 prompt = (dialog_type ==
DF_PROMPT);
212 if ((!prompt && (n >
NUM_BUTTONS_SUPPORTED)) ||
213 (prompt && (n >
NUM_BUTTONS_MAXPROMPT))) {
214 printf (
"\nError calling DialogF - Too many buttons specified\n");
215 return (
0);
216 }
217
218 df.done_with_dialog = False;
219 df.destroyed = False;
220
221 va_start (var, msgstr);
222 if (prompt) {
223 input_string = va_arg(var,
char*);
224 }
225 if (n ==
NUM_BUTTONS_MAXPROMPT)
226 df.apply_up =
1;
227 else
228 df.apply_up =
0;
229 for (argcount =
0; argcount < (
int)n; ++argcount) {
230 but_lbl = va_arg(var,
char *);
231 but_lbl_xms[num_but_lbls] = XmStringCreateLtoR (but_lbl,
232 XmSTRING_DEFAULT_CHARSET);
233 but_index = df.apply_up ? argcount :
234 ((argcount ==
0) ? argcount : argcount+
1);
235 XtSetArg (args[argcount], button_name[but_index],
236 but_lbl_xms[num_but_lbls++]);
237 if (!strcmp(but_lbl,
"Cancel") || !strcmp(but_lbl,
"Dismiss"))
238 cancel_index = but_index;
239 }
240 if (n ==
1)
241 cancel_index =
0;
242
243
244
245
246
247
248
249
250
251
252 vsprintf (msgstr_vsp, msgstr, var);
253 va_end(var);
254
255 strncpy(&titleCopy[
0], title,
MAX_TITLE_LEN);
256 titleCopy[
MAX_TITLE_LEN-
1] =
'\0';
257
258 msgstr_xms = XmStringCreateLtoR(msgstr_vsp, XmSTRING_DEFAULT_CHARSET);
259 titstr_xms = XmStringCreateLtoR(titleCopy, XmSTRING_DEFAULT_CHARSET);
260
261 if (prompt) {
262 XtSetArg (args[argcount], XmNselectionLabelString, msgstr_xms);
263 argcount++;
264 XtSetArg (args[argcount], XmNdialogTitle, titstr_xms);
265 argcount++;
266 XtSetArg (args[argcount], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL);
267 argcount ++;
268
269 dialog = CreatePromptDialog(parent, dialog_name[dialog_num], args,
270 argcount);
271 XtAddCallback (dialog, XmNokCallback, (XtCallbackProc)ok_callback,
272 (
char *)&df);
273 XtAddCallback (dialog, XmNcancelCallback,
274 (XtCallbackProc)cancel_callback, (
char *)&df);
275 XtAddCallback (dialog, XmNhelpCallback, (XtCallbackProc)help_callback,
276 (
char *)&df);
277 XtAddCallback (dialog, XmNapplyCallback, (XtCallbackProc)apply_callback,
278 (
char *)&df);
279 RemapDeleteKey(XmSelectionBoxGetChild(dialog, XmDIALOG_TEXT));
280
281
282
283
284
285 XtVaSetValues(dialog, XmNdefaultButton,
NULL,
NULL);
286 XtAddCallback(XmSelectionBoxGetChild(dialog, XmDIALOG_TEXT),
287 XmNfocusCallback, (XtCallbackProc)focusCB, (
char *)dialog);
288
289
290 XtVaSetValues(XmSelectionBoxGetChild(dialog, XmDIALOG_TEXT),
291 XmNmaxLength,
DF_MAX_PROMPT_LENGTH-
1,
NULL);
292
293
294
295 switch (n) {
296 case 0:
case 3:
297 break;
298 case 1:
299 XtUnmanageChild (XmSelectionBoxGetChild (dialog,
300 XmDIALOG_CANCEL_BUTTON) );
301 case 2:
302 XtUnmanageChild (XmSelectionBoxGetChild (dialog,
303 XmDIALOG_HELP_BUTTON) );
304 break;
305 case 4:
306 XtManageChild (XmSelectionBoxGetChild (dialog,
307 XmDIALOG_APPLY_BUTTON) );
308 df.apply_up =
1;
309 default:
310 break;
311 }
312
313
314 for (i =
0; (
unsigned) i <
N_SELECTION_BUTTONS; i++)
315 {
316 Widget button = XmSelectionBoxGetChild(dialog, selectionButton_id[i]);
317
318 if (XtIsManaged(button))
319 {
320 XtVaSetValues(button, XmNmarginWidth,
BUTTON_WIDTH_MARGIN,
NULL);
321 }
322 }
323
324
325
326
327
328 if (cancel_index == -
1)
329 addEscapeHandler(dialog,
NULL,
0);
330 else if (cancel_index !=
CANCEL_BTN)
331 addEscapeHandler(dialog, &df, cancel_index);
332
333
334 AddMotifCloseCallback(XtParent(dialog),
335 (XtCallbackProc)(cancel_index ==
APPLY_BTN ? apply_callback :
336 (cancel_index ==
CANCEL_BTN ? cancel_callback :
337 (cancel_index ==
HELP_BTN ? help_callback : ok_callback))), &df);
338
339
340
341 XtAddCallback(dialog, XmNdestroyCallback,
342 (XtCallbackProc)destroy_callback, &df);
343
344
345
346 if (NPromptHistoryItems != -
1)
347 AddHistoryToTextWidget(XmSelectionBoxGetChild(dialog,XmDIALOG_TEXT),
348 &PromptHistory, &NPromptHistoryItems);
349
350
351 ManageDialogCenteredOnPointer(dialog);
352
353
354
355 for (i=
0; i<
20; i++)
356 XmProcessTraversal(XmSelectionBoxGetChild(dialog, XmDIALOG_TEXT),
357 XmTRAVERSE_CURRENT);
358
359
360 while (!df.done_with_dialog && !df.destroyed)
361 XtAppProcessEvent (XtWidgetToApplicationContext(dialog), XtIMAll);
362
363 if (!df.destroyed) {
364 argcount =
0;
365 XtSetArg (args[argcount], XmNtextString, &input_string_xms); argcount++;
366 XtGetValues (dialog, args, argcount);
367 XmStringGetLtoR (input_string_xms, XmSTRING_DEFAULT_CHARSET,
368 &input_string_ptr);
369 strcpy (input_string, input_string_ptr);
370 XmStringFree(input_string_xms );
371 NEditFree(input_string_ptr);
372
373 XtRemoveCallback(dialog, XmNdestroyCallback,
374 (XtCallbackProc)destroy_callback, &df);
375 XtDestroyWidget(dialog);
376 }
377 PromptHistory =
NULL;
378 NPromptHistoryItems = -
1;
379 }
380
381 else {
382 XtSetArg (args[argcount], XmNmessageString, msgstr_xms); argcount++;
383
384 XtSetArg (args[argcount], XmNdialogType, dialog_types[dialog_num]);
385 argcount ++;
386 XtSetArg (args[argcount], XmNdialogTitle, titstr_xms);
387 argcount++;
388 XtSetArg (args[argcount], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL);
389 argcount ++;
390
391 dialog_shell = CreateDialogShell (parent, dialog_name[dialog_num],
392 0,
0);
393 dialog = XmCreateMessageBox (dialog_shell,
"msg box", args, argcount);
394
395 XtAddCallback (dialog, XmNokCallback, (XtCallbackProc)ok_callback,
396 (
char *)&df);
397 XtAddCallback (dialog, XmNcancelCallback,
398 (XtCallbackProc)cancel_callback, (
char *)&df);
399 XtAddCallback (dialog, XmNhelpCallback, (XtCallbackProc)help_callback,
400 (
char *)&df);
401
402
403 switch (n) {
404 case 0:
case 3:
405 break;
406 case 1:
407 XtUnmanageChild (XmMessageBoxGetChild (dialog,
408 XmDIALOG_CANCEL_BUTTON) );
409 case 2:
410 XtUnmanageChild (XmMessageBoxGetChild (dialog,
411 XmDIALOG_HELP_BUTTON) );
412 break;
413 default:
414 break;
415 }
416
417
418 for (i =
0; (
unsigned) i <
N_MESSAGE_BUTTONS; i++)
419 {
420 Widget button = XmMessageBoxGetChild(dialog, messageButton_id[i]);
421
422 if (XtIsManaged(button))
423 {
424 XtVaSetValues(button, XmNmarginWidth,
BUTTON_WIDTH_MARGIN,
NULL);
425 }
426 }
427
428
429 createMnemonics(dialog_shell);
430 AddDialogMnemonicHandler(dialog_shell,
TRUE);
431
432
433
434
435
436 if (cancel_index == -
1)
437 addEscapeHandler(dialog,
NULL,
0);
438 else if (cancel_index !=
CANCEL_BTN)
439 addEscapeHandler(dialog, &df, cancel_index);
440
441
442 AddMotifCloseCallback(XtParent(dialog),
443 (XtCallbackProc)(cancel_index ==
APPLY_BTN ? apply_callback :
444 (cancel_index ==
CANCEL_BTN ? cancel_callback :
445 (cancel_index ==
HELP_BTN ? help_callback : ok_callback))),&df);
446
447
448
449 XtAddCallback(dialog_shell, XmNdestroyCallback,
450 (XtCallbackProc)destroy_callback, &df);
451
452
453 ManageDialogCenteredOnPointer(dialog);
454 while (!df.done_with_dialog && !df.destroyed)
455 XtAppProcessEvent (XtWidgetToApplicationContext(dialog), XtIMAll);
456
457 if (!df.destroyed) {
458
459 XtRemoveCallback(dialog_shell, XmNdestroyCallback,
460 (XtCallbackProc)destroy_callback, &df);
461 XtDestroyWidget(dialog_shell);
462 }
463 }
464
465 XmStringFree(msgstr_xms);
466 XmStringFree(titstr_xms);
467 for (i =
0; i < num_but_lbls; ++i)
468 XmStringFree(but_lbl_xms[i]);
469
470
471
472 if (df.destroyed) {
473 df.button = cancel_index ==
APPLY_BTN ?
2 :
474 (cancel_index ==
CANCEL_BTN ?
2 + df.apply_up :
475 (cancel_index ==
HELP_BTN ?
3 + df.apply_up :
1));
476 }
477
478 df.apply_up =
0;
479
480 return (df.button);
481 }
482
483
484
485
486
487
488
489 void SetDialogFPromptHistory(
char **historyList,
int nItems)
490 {
491 PromptHistory = historyList;
492 NPromptHistoryItems = nItems;
493 }
494
495 static void ok_callback (Widget w,
struct dfcallbackstruct *client_data,
496 caddr_t call_data)
497 {
498 client_data->done_with_dialog = True;
499 client_data->button =
1;
500 }
501
502 static void cancel_callback (Widget w,
struct dfcallbackstruct *client_data,
503 caddr_t call_data)
504 {
505 client_data->done_with_dialog = True;
506 client_data->button =
2 + client_data->apply_up;
507 }
508
509 static void help_callback (Widget w,
struct dfcallbackstruct *client_data,
510 caddr_t call_data)
511 {
512 client_data->done_with_dialog = True;
513 client_data->button =
3 + client_data->apply_up;
514 }
515
516 static void apply_callback (Widget w,
struct dfcallbackstruct *client_data,
517 caddr_t call_data)
518 {
519 client_data->done_with_dialog = True;
520 client_data->button =
2;
521 }
522
523 static void destroy_callback (Widget w,
struct dfcallbackstruct *client_data,
524 caddr_t call_data)
525 {
526 client_data->destroyed = True;
527 }
528
529
530
531
532
533 static void focusCB(Widget w, Widget dialog,
caddr_t call_data)
534 {
535 XtVaSetValues(dialog, XmNdefaultButton,
536 XmSelectionBoxGetChild(dialog, XmDIALOG_OK_BUTTON),
NULL);
537 }
538
539
540
541
542
543
544
545
546
547
548
549 static void addEscapeHandler(Widget dialog,
struct dfcallbackstruct *df,
550 int whichBtn)
551 {
552 XtAddEventHandler(dialog, KeyPressMask, False, whichBtn ==
APPLY_BTN ?
553 escapeApplyCB : escapeHelpCB, (XtPointer)df);
554 XtGrabKey(dialog, XKeysymToKeycode(XtDisplay(dialog), XK_Escape),
0,
555 True, GrabModeAsync, GrabModeAsync);
556 }
557
558
559
560
561
562 static void escapeHelpCB(Widget w, XtPointer callData, XEvent *event,
563 Boolean *cont)
564 {
565 if (event->xkey.keycode != XKeysymToKeycode(XtDisplay(w), XK_Escape))
566 return;
567 if (callData !=
NULL)
568 help_callback(w, (
struct dfcallbackstruct *)callData,
NULL);
569 *cont = False;
570 }
571
572
573
574
575
576 static void escapeApplyCB(Widget w, XtPointer callData, XEvent *event,
577 Boolean *cont)
578 {
579 if (event->xkey.keycode != XKeysymToKeycode(XtDisplay(w), XK_Escape))
580 return;
581 if (callData !=
NULL)
582 apply_callback(w, (
struct dfcallbackstruct *)callData,
NULL);
583 *cont = False;
584 }
585
586
587
588
589 static void recurseCreateMnemonics(Widget w, Boolean *mnemonicUsed)
590 {
591 WidgetList children;
592 Cardinal numChildren, i;
593
594 XtVaGetValues(w,
595 XmNchildren, &children,
596 XmNnumChildren, &numChildren,
597 NULL);
598
599 for (i =
0; i < numChildren; i++)
600 {
601 Widget child = children[i];
602
603 if (XtIsComposite(child))
604 {
605 recurseCreateMnemonics(child, mnemonicUsed);
606 }
607 else if (XtIsSubclass(child, xmPushButtonWidgetClass) ||
608 XtIsSubclass(child, xmPushButtonGadgetClass))
609 {
610 XmString xmslabel;
611 char *label;
612 int c;
613
614 XtVaGetValues(child, XmNlabelString, &xmslabel,
NULL);
615 if (XmStringGetLtoR(xmslabel, XmSTRING_DEFAULT_CHARSET, &label))
616 {
617
618 int labelLen = strlen(label);
619 for (c =
0; c < labelLen; c++)
620 {
621 unsigned char lc = tolower((
unsigned char)label[c]);
622
623 if (!mnemonicUsed[lc] && isalnum(lc))
624 {
625 mnemonicUsed[lc] =
TRUE;
626 XtVaSetValues(child, XmNmnemonic, label[c],
NULL);
627 break;
628 }
629 }
630
631 NEditFree(label);
632 }
633 XmStringFree(xmslabel);
634 }
635 }
636 }
637
638
639
640
641
642
643
644 static void createMnemonics(Widget w)
645 {
646 Boolean mnemonicUsed[
UCHAR_MAX +
1];
647 memset(mnemonicUsed,
FALSE,
sizeof(mnemonicUsed));
648 recurseCreateMnemonics(w, mnemonicUsed);
649 }
650