Close notifier socket before re-exec of daemon. Bug 2539
[exim.git] / src / exim_monitor / em_TextPop.c
1 /***********************************************************
2 Copyright 1989 by the Massachusetts Institute of Technology,
3 Cambridge, Massachusetts.
4
5 All Rights Reserved
6
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the names of Digital or MIT not be
12 used in advertising or publicity pertaining to distribution of the
13 software without specific, written prior permission.
14
15 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
16 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
17 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
18 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
19 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
20 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
21 SOFTWARE.
22
23 ******************************************************************/
24
25
26 /****************************************************************************
27 * Modified by Philip Hazel for use with Exim. The "replace" and "insert *
28 * file" features of the search facility have been removed. Also took out *
29 * the declaration of sys_errlist, as it isn't used and causes trouble on *
30 * some systems that declare it differently. September 1996. *
31 * Added the arguments into the static functions declared at the head, to *
32 * stop some compiler warnings. August 1999. *
33 * Took out the separate declarations of errno and sys_nerr at the start, *
34 * because they too aren't actually used, and the declaration causes trouble *
35 * on some systems. December 2002. *
36 ****************************************************************************/
37
38
39 /************************************************************
40 *
41 * This file is broken up into three sections one dealing with
42 * each of the three popups created here:
43 *
44 * FileInsert, Search, and Replace.
45 *
46 * There is also a section at the end for utility functions
47 * used by all more than one of these dialogs.
48 *
49 * The following functions are the only non-static ones defined
50 * in this module. They are located at the beginning of the
51 * section that contains this dialog box that uses them.
52 *
53 * void _XawTextInsertFileAction(w, event, params, num_params);
54 * void _XawTextDoSearchAction(w, event, params, num_params);
55 * void _XawTextDoReplaceAction(w, event, params, num_params);
56 * void _XawTextInsertFile(w, event, params, num_params);
57 *
58 *************************************************************/
59
60 #include <X11/IntrinsicP.h>
61 #include <X11/StringDefs.h>
62 #include <X11/Shell.h>
63
64 #include <X11/Xaw/TextP.h>
65 #include <X11/Xaw/AsciiText.h>
66 #include <X11/Xaw/Cardinals.h>
67 #include <X11/Xaw/Command.h>
68 #include <X11/Xaw/Form.h>
69 #include <X11/Xaw/Toggle.h>
70 #include <X11/Xmu/CharSet.h>
71 #include <stdio.h>
72 #include <X11/Xos.h> /* for O_RDONLY */
73 #include <errno.h>
74
75 /* extern int errno, sys_nerr; */
76 /* extern char* sys_errlist[]; */
77
78 #define DISMISS_NAME ("cancel")
79 #define DISMISS_NAME_LEN 6
80 #define FORM_NAME ("form")
81 #define LABEL_NAME ("label")
82 #define TEXT_NAME ("text")
83
84 #define R_OFFSET 1
85
86 /* Argument types added by PH August 1999 */
87
88 static void CenterWidgetOnPoint(Widget, XEvent *);
89 static void PopdownSearch(Widget, XtPointer, XtPointer);
90 static void InitializeSearchWidget(struct SearchAndReplace *,
91 XawTextScanDirection, Boolean);
92 static void SetResource(Widget, char *, XtArgVal);
93 static void SetSearchLabels(struct SearchAndReplace *, String, String,
94 Boolean);
95 static Widget CreateDialog(Widget, String, String,
96 void (*)(Widget, char *, Widget));
97 static Widget GetShell(Widget);
98 static void SetWMProtocolTranslations(Widget w);
99 static Boolean DoSearch(struct SearchAndReplace *);
100 static String GetString(Widget);
101
102 static void AddSearchChildren(Widget, char *, Widget);
103
104 static char radio_trans_string[] =
105 "<Btn1Down>,<Btn1Up>: set() notify()";
106
107 static char search_text_trans[] =
108 "~Shift<Key>Return: DoSearchAction(Popdown) \n\
109 Ctrl<Key>c: PopdownSearchAction() \n\
110 ";
111
112
113
114 /************************************************************
115 *
116 * This section of the file contains all the functions that
117 * the search dialog box uses.
118 *
119 ************************************************************/
120
121 /* Function Name: _XawTextDoSearchAction
122 * Description: Action routine that can be bound to dialog box's
123 * Text Widget that will search for a string in the main
124 * Text Widget.
125 * Arguments: (Standard Action Routine args)
126 * Returns: none.
127 *
128 * Note:
129 *
130 * If the search was successful and the argument popdown is passed to
131 * this action routine then the widget will automatically popdown the
132 * search widget.
133 */
134
135 /* ARGSUSED */
136 void
137 _XawTextDoSearchAction(w, event, params, num_params)
138 Widget w;
139 XEvent *event;
140 String * params;
141 Cardinal * num_params;
142 {
143 TextWidget tw = (TextWidget) XtParent(XtParent(XtParent(w)));
144 Boolean popdown = FALSE;
145
146 if ( (*num_params == 1) &&
147 ((params[0][0] == 'p') || (params[0][0] == 'P')) )
148 popdown = TRUE;
149
150 if (DoSearch(tw->text.search) && popdown)
151 PopdownSearch(w, (XtPointer) tw->text.search, NULL);
152 }
153
154 /* Function Name: _XawTextPopdownSearchAction
155 * Description: Action routine that can be bound to dialog box's
156 * Text Widget that will popdown the search widget.
157 * Arguments: (Standard Action Routine args)
158 * Returns: none.
159 */
160
161 /* ARGSUSED */
162 void
163 _XawTextPopdownSearchAction(w, event, params, num_params)
164 Widget w;
165 XEvent *event;
166 String * params;
167 Cardinal * num_params;
168 {
169 TextWidget tw = (TextWidget) XtParent(XtParent(XtParent(w)));
170
171 PopdownSearch(w, (XtPointer) tw->text.search, NULL);
172 }
173
174 /* Function Name: PopdownSearch
175 * Description: Pops down the search widget and resets it.
176 * Arguments: w - *** NOT USED ***.
177 * closure - a pointer to the search structure.
178 * call_data - *** NOT USED ***.
179 * Returns: none
180 */
181
182 /* ARGSUSED */
183 static void
184 PopdownSearch(w, closure, call_data)
185 Widget w;
186 XtPointer closure;
187 XtPointer call_data;
188 {
189 struct SearchAndReplace * search = (struct SearchAndReplace *) closure;
190
191 SetSearchLabels(search, "Search", "", FALSE);
192 XtPopdown( search->search_popup );
193 }
194
195 /* Function Name: SearchButton
196 * Description: Performs a search when the button is clicked.
197 * Arguments: w - *** NOT USED **.
198 * closure - a pointer to the search info.
199 * call_data - *** NOT USED ***.
200 * Returns:
201 */
202
203 /* ARGSUSED */
204 static void
205 SearchButton(w, closure, call_data)
206 Widget w;
207 XtPointer closure;
208 XtPointer call_data;
209 {
210 (void) DoSearch( (struct SearchAndReplace *) closure );
211 }
212
213 /* Function Name: _XawTextSearch
214 * Description: Action routine that can be bound to the text widget
215 * it will popup the search dialog box.
216 * Arguments: w - the text widget.
217 * event - X Event (used to get x and y location).
218 * params, num_params - the parameter list.
219 * Returns: none.
220 *
221 * NOTE:
222 *
223 * The parameter list contains one or two entries that may be the following.
224 *
225 * First Entry: The first entry is the direction to search by default.
226 * This argument must be specified and may have a value of
227 * "left" or "right".
228 *
229 * Second Entry: This entry is optional and contains the value of the default
230 * string to search for.
231 */
232
233 #define SEARCH_HEADER ("Text Widget - Search():")
234
235 void
236 _XawTextSearch(w, event, params, num_params)
237 Widget w;
238 XEvent *event;
239 String * params;
240 Cardinal * num_params;
241 {
242 TextWidget ctx = (TextWidget)w;
243 XawTextScanDirection dir;
244 char * ptr, buf[BUFSIZ];
245 XawTextEditType edit_mode;
246 Arg args[1];
247
248 #ifdef notdef
249 if (ctx->text.source->Search == NULL) {
250 XBell(XtDisplay(w), 0);
251 return;
252 }
253 #endif
254
255 if ( (*num_params < 1) || (*num_params > 2) ) {
256 sprintf(buf, "%s %s\n%s", SEARCH_HEADER, "This action must have only",
257 "one or two parameters");
258 XtAppWarning(XtWidgetToApplicationContext(w), buf);
259 return;
260 }
261 else if (*num_params == 1)
262 ptr = "";
263 else
264 ptr = params[1];
265
266 switch(params[0][0]) {
267 case 'b': /* Left. */
268 case 'B':
269 dir = XawsdLeft;
270 break;
271 case 'f': /* Right. */
272 case 'F':
273 dir = XawsdRight;
274 break;
275 default:
276 sprintf(buf, "%s %s\n%s", SEARCH_HEADER, "The first parameter must be",
277 "Either 'backward' or 'forward'");
278 XtAppWarning(XtWidgetToApplicationContext(w), buf);
279 return;
280 }
281
282 if (ctx->text.search== NULL) {
283 ctx->text.search = XtNew(struct SearchAndReplace);
284 ctx->text.search->search_popup = CreateDialog(w, ptr, "search",
285 AddSearchChildren);
286 XtRealizeWidget(ctx->text.search->search_popup);
287 SetWMProtocolTranslations(ctx->text.search->search_popup);
288 }
289 else if (*num_params > 1) {
290 XtVaSetValues(ctx->text.search->search_text, XtNstring, ptr, NULL);
291 }
292
293 XtSetArg(args[0], XtNeditType,&edit_mode);
294 XtGetValues(ctx->text.source, args, ONE);
295
296 InitializeSearchWidget(ctx->text.search, dir, (edit_mode == XawtextEdit));
297
298 CenterWidgetOnPoint(ctx->text.search->search_popup, event);
299 XtPopup(ctx->text.search->search_popup, XtGrabNone);
300 }
301
302 /* Function Name: InitializeSearchWidget
303 * Description: This function initializes the search widget and
304 * is called each time the search widget is poped up.
305 * Arguments: search - the search widget structure.
306 * dir - direction to search.
307 * replace_active - state of the sensitivity for the
308 * replace button.
309 * Returns: none.
310 */
311
312 static void
313 InitializeSearchWidget(struct SearchAndReplace *search,
314 XawTextScanDirection dir, Boolean replace_active)
315 {
316 replace_active = replace_active; /* PH - shuts compilers up */
317
318 switch (dir) {
319 case XawsdLeft:
320 SetResource(search->left_toggle, XtNstate, (XtArgVal) TRUE);
321 break;
322 case XawsdRight:
323 SetResource(search->right_toggle, XtNstate, (XtArgVal) TRUE);
324 break;
325 default:
326 break;
327 }
328 }
329
330 /* Function Name: AddSearchChildren
331 * Description: Adds all children to the Search Dialog Widget.
332 * Arguments: form - the form widget for the search widget.
333 * ptr - a pointer to the initial string for the Text Widget.
334 * tw - the main text widget.
335 * Returns: none.
336 */
337
338 static void
339 AddSearchChildren(form, ptr, tw)
340 Widget form, tw;
341 char * ptr;
342 {
343 Arg args[10];
344 Cardinal num_args;
345 Widget cancel, search_button, s_label, s_text;
346 XtTranslations trans;
347 struct SearchAndReplace * search = ((TextWidget) tw)->text.search;
348
349 num_args = 0;
350 XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++;
351 XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++;
352 XtSetArg(args[num_args], XtNresizable, TRUE ); num_args++;
353 XtSetArg(args[num_args], XtNborderWidth, 0 ); num_args++;
354 search->label1 = XtCreateManagedWidget("label1", labelWidgetClass,
355 form, args, num_args);
356
357 /*
358 * We need to add R_OFFSET to the radio_data, because the value zero (0)
359 * has special meaning.
360 */
361
362 num_args = 0;
363 XtSetArg(args[num_args], XtNlabel, "Backward"); num_args++;
364 XtSetArg(args[num_args], XtNfromVert, search->label1); num_args++;
365 XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++;
366 XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++;
367 XtSetArg(args[num_args], XtNradioData, (caddr_t) XawsdLeft + R_OFFSET);
368 num_args++;
369 search->left_toggle = XtCreateManagedWidget("backwards", toggleWidgetClass,
370 form, args, num_args);
371
372 num_args = 0;
373 XtSetArg(args[num_args], XtNlabel, "Forward"); num_args++;
374 XtSetArg(args[num_args], XtNfromVert, search->label1); num_args++;
375 XtSetArg(args[num_args], XtNfromHoriz, search->left_toggle); num_args++;
376 XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++;
377 XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++;
378 XtSetArg(args[num_args], XtNradioGroup, search->left_toggle); num_args++;
379 XtSetArg(args[num_args], XtNradioData, (caddr_t) XawsdRight + R_OFFSET);
380 num_args++;
381 search->right_toggle = XtCreateManagedWidget("forwards", toggleWidgetClass,
382 form, args, num_args);
383
384 {
385 XtTranslations radio_translations;
386
387 radio_translations = XtParseTranslationTable(radio_trans_string);
388 XtOverrideTranslations(search->left_toggle, radio_translations);
389 XtOverrideTranslations(search->right_toggle, radio_translations);
390 }
391
392 num_args = 0;
393 XtSetArg(args[num_args], XtNfromVert, search->left_toggle); num_args++;
394 XtSetArg(args[num_args], XtNlabel, "Search for: ");num_args++;
395 XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++;
396 XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++;
397 XtSetArg(args[num_args], XtNborderWidth, 0 ); num_args++;
398 s_label = XtCreateManagedWidget("searchLabel", labelWidgetClass,
399 form, args, num_args);
400
401 num_args = 0;
402 XtSetArg(args[num_args], XtNfromVert, search->left_toggle); num_args++;
403 XtSetArg(args[num_args], XtNfromHoriz, s_label); num_args++;
404 XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++;
405 XtSetArg(args[num_args], XtNright, XtChainRight); num_args++;
406 XtSetArg(args[num_args], XtNeditType, XawtextEdit); num_args++;
407 XtSetArg(args[num_args], XtNresizable, TRUE); num_args++;
408 XtSetArg(args[num_args], XtNresize, XawtextResizeWidth); num_args++;
409 XtSetArg(args[num_args], XtNstring, ptr); num_args++;
410 s_text = XtCreateManagedWidget("searchText", asciiTextWidgetClass, form,
411 args, num_args);
412 search->search_text = s_text;
413
414 num_args = 0;
415 XtSetArg(args[num_args], XtNlabel, "Search"); num_args++;
416 XtSetArg(args[num_args], XtNfromVert, s_text); num_args++;
417 XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++;
418 XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++;
419 search_button = XtCreateManagedWidget("search", commandWidgetClass, form,
420 args, num_args);
421
422 num_args = 0;
423 XtSetArg(args[num_args], XtNlabel, "Cancel"); num_args++;
424 XtSetArg(args[num_args], XtNfromVert, s_text); num_args++;
425 XtSetArg(args[num_args], XtNfromHoriz, search_button); num_args++;
426 XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++;
427 XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++;
428 cancel = XtCreateManagedWidget(DISMISS_NAME, commandWidgetClass, form,
429 args, num_args);
430
431 XtAddCallback(search_button, XtNcallback, SearchButton, (XtPointer) search);
432 XtAddCallback(cancel, XtNcallback, PopdownSearch, (XtPointer) search);
433
434 /*
435 * Initialize the text entry fields.
436 */
437
438 SetSearchLabels(search, "Search", "", FALSE);
439 XtSetKeyboardFocus(form, search->search_text);
440
441 /*
442 * Bind Extra translations.
443 */
444
445 trans = XtParseTranslationTable(search_text_trans);
446 XtOverrideTranslations(search->search_text, trans);
447 }
448
449 /* Function Name: DoSearch
450 * Description: Performs a search.
451 * Arguments: search - the search structure.
452 * Returns: TRUE if successful.
453 */
454
455 /* ARGSUSED */
456 static Boolean
457 DoSearch(search)
458 struct SearchAndReplace * search;
459 {
460 char msg[BUFSIZ];
461 Widget tw = XtParent(search->search_popup);
462 XawTextPosition pos;
463 XawTextScanDirection dir;
464 XawTextBlock text;
465
466 text.ptr = GetString(search->search_text);
467 text.length = strlen(text.ptr);
468 text.firstPos = 0;
469 text.format = FMT8BIT;
470
471 dir = (XawTextScanDirection) ((long)XawToggleGetCurrent(search->left_toggle) -
472 R_OFFSET);
473
474 pos = XawTextSearch( tw, dir, &text);
475
476 if (pos == XawTextSearchError)
477 sprintf( msg, "Could not find string '%s'.", text.ptr);
478 else {
479 if (dir == XawsdRight)
480 XawTextSetInsertionPoint( tw, pos + text.length);
481 else
482 XawTextSetInsertionPoint( tw, pos);
483
484 XawTextSetSelection( tw, pos, pos + text.length);
485 search->selection_changed = FALSE; /* selection is good. */
486 return(TRUE);
487 }
488
489 XawTextUnsetSelection(tw);
490 SetSearchLabels(search, msg, "", TRUE);
491 return(FALSE);
492 }
493
494
495 /* Function Name: SetSearchLabels
496 * Description: Sets both the search labels, and also rings the bell
497 * HACKED: Only one label needed now
498 * Arguments: search - the search structure.
499 * msg1, msg2 - message to put in each search label.
500 * bell - if TRUE then ring bell.
501 * Returns: none.
502 */
503
504 static void
505 SetSearchLabels(struct SearchAndReplace *search, String msg1, String msg2,
506 Boolean bell)
507 {
508 msg2 = msg2; /* PH - shuts compilers up */
509 (void) SetResource( search->label1, XtNlabel, (XtArgVal) msg1);
510 /* (void) SetResource( search->label2, XtNlabel, (XtArgVal) msg2); */
511 if (bell)
512 XBell(XtDisplay(search->search_popup), 0);
513 }
514
515 /************************************************************
516 *
517 * This section of the file contains utility routines used by
518 * other functions in this file.
519 *
520 ************************************************************/
521
522
523 /* Function Name: SetResource
524 * Description: Sets a resource in a widget
525 * Arguments: w - the widget.
526 * res_name - name of the resource.
527 * value - the value of the resource.
528 * Returns: none.
529 */
530
531 static void
532 SetResource(w, res_name, value)
533 Widget w;
534 char * res_name;
535 XtArgVal value;
536 {
537 Arg args[1];
538
539 XtSetArg(args[0], res_name, value);
540 XtSetValues( w, args, ONE );
541 }
542
543 /* Function Name: GetString
544 * Description: Gets the value for the string in the popup.
545 * Arguments: text - the text widget whose string we will get.
546 * Returns: the string.
547 */
548
549 static String
550 GetString(text)
551 Widget text;
552 {
553 String string;
554 Arg args[1];
555
556 XtSetArg( args[0], XtNstring, &string );
557 XtGetValues( text, args, ONE );
558 return(string);
559 }
560
561 /* Function Name: CenterWidgetOnPoint.
562 * Description: Centers a shell widget on a point relative to
563 * the root window.
564 * Arguments: w - the shell widget.
565 * event - event containing the location of the point
566 * Returns: none.
567 *
568 * NOTE: The widget is not allowed to go off the screen.
569 */
570
571 static void
572 CenterWidgetOnPoint(w, event)
573 Widget w;
574 XEvent *event;
575 {
576 Arg args[3];
577 Cardinal num_args;
578 Dimension width, height, b_width;
579 Position x=0, y=0, max_x, max_y;
580
581 if (event != NULL) {
582 switch (event->type) {
583 case ButtonPress:
584 case ButtonRelease:
585 x = event->xbutton.x_root;
586 y = event->xbutton.y_root;
587 break;
588 case KeyPress:
589 case KeyRelease:
590 x = event->xkey.x_root;
591 y = event->xkey.y_root;
592 break;
593 default:
594 return;
595 }
596 }
597
598 num_args = 0;
599 XtSetArg(args[num_args], XtNwidth, &width); num_args++;
600 XtSetArg(args[num_args], XtNheight, &height); num_args++;
601 XtSetArg(args[num_args], XtNborderWidth, &b_width); num_args++;
602 XtGetValues(w, args, num_args);
603
604 width += 2 * b_width;
605 height += 2 * b_width;
606
607 x -= ( (Position) width/2 );
608 if (x < 0) x = 0;
609 if ( x > (max_x = (Position) (XtScreen(w)->width - width)) ) x = max_x;
610
611 y -= ( (Position) height/2 );
612 if (y < 0) y = 0;
613 if ( y > (max_y = (Position) (XtScreen(w)->height - height)) ) y = max_y;
614
615 num_args = 0;
616 XtSetArg(args[num_args], XtNx, x); num_args++;
617 XtSetArg(args[num_args], XtNy, y); num_args++;
618 XtSetValues(w, args, num_args);
619 }
620
621 /* Function Name: CreateDialog
622 * Description: Actually creates a dialog.
623 * Arguments: parent - the parent of the dialog - the main text widget.
624 * ptr - initial_string for the dialog.
625 * name - name of the dialog.
626 * func - function to create the children of the dialog.
627 * Returns: the popup shell of the dialog.
628 *
629 * NOTE:
630 *
631 * The function argument is passed the following arguments.
632 *
633 * form - the from widget that is the dialog.
634 * ptr - the initial string for the dialog's text widget.
635 * parent - the parent of the dialog - the main text widget.
636 */
637
638 static Widget
639 CreateDialog(parent, ptr, name, func)
640 Widget parent;
641 String ptr, name;
642 void (*func)();
643 {
644 Widget popup, form;
645 Arg args[5];
646 Cardinal num_args;
647
648 num_args = 0;
649 XtSetArg(args[num_args], XtNiconName, name); num_args++;
650 XtSetArg(args[num_args], XtNgeometry, NULL); num_args++;
651 XtSetArg(args[num_args], XtNallowShellResize, TRUE); num_args++;
652 XtSetArg(args[num_args], XtNtransientFor, GetShell(parent)); num_args++;
653 popup = XtCreatePopupShell(name, transientShellWidgetClass,
654 parent, args, num_args);
655
656 form = XtCreateManagedWidget(FORM_NAME, formWidgetClass, popup,
657 NULL, ZERO);
658
659 (*func) (form, ptr, parent);
660 return(popup);
661 }
662
663 /* Function Name: GetShell
664 * Description: Walks up the widget hierarchy to find the
665 * nearest shell widget.
666 * Arguments: w - the widget whose parent shell should be returned.
667 * Returns: The shell widget among the ancestors of w that is the
668 * fewest levels up in the widget hierarchy.
669 */
670
671 static Widget
672 GetShell(w)
673 Widget w;
674 {
675 while ((w != NULL) && !XtIsShell(w))
676 w = XtParent(w);
677
678 return (w);
679 }
680
681 /* Add proper prototype to keep IRIX 6 compiler happy. PH */
682
683 static Boolean InParams(String, String *, Cardinal);
684
685 static Boolean InParams(str, p, n)
686 String str;
687 String *p;
688 Cardinal n;
689 {
690 int i;
691 for (i=0; i < n; p++, i++)
692 if (! XmuCompareISOLatin1(*p, str)) return True;
693 return False;
694 }
695
696 static char *WM_DELETE_WINDOW = "WM_DELETE_WINDOW";
697
698 static void WMProtocols(w, event, params, num_params)
699 Widget w; /* popup shell */
700 XEvent *event;
701 String *params;
702 Cardinal *num_params;
703 {
704 Atom wm_delete_window;
705 Atom wm_protocols;
706
707 wm_delete_window = XInternAtom(XtDisplay(w), WM_DELETE_WINDOW, True);
708 wm_protocols = XInternAtom(XtDisplay(w), "WM_PROTOCOLS", True);
709
710 /* Respond to a recognized WM protocol request iff
711 * event type is ClientMessage and no parameters are passed, or
712 * event type is ClientMessage and event data is matched to parameters, or
713 * event type isn't ClientMessage and parameters make a request.
714 */
715 #define DO_DELETE_WINDOW InParams(WM_DELETE_WINDOW, params, *num_params)
716
717 if ((event->type == ClientMessage &&
718 event->xclient.message_type == wm_protocols &&
719 event->xclient.data.l[0] == wm_delete_window &&
720 (*num_params == 0 || DO_DELETE_WINDOW))
721 ||
722 (event->type != ClientMessage && DO_DELETE_WINDOW)) {
723
724 #undef DO_DELETE_WINDOW
725
726 Widget cancel;
727 char descendant[DISMISS_NAME_LEN + 2];
728 sprintf(descendant, "*%s", DISMISS_NAME);
729 cancel = XtNameToWidget(w, descendant);
730 if (cancel) XtCallCallbacks(cancel, XtNcallback, (XtPointer)NULL);
731 }
732 }
733
734 static void SetWMProtocolTranslations(w)
735 Widget w; /* realized popup shell */
736 {
737 int i;
738 XtAppContext app_context;
739 Atom wm_delete_window;
740 static XtTranslations compiled_table; /* initially 0 */
741 static XtAppContext *app_context_list; /* initially 0 */
742 static Cardinal list_size; /* initially 0 */
743
744 app_context = XtWidgetToApplicationContext(w);
745
746 /* parse translation table once */
747 if (! compiled_table) compiled_table = XtParseTranslationTable
748 ("<Message>WM_PROTOCOLS: XawWMProtocols()\n");
749
750 /* add actions once per application context */
751 for (i=0; i < list_size && app_context_list[i] != app_context; i++) ;
752 if (i == list_size) {
753 XtActionsRec actions[1];
754 actions[0].string = "XawWMProtocols";
755 actions[0].proc = WMProtocols;
756 list_size++;
757 app_context_list = (XtAppContext *) XtRealloc
758 ((char *)app_context_list, list_size * sizeof(XtAppContext));
759 XtAppAddActions(app_context, actions, 1);
760 app_context_list[i] = app_context;
761 }
762
763 /* establish communication between the window manager and each shell */
764 XtAugmentTranslations(w, compiled_table);
765 wm_delete_window = XInternAtom(XtDisplay(w), WM_DELETE_WINDOW, False);
766 (void) XSetWMProtocols(XtDisplay(w), XtWindow(w), &wm_delete_window, 1);
767 }