1 /***********************************************************
2 Copyright 1989 by the Massachusetts Institute of Technology,
3 Cambridge, Massachusetts.
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.
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
23 ******************************************************************/
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 ****************************************************************************/
39 /************************************************************
41 * This file is broken up into three sections one dealing with
42 * each of the three popups created here:
44 * FileInsert, Search, and Replace.
46 * There is also a section at the end for utility functions
47 * used by all more than one of these dialogs.
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.
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);
58 *************************************************************/
60 #include <X11/IntrinsicP.h>
61 #include <X11/StringDefs.h>
62 #include <X11/Shell.h>
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>
72 #include <X11/Xos.h> /* for O_RDONLY */
75 /* extern int errno, sys_nerr; */
76 /* extern char* sys_errlist[]; */
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")
86 /* Argument types added by PH August 1999 */
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,
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);
102 static void AddSearchChildren(Widget, char *, Widget);
104 static char radio_trans_string[] =
105 "<Btn1Down>,<Btn1Up>: set() notify()";
107 static char search_text_trans[] =
108 "~Shift<Key>Return: DoSearchAction(Popdown) \n\
109 Ctrl<Key>c: PopdownSearchAction() \n\
114 /************************************************************
116 * This section of the file contains all the functions that
117 * the search dialog box uses.
119 ************************************************************/
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
125 * Arguments: (Standard Action Routine args)
130 * If the search was successful and the argument popdown is passed to
131 * this action routine then the widget will automatically popdown the
137 _XawTextDoSearchAction(w, event, params, num_params)
141 Cardinal * num_params;
143 TextWidget tw = (TextWidget) XtParent(XtParent(XtParent(w)));
144 Boolean popdown = FALSE;
146 if ( (*num_params == 1) &&
147 ((params[0][0] == 'p') || (params[0][0] == 'P')) )
150 if (DoSearch(tw->text.search) && popdown)
151 PopdownSearch(w, (XtPointer) tw->text.search, NULL);
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)
163 _XawTextPopdownSearchAction(w, event, params, num_params)
167 Cardinal * num_params;
169 TextWidget tw = (TextWidget) XtParent(XtParent(XtParent(w)));
171 PopdownSearch(w, (XtPointer) tw->text.search, NULL);
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 ***.
184 PopdownSearch(w, closure, call_data)
189 struct SearchAndReplace * search = (struct SearchAndReplace *) closure;
191 SetSearchLabels(search, "Search", "", FALSE);
192 XtPopdown( search->search_popup );
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 ***.
205 SearchButton(w, closure, call_data)
210 (void) DoSearch( (struct SearchAndReplace *) closure );
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.
223 * The parameter list contains one or two entries that may be the following.
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
229 * Second Entry: This entry is optional and contains the value of the default
230 * string to search for.
233 #define SEARCH_HEADER ("Text Widget - Search():")
236 _XawTextSearch(w, event, params, num_params)
240 Cardinal * num_params;
242 TextWidget ctx = (TextWidget)w;
243 XawTextScanDirection dir;
244 char * ptr, buf[BUFSIZ];
245 XawTextEditType edit_mode;
249 if (!ctx->text.source->Search) {
250 XBell(XtDisplay(w), 0);
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);
261 else if (*num_params == 1)
266 switch(params[0][0]) {
267 case 'b': /* Left. */
271 case 'f': /* Right. */
276 sprintf(buf, "%s %s\n%s", SEARCH_HEADER, "The first parameter must be",
277 "Either 'backward' or 'forward'");
278 XtAppWarning(XtWidgetToApplicationContext(w), buf);
282 if (!ctx->text.search) {
283 ctx->text.search = XtNew(struct SearchAndReplace);
284 ctx->text.search->search_popup = CreateDialog(w, ptr, "search",
286 XtRealizeWidget(ctx->text.search->search_popup);
287 SetWMProtocolTranslations(ctx->text.search->search_popup);
289 else if (*num_params > 1)
290 XtVaSetValues(ctx->text.search->search_text, XtNstring, ptr, NULL);
292 XtSetArg(args[0], XtNeditType,&edit_mode);
293 XtGetValues(ctx->text.source, args, ONE);
295 InitializeSearchWidget(ctx->text.search, dir, (edit_mode == XawtextEdit));
297 CenterWidgetOnPoint(ctx->text.search->search_popup, event);
298 XtPopup(ctx->text.search->search_popup, XtGrabNone);
301 /* Function Name: InitializeSearchWidget
302 * Description: This function initializes the search widget and
303 * is called each time the search widget is poped up.
304 * Arguments: search - the search widget structure.
305 * dir - direction to search.
306 * replace_active - state of the sensitivity for the
312 InitializeSearchWidget(struct SearchAndReplace *search,
313 XawTextScanDirection dir, Boolean replace_active)
315 replace_active = replace_active; /* PH - shuts compilers up */
319 SetResource(search->left_toggle, XtNstate, (XtArgVal) TRUE);
322 SetResource(search->right_toggle, XtNstate, (XtArgVal) TRUE);
329 /* Function Name: AddSearchChildren
330 * Description: Adds all children to the Search Dialog Widget.
331 * Arguments: form - the form widget for the search widget.
332 * ptr - a pointer to the initial string for the Text Widget.
333 * tw - the main text widget.
338 AddSearchChildren(form, ptr, tw)
344 Widget cancel, search_button, s_label, s_text;
345 XtTranslations trans;
346 struct SearchAndReplace * search = ((TextWidget) tw)->text.search;
349 XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++;
350 XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++;
351 XtSetArg(args[num_args], XtNresizable, TRUE ); num_args++;
352 XtSetArg(args[num_args], XtNborderWidth, 0 ); num_args++;
353 search->label1 = XtCreateManagedWidget("label1", labelWidgetClass,
354 form, args, num_args);
357 * We need to add R_OFFSET to the radio_data, because the value zero (0)
358 * has special meaning.
362 XtSetArg(args[num_args], XtNlabel, "Backward"); num_args++;
363 XtSetArg(args[num_args], XtNfromVert, search->label1); num_args++;
364 XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++;
365 XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++;
366 XtSetArg(args[num_args], XtNradioData, (caddr_t) XawsdLeft + R_OFFSET);
368 search->left_toggle = XtCreateManagedWidget("backwards", toggleWidgetClass,
369 form, args, num_args);
372 XtSetArg(args[num_args], XtNlabel, "Forward"); num_args++;
373 XtSetArg(args[num_args], XtNfromVert, search->label1); num_args++;
374 XtSetArg(args[num_args], XtNfromHoriz, search->left_toggle); num_args++;
375 XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++;
376 XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++;
377 XtSetArg(args[num_args], XtNradioGroup, search->left_toggle); num_args++;
378 XtSetArg(args[num_args], XtNradioData, (caddr_t) XawsdRight + R_OFFSET);
380 search->right_toggle = XtCreateManagedWidget("forwards", toggleWidgetClass,
381 form, args, num_args);
384 XtTranslations radio_translations;
386 radio_translations = XtParseTranslationTable(radio_trans_string);
387 XtOverrideTranslations(search->left_toggle, radio_translations);
388 XtOverrideTranslations(search->right_toggle, radio_translations);
392 XtSetArg(args[num_args], XtNfromVert, search->left_toggle); num_args++;
393 XtSetArg(args[num_args], XtNlabel, "Search for: ");num_args++;
394 XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++;
395 XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++;
396 XtSetArg(args[num_args], XtNborderWidth, 0 ); num_args++;
397 s_label = XtCreateManagedWidget("searchLabel", labelWidgetClass,
398 form, args, num_args);
401 XtSetArg(args[num_args], XtNfromVert, search->left_toggle); num_args++;
402 XtSetArg(args[num_args], XtNfromHoriz, s_label); num_args++;
403 XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++;
404 XtSetArg(args[num_args], XtNright, XtChainRight); num_args++;
405 XtSetArg(args[num_args], XtNeditType, XawtextEdit); num_args++;
406 XtSetArg(args[num_args], XtNresizable, TRUE); num_args++;
407 XtSetArg(args[num_args], XtNresize, XawtextResizeWidth); num_args++;
408 XtSetArg(args[num_args], XtNstring, ptr); num_args++;
409 s_text = XtCreateManagedWidget("searchText", asciiTextWidgetClass, form,
411 search->search_text = s_text;
414 XtSetArg(args[num_args], XtNlabel, "Search"); num_args++;
415 XtSetArg(args[num_args], XtNfromVert, s_text); num_args++;
416 XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++;
417 XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++;
418 search_button = XtCreateManagedWidget("search", commandWidgetClass, form,
422 XtSetArg(args[num_args], XtNlabel, "Cancel"); num_args++;
423 XtSetArg(args[num_args], XtNfromVert, s_text); num_args++;
424 XtSetArg(args[num_args], XtNfromHoriz, search_button); num_args++;
425 XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++;
426 XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++;
427 cancel = XtCreateManagedWidget(DISMISS_NAME, commandWidgetClass, form,
430 XtAddCallback(search_button, XtNcallback, SearchButton, (XtPointer) search);
431 XtAddCallback(cancel, XtNcallback, PopdownSearch, (XtPointer) search);
434 * Initialize the text entry fields.
437 SetSearchLabels(search, "Search", "", FALSE);
438 XtSetKeyboardFocus(form, search->search_text);
441 * Bind Extra translations.
444 trans = XtParseTranslationTable(search_text_trans);
445 XtOverrideTranslations(search->search_text, trans);
448 /* Function Name: DoSearch
449 * Description: Performs a search.
450 * Arguments: search - the search structure.
451 * Returns: TRUE if successful.
457 struct SearchAndReplace * search;
460 Widget tw = XtParent(search->search_popup);
462 XawTextScanDirection dir;
465 text.ptr = GetString(search->search_text);
466 text.length = strlen(text.ptr);
468 text.format = FMT8BIT;
470 dir = (XawTextScanDirection) ((long)XawToggleGetCurrent(search->left_toggle) -
473 pos = XawTextSearch( tw, dir, &text);
475 if (pos == XawTextSearchError)
476 sprintf( msg, "Could not find string '%s'.", text.ptr);
478 if (dir == XawsdRight)
479 XawTextSetInsertionPoint( tw, pos + text.length);
481 XawTextSetInsertionPoint( tw, pos);
483 XawTextSetSelection( tw, pos, pos + text.length);
484 search->selection_changed = FALSE; /* selection is good. */
488 XawTextUnsetSelection(tw);
489 SetSearchLabels(search, msg, "", TRUE);
494 /* Function Name: SetSearchLabels
495 * Description: Sets both the search labels, and also rings the bell
496 * HACKED: Only one label needed now
497 * Arguments: search - the search structure.
498 * msg1, msg2 - message to put in each search label.
499 * bell - if TRUE then ring bell.
504 SetSearchLabels(struct SearchAndReplace *search, String msg1, String msg2,
507 msg2 = msg2; /* PH - shuts compilers up */
508 (void) SetResource( search->label1, XtNlabel, (XtArgVal) msg1);
509 /* (void) SetResource( search->label2, XtNlabel, (XtArgVal) msg2); */
511 XBell(XtDisplay(search->search_popup), 0);
514 /************************************************************
516 * This section of the file contains utility routines used by
517 * other functions in this file.
519 ************************************************************/
522 /* Function Name: SetResource
523 * Description: Sets a resource in a widget
524 * Arguments: w - the widget.
525 * res_name - name of the resource.
526 * value - the value of the resource.
531 SetResource(w, res_name, value)
538 XtSetArg(args[0], res_name, value);
539 XtSetValues( w, args, ONE );
542 /* Function Name: GetString
543 * Description: Gets the value for the string in the popup.
544 * Arguments: text - the text widget whose string we will get.
545 * Returns: the string.
555 XtSetArg( args[0], XtNstring, &string );
556 XtGetValues( text, args, ONE );
560 /* Function Name: CenterWidgetOnPoint.
561 * Description: Centers a shell widget on a point relative to
563 * Arguments: w - the shell widget.
564 * event - event containing the location of the point
567 * NOTE: The widget is not allowed to go off the screen.
571 CenterWidgetOnPoint(w, event)
577 Dimension width, height, b_width;
578 Position x=0, y=0, max_x, max_y;
581 switch (event->type) {
584 x = event->xbutton.x_root;
585 y = event->xbutton.y_root;
589 x = event->xkey.x_root;
590 y = event->xkey.y_root;
598 XtSetArg(args[num_args], XtNwidth, &width); num_args++;
599 XtSetArg(args[num_args], XtNheight, &height); num_args++;
600 XtSetArg(args[num_args], XtNborderWidth, &b_width); num_args++;
601 XtGetValues(w, args, num_args);
603 width += 2 * b_width;
604 height += 2 * b_width;
606 x -= ( (Position) width/2 );
608 if ( x > (max_x = (Position) (XtScreen(w)->width - width)) ) x = max_x;
610 y -= ( (Position) height/2 );
612 if ( y > (max_y = (Position) (XtScreen(w)->height - height)) ) y = max_y;
615 XtSetArg(args[num_args], XtNx, x); num_args++;
616 XtSetArg(args[num_args], XtNy, y); num_args++;
617 XtSetValues(w, args, num_args);
620 /* Function Name: CreateDialog
621 * Description: Actually creates a dialog.
622 * Arguments: parent - the parent of the dialog - the main text widget.
623 * ptr - initial_string for the dialog.
624 * name - name of the dialog.
625 * func - function to create the children of the dialog.
626 * Returns: the popup shell of the dialog.
630 * The function argument is passed the following arguments.
632 * form - the from widget that is the dialog.
633 * ptr - the initial string for the dialog's text widget.
634 * parent - the parent of the dialog - the main text widget.
638 CreateDialog(parent, ptr, name, func)
648 XtSetArg(args[num_args], XtNiconName, name); num_args++;
649 XtSetArg(args[num_args], XtNgeometry, NULL); num_args++;
650 XtSetArg(args[num_args], XtNallowShellResize, TRUE); num_args++;
651 XtSetArg(args[num_args], XtNtransientFor, GetShell(parent)); num_args++;
652 popup = XtCreatePopupShell(name, transientShellWidgetClass,
653 parent, args, num_args);
655 form = XtCreateManagedWidget(FORM_NAME, formWidgetClass, popup,
658 (*func) (form, ptr, parent);
662 /* Function Name: GetShell
663 * Description: Walks up the widget hierarchy to find the
664 * nearest shell widget.
665 * Arguments: w - the widget whose parent shell should be returned.
666 * Returns: The shell widget among the ancestors of w that is the
667 * fewest levels up in the widget hierarchy.
674 while ((w != NULL) && !XtIsShell(w))
680 /* Add proper prototype to keep IRIX 6 compiler happy. PH */
682 static Boolean InParams(String, String *, Cardinal);
684 static Boolean InParams(str, p, n)
690 for (i=0; i < n; p++, i++)
691 if (! XmuCompareISOLatin1(*p, str)) return True;
695 static char *WM_DELETE_WINDOW = "WM_DELETE_WINDOW";
697 static void WMProtocols(w, event, params, num_params)
698 Widget w; /* popup shell */
701 Cardinal *num_params;
703 Atom wm_delete_window;
706 wm_delete_window = XInternAtom(XtDisplay(w), WM_DELETE_WINDOW, True);
707 wm_protocols = XInternAtom(XtDisplay(w), "WM_PROTOCOLS", True);
709 /* Respond to a recognized WM protocol request iff
710 * event type is ClientMessage and no parameters are passed, or
711 * event type is ClientMessage and event data is matched to parameters, or
712 * event type isn't ClientMessage and parameters make a request.
714 #define DO_DELETE_WINDOW InParams(WM_DELETE_WINDOW, params, *num_params)
716 if ((event->type == ClientMessage &&
717 event->xclient.message_type == wm_protocols &&
718 event->xclient.data.l[0] == wm_delete_window &&
719 (*num_params == 0 || DO_DELETE_WINDOW))
721 (event->type != ClientMessage && DO_DELETE_WINDOW)) {
723 #undef DO_DELETE_WINDOW
726 char descendant[DISMISS_NAME_LEN + 2];
727 sprintf(descendant, "*%s", DISMISS_NAME);
728 cancel = XtNameToWidget(w, descendant);
729 if (cancel) XtCallCallbacks(cancel, XtNcallback, (XtPointer)NULL);
733 static void SetWMProtocolTranslations(w)
734 Widget w; /* realized popup shell */
737 XtAppContext app_context;
738 Atom wm_delete_window;
739 static XtTranslations compiled_table; /* initially 0 */
740 static XtAppContext *app_context_list; /* initially 0 */
741 static Cardinal list_size; /* initially 0 */
743 app_context = XtWidgetToApplicationContext(w);
745 /* parse translation table once */
746 if (! compiled_table) compiled_table = XtParseTranslationTable
747 ("<Message>WM_PROTOCOLS: XawWMProtocols()\n");
749 /* add actions once per application context */
750 for (i=0; i < list_size && app_context_list[i] != app_context; i++) ;
751 if (i == list_size) {
752 XtActionsRec actions[1];
753 actions[0].string = "XawWMProtocols";
754 actions[0].proc = WMProtocols;
756 app_context_list = (XtAppContext *) XtRealloc
757 ((char *)app_context_list, list_size * sizeof(XtAppContext));
758 XtAppAddActions(app_context, actions, 1);
759 app_context_list[i] = app_context;
762 /* establish communication between the window manager and each shell */
763 XtAugmentTranslations(w, compiled_table);
764 wm_delete_window = XInternAtom(XtDisplay(w), WM_DELETE_WINDOW, False);
765 (void) XSetWMProtocols(XtDisplay(w), XtWindow(w), &wm_delete_window, 1);