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 $ */
4 /***********************************************************
5 Copyright 1989 by the Massachusetts Institute of Technology,
6 Cambridge, Massachusetts.
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.
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
26 ******************************************************************/
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 ****************************************************************************/
42 /************************************************************
44 * This file is broken up into three sections one dealing with
45 * each of the three popups created here:
47 * FileInsert, Search, and Replace.
49 * There is also a section at the end for utility functions
50 * used by all more than one of these dialogs.
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.
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);
61 *************************************************************/
63 #include <X11/IntrinsicP.h>
64 #include <X11/StringDefs.h>
65 #include <X11/Shell.h>
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>
75 #include <X11/Xos.h> /* for O_RDONLY */
78 /* extern int errno, sys_nerr; */
79 /* extern char* sys_errlist[]; */
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")
89 /* Argument types added by PH August 1999 */
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,
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);
105 static void AddSearchChildren(Widget, char *, Widget);
107 static char radio_trans_string[] =
108 "<Btn1Down>,<Btn1Up>: set() notify()";
110 static char search_text_trans[] =
111 "~Shift<Key>Return: DoSearchAction(Popdown) \n\
112 Ctrl<Key>c: PopdownSearchAction() \n\
117 /************************************************************
119 * This section of the file contains all the functions that
120 * the search dialog box uses.
122 ************************************************************/
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
128 * Arguments: (Standard Action Routine args)
133 * If the search was sucessful and the argument popdown is passed to
134 * this action routine then the widget will automatically popdown the
140 _XawTextDoSearchAction(w, event, params, num_params)
144 Cardinal * num_params;
146 TextWidget tw = (TextWidget) XtParent(XtParent(XtParent(w)));
147 Boolean popdown = FALSE;
149 if ( (*num_params == 1) &&
150 ((params[0][0] == 'p') || (params[0][0] == 'P')) )
153 if (DoSearch(tw->text.search) && popdown)
154 PopdownSearch(w, (XtPointer) tw->text.search, NULL);
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)
166 _XawTextPopdownSearchAction(w, event, params, num_params)
170 Cardinal * num_params;
172 TextWidget tw = (TextWidget) XtParent(XtParent(XtParent(w)));
174 PopdownSearch(w, (XtPointer) tw->text.search, NULL);
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 ***.
187 PopdownSearch(w, closure, call_data)
192 struct SearchAndReplace * search = (struct SearchAndReplace *) closure;
194 SetSearchLabels(search, "Search", "", FALSE);
195 XtPopdown( search->search_popup );
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 ***.
208 SearchButton(w, closure, call_data)
213 (void) DoSearch( (struct SearchAndReplace *) closure );
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.
226 * The parameter list contains one or two entries that may be the following.
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
232 * Second Entry: This entry is optional and contains the value of the default
233 * string to search for.
236 #define SEARCH_HEADER ("Text Widget - Search():")
239 _XawTextSearch(w, event, params, num_params)
243 Cardinal * num_params;
245 TextWidget ctx = (TextWidget)w;
246 XawTextScanDirection dir;
247 char * ptr, buf[BUFSIZ];
248 XawTextEditType edit_mode;
252 if (ctx->text.source->Search == NULL) {
253 XBell(XtDisplay(w), 0);
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);
264 else if (*num_params == 1)
269 switch(params[0][0]) {
270 case 'b': /* Left. */
274 case 'f': /* Right. */
279 sprintf(buf, "%s %s\n%s", SEARCH_HEADER, "The first parameter must be",
280 "Either 'backward' or 'forward'");
281 XtAppWarning(XtWidgetToApplicationContext(w), buf);
285 if (ctx->text.search== NULL) {
286 ctx->text.search = XtNew(struct SearchAndReplace);
287 ctx->text.search->search_popup = CreateDialog(w, ptr, "search",
289 XtRealizeWidget(ctx->text.search->search_popup);
290 SetWMProtocolTranslations(ctx->text.search->search_popup);
292 else if (*num_params > 1) {
293 XtVaSetValues(ctx->text.search->search_text, XtNstring, ptr, NULL);
296 XtSetArg(args[0], XtNeditType,&edit_mode);
297 XtGetValues(ctx->text.source, args, ONE);
299 InitializeSearchWidget(ctx->text.search, dir, (edit_mode == XawtextEdit));
301 CenterWidgetOnPoint(ctx->text.search->search_popup, event);
302 XtPopup(ctx->text.search->search_popup, XtGrabNone);
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
316 InitializeSearchWidget(struct SearchAndReplace *search,
317 XawTextScanDirection dir, Boolean replace_active)
319 replace_active = replace_active; /* PH - shuts compilers up */
323 SetResource(search->left_toggle, XtNstate, (XtArgVal) TRUE);
326 SetResource(search->right_toggle, XtNstate, (XtArgVal) TRUE);
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.
342 AddSearchChildren(form, ptr, tw)
348 Widget cancel, search_button, s_label, s_text;
349 XtTranslations trans;
350 struct SearchAndReplace * search = ((TextWidget) tw)->text.search;
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);
361 * We need to add R_OFFSET to the radio_data, because the value zero (0)
362 * has special meaning.
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);
372 search->left_toggle = XtCreateManagedWidget("backwards", toggleWidgetClass,
373 form, args, num_args);
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);
384 search->right_toggle = XtCreateManagedWidget("forwards", toggleWidgetClass,
385 form, args, num_args);
388 XtTranslations radio_translations;
390 radio_translations = XtParseTranslationTable(radio_trans_string);
391 XtOverrideTranslations(search->left_toggle, radio_translations);
392 XtOverrideTranslations(search->right_toggle, radio_translations);
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);
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,
415 search->search_text = s_text;
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,
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,
434 XtAddCallback(search_button, XtNcallback, SearchButton, (XtPointer) search);
435 XtAddCallback(cancel, XtNcallback, PopdownSearch, (XtPointer) search);
438 * Initialize the text entry fields.
441 SetSearchLabels(search, "Search", "", FALSE);
442 XtSetKeyboardFocus(form, search->search_text);
445 * Bind Extra translations.
448 trans = XtParseTranslationTable(search_text_trans);
449 XtOverrideTranslations(search->search_text, trans);
452 /* Function Name: DoSearch
453 * Description: Performs a search.
454 * Arguments: search - the serach structure.
455 * Returns: TRUE if sucessful.
461 struct SearchAndReplace * search;
464 Widget tw = XtParent(search->search_popup);
466 XawTextScanDirection dir;
469 text.ptr = GetString(search->search_text);
470 text.length = strlen(text.ptr);
472 text.format = FMT8BIT;
474 dir = (XawTextScanDirection)(int) ((caddr_t)XawToggleGetCurrent(search->left_toggle) -
477 pos = XawTextSearch( tw, dir, &text);
479 if (pos == XawTextSearchError)
480 sprintf( msg, "Could not find string '%s'.", text.ptr);
482 if (dir == XawsdRight)
483 XawTextSetInsertionPoint( tw, pos + text.length);
485 XawTextSetInsertionPoint( tw, pos);
487 XawTextSetSelection( tw, pos, pos + text.length);
488 search->selection_changed = FALSE; /* selection is good. */
492 XawTextUnsetSelection(tw);
493 SetSearchLabels(search, msg, "", TRUE);
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.
508 SetSearchLabels(struct SearchAndReplace *search, String msg1, String msg2,
511 msg2 = msg2; /* PH - shuts compilers up */
512 (void) SetResource( search->label1, XtNlabel, (XtArgVal) msg1);
513 /* (void) SetResource( search->label2, XtNlabel, (XtArgVal) msg2); */
515 XBell(XtDisplay(search->search_popup), 0);
518 /************************************************************
520 * This section of the file contains utility routines used by
521 * other functions in this file.
523 ************************************************************/
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.
535 SetResource(w, res_name, value)
542 XtSetArg(args[0], res_name, value);
543 XtSetValues( w, args, ONE );
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.
559 XtSetArg( args[0], XtNstring, &string );
560 XtGetValues( text, args, ONE );
564 /* Function Name: CenterWidgetOnPoint.
565 * Description: Centers a shell widget on a point relative to
567 * Arguments: w - the shell widget.
568 * event - event containing the location of the point
571 * NOTE: The widget is not allowed to go off the screen.
575 CenterWidgetOnPoint(w, event)
581 Dimension width, height, b_width;
582 Position x=0, y=0, max_x, max_y;
585 switch (event->type) {
588 x = event->xbutton.x_root;
589 y = event->xbutton.y_root;
593 x = event->xkey.x_root;
594 y = event->xkey.y_root;
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);
607 width += 2 * b_width;
608 height += 2 * b_width;
610 x -= ( (Position) width/2 );
612 if ( x > (max_x = (Position) (XtScreen(w)->width - width)) ) x = max_x;
614 y -= ( (Position) height/2 );
616 if ( y > (max_y = (Position) (XtScreen(w)->height - height)) ) y = max_y;
619 XtSetArg(args[num_args], XtNx, x); num_args++;
620 XtSetArg(args[num_args], XtNy, y); num_args++;
621 XtSetValues(w, args, num_args);
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.
634 * The function argument is passed the following arguements.
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.
642 CreateDialog(parent, ptr, name, func)
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);
659 form = XtCreateManagedWidget(FORM_NAME, formWidgetClass, popup,
662 (*func) (form, ptr, parent);
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.
678 while ((w != NULL) && !XtIsShell(w))
684 /* Add proper prototype to keep IRIX 6 compiler happy. PH */
686 static Boolean InParams(String, String *, Cardinal);
688 static Boolean InParams(str, p, n)
694 for (i=0; i < n; p++, i++)
695 if (! XmuCompareISOLatin1(*p, str)) return True;
699 static char *WM_DELETE_WINDOW = "WM_DELETE_WINDOW";
701 static void WMProtocols(w, event, params, num_params)
702 Widget w; /* popup shell */
705 Cardinal *num_params;
707 Atom wm_delete_window;
710 wm_delete_window = XInternAtom(XtDisplay(w), WM_DELETE_WINDOW, True);
711 wm_protocols = XInternAtom(XtDisplay(w), "WM_PROTOCOLS", True);
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.
718 #define DO_DELETE_WINDOW InParams(WM_DELETE_WINDOW, params, *num_params)
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))
725 (event->type != ClientMessage && DO_DELETE_WINDOW)) {
727 #undef DO_DELETE_WINDOW
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);
737 static void SetWMProtocolTranslations(w)
738 Widget w; /* realized popup shell */
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 */
747 app_context = XtWidgetToApplicationContext(w);
749 /* parse translation table once */
750 if (! compiled_table) compiled_table = XtParseTranslationTable
751 ("<Message>WM_PROTOCOLS: XawWMProtocols()\n");
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;
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;
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);