Commit | Line | Data |
---|---|---|
059ec3d9 PH |
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 | } |