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