1
/* $Cambridge: exim/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);