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