| 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 | } |