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