TextPop.c revision 5b16253f
1/* 2 3Copyright 1989, 1994, 1998 The Open Group 4 5Permission to use, copy, modify, distribute, and sell this software and its 6documentation for any purpose is hereby granted without fee, provided that 7the above copyright notice appear in all copies and that both that 8copyright notice and this permission notice appear in supporting 9documentation. 10 11The above copyright notice and this permission notice shall be included in 12all copies or substantial portions of the Software. 13 14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 21Except as contained in this notice, the name of The Open Group shall not be 22used in advertising or otherwise to promote the sale, use or other dealings 23in this Software without prior written authorization from The Open Group. 24 25*/ 26 27/* 28 * This file is broken up into three sections one dealing with 29 * each of the three popups created here: 30 * 31 * FileInsert, Search, and Replace. 32 * 33 * There is also a section at the end for utility functions 34 * used by all more than one of these dialogs. 35 * 36 * The following functions are the only non-static ones defined 37 * in this module. They are located at the beginning of the 38 * section that contains this dialog box that uses them. 39 * 40 * void _XawTextInsertFileAction(w, event, params, num_params); 41 * void _XawTextDoSearchAction(w, event, params, num_params); 42 * void _XawTextDoReplaceAction(w, event, params, num_params); 43 * void _XawTextInsertFile(w, event, params, num_params); 44 */ 45 46#ifdef HAVE_CONFIG_H 47#include <config.h> 48#endif 49#include <stdio.h> 50#include <errno.h> 51#include <X11/IntrinsicP.h> 52#include <X11/StringDefs.h> 53#include <X11/Shell.h> 54#include <X11/Xos.h> 55#include <X11/Xmu/CharSet.h> 56#include <X11/Xaw/TextP.h> 57#include <X11/Xaw/AsciiText.h> 58#include <X11/Xaw/Cardinals.h> 59#include <X11/Xaw/Command.h> 60#include <X11/Xaw/Form.h> 61#include <X11/Xaw/Toggle.h> 62#include "XawI18n.h" 63 64static _Xconst char* INSERT_FILE = "Enter Filename:"; 65static _Xconst char* SEARCH_LABEL_1 = "Use <Tab> to change fields."; 66static _Xconst char* SEARCH_LABEL_2 = "Use ^q<Tab> for <Tab>."; 67static _Xconst char* DISMISS_NAME = "cancel"; 68#define DISMISS_NAME_LEN 6 69static _Xconst char* FORM_NAME = "form"; 70static _Xconst char* LABEL_NAME = "label"; 71static _Xconst char* TEXT_NAME = "text"; 72 73#define R_OFFSET 1 74 75typedef void (*AddFunc)(Widget, String, Widget); 76 77/* 78 * Prototypes 79 */ 80static void _SetField(Widget, Widget); 81static void AddSearchChildren(Widget, String, Widget); 82static void AddInsertFileChildren(Widget, String, Widget); 83static void CenterWidgetOnPoint(Widget, XEvent*); 84static Widget CreateDialog(Widget, String, String, AddFunc); 85static void DoInsert(Widget, XtPointer, XtPointer); 86static void DoReplaceAll(Widget, XtPointer, XtPointer); 87static void DoReplaceOne(Widget, XtPointer, XtPointer); 88static Bool DoSearch(struct SearchAndReplace*); 89static Widget GetShell(Widget); 90static String GetString(Widget); 91static _XtString GetStringRaw(Widget); 92static void InitializeSearchWidget(struct SearchAndReplace*, 93 XawTextScanDirection, Bool); 94static Bool InParams(String, String*, unsigned int); 95static Bool InsertFileNamed(Widget, String); 96static void PopdownFileInsert(Widget, XtPointer, XtPointer); 97static void PopdownSearch(Widget, XtPointer, XtPointer); 98static Bool Replace(struct SearchAndReplace*, Bool, Bool); 99static void SearchButton(Widget, XtPointer, XtPointer); 100static void SetResource(Widget, String, XtArgVal); 101static Bool SetResourceByName(Widget, String, String, XtArgVal); 102static void SetSearchLabels(struct SearchAndReplace*, String, String, Bool); 103static void SetWMProtocolTranslations(Widget); 104 105/* 106 * Actions 107 */ 108static void WMProtocols(Widget, XEvent*, String*, Cardinal*); 109 110/* 111 * External Actions 112 */ 113void _XawTextDoReplaceAction(Widget, XEvent*, String*, Cardinal*); 114void _XawTextDoSearchAction(Widget, XEvent*, String*, Cardinal*); 115void _XawTextInsertFile(Widget, XEvent*, String*, Cardinal*); 116void _XawTextInsertFileAction(Widget, XEvent*, String*, Cardinal*); 117void _XawTextPopdownSearchAction(Widget, XEvent*, String*, Cardinal*); 118void _XawTextSearch(Widget, XEvent*, String*, Cardinal*); 119void _XawTextSetField(Widget, XEvent*, String*, Cardinal*); 120 121/* 122 * From Text.c 123 */ 124char *_XawTextGetText(TextWidget, XawTextPosition, XawTextPosition); 125void _XawTextShowPosition(TextWidget); 126 127/* 128 * Initialization 129 */ 130static char radio_trans_string[] = 131"<Btn1Down>,<Btn1Up>:" "set() notify()\n" 132; 133 134static char search_text_trans[] = 135"~s<Key>Return:" "DoSearchAction(Popdown)\n" 136"s<Key>Return:" "DoSearchAction() SetField(Replace)\n" 137"c<Key>c:" "PopdownSearchAction()\n" 138"<Btn1Down>:" "select-start() SetField(Search)\n" 139"<Key>Tab:" "DoSearchAction() SetField(Replace)\n" 140; 141 142static char rep_text_trans[] = 143"~s<Key>Return:" "DoReplaceAction(Popdown)\n" 144"s<Key>Return:" "SetField(Search)\n" 145"c<Key>c:" "PopdownSearchAction()\n" 146"<Btn1Down>:" "select-start() DoSearchAction() SetField(Replace)\n" 147"<Key>Tab:" "SetField(Search)\n" 148; 149 150/* 151 * Implementation 152 */ 153/* 154 * This section of the file contains all the functions that 155 * the file insert dialog box uses 156 */ 157 158/* 159 * Function: 160 * _XawTextInsertFileAction 161 * 162 * Description: 163 * Action routine that can be bound to dialog box's Text Widget 164 * that will insert a file into the main Text Widget. 165 */ 166/*ARGSUSED*/ 167void 168_XawTextInsertFileAction(Widget w, XEvent *event _X_UNUSED, 169 String *params _X_UNUSED, Cardinal *num_params _X_UNUSED) 170{ 171 DoInsert(w, (XtPointer)XtParent(XtParent(XtParent(w))), NULL); 172} 173 174/* 175 * Function: 176 * _XawTextInsertFile 177 * 178 * Parameters: 179 * w - text widget 180 * event - X Event (used to get x and y location) 181 * params - parameter list 182 * num_params - "" 183 * 184 * Description: 185 * Action routine that can be bound to the text widget 186 * it will popup the insert file dialog box. 187 * 188 * Note: 189 * The parameter list may contain one entry 190 * 191 * Entry: 192 * This entry is optional and contains the value of the default 193 * file to insert 194 */ 195void 196_XawTextInsertFile(Widget w, XEvent *event, 197 String *params, Cardinal *num_params) 198{ 199 TextWidget ctx = (TextWidget)w; 200 String ptr; 201 XawTextEditType edit_mode; 202 Arg args[1]; 203 204 XtSetArg(args[0], XtNeditType, &edit_mode); 205 XtGetValues(ctx->text.source, args, 1); 206 207 if (edit_mode != XawtextEdit) { 208 XBell(XtDisplay(w), 0); 209 return; 210 } 211 212 if (*num_params == 0) 213 ptr = ""; 214 else 215 ptr = params[0]; 216 217 if (!ctx->text.file_insert) { 218 ctx->text.file_insert = CreateDialog(w, ptr, "insertFile", 219 AddInsertFileChildren); 220 XtRealizeWidget(ctx->text.file_insert); 221 SetWMProtocolTranslations(ctx->text.file_insert); 222 } 223 224 CenterWidgetOnPoint(ctx->text.file_insert, event); 225 XtPopup(ctx->text.file_insert, XtGrabNone); 226} 227 228/* 229 * Function: 230 * PopdownFileInsert 231 * 232 * Parameters: 233 * w - widget that caused this action 234 * closure - pointer to the main text widget that popped up this dialog 235 * call_data - (not used) 236 * 237 * Description: 238 * Pops down the file insert button 239 */ 240/*ARGSUSED*/ 241static void 242PopdownFileInsert(Widget w _X_UNUSED, XtPointer closure, XtPointer call_data _X_UNUSED) 243{ 244 TextWidget ctx = (TextWidget)closure; 245 246 XtPopdown(ctx->text.file_insert); 247 (void)SetResourceByName(ctx->text.file_insert, LABEL_NAME, 248 XtNlabel, (XtArgVal)INSERT_FILE); 249} 250 251/* 252 * Function: 253 * DoInsert 254 * 255 * Parameters: 256 * w - widget that activated this callback 257 * closure - pointer to the text widget to insert the file into 258 * 259 * Description: 260 * Actually insert the file named in the text widget of the file dialog 261 */ 262/*ARGSUSED*/ 263static void 264DoInsert(Widget w, XtPointer closure, XtPointer call_data) 265{ 266 TextWidget ctx = (TextWidget)closure; 267 char buf[BUFSIZ], msg[BUFSIZ]; 268 Widget temp_widget; 269 270 snprintf(buf, sizeof(buf), "%s.%s", FORM_NAME, TEXT_NAME); 271 if ((temp_widget = XtNameToWidget(ctx->text.file_insert, buf)) == NULL) { 272 (void)strcpy(msg, 273 "Error: Could not get text widget from file insert popup"); 274 } 275 else if (InsertFileNamed((Widget)ctx, GetString(temp_widget))) { 276 PopdownFileInsert(w, closure, call_data); 277 return; 278 } 279 else 280 snprintf(msg, sizeof(msg), "Error: %s", strerror(errno)); 281 282 (void)SetResourceByName(ctx->text.file_insert, 283 LABEL_NAME, XtNlabel, (XtArgVal)msg); 284 XBell(XtDisplay(w), 0); 285} 286 287/* 288 * Function: 289 * InsertFileNamed 290 * 291 * Parameters: 292 * tw - text widget to insert this file into 293 * str - name of the file to insert 294 * 295 * Description: 296 * Inserts a file into the text widget. 297 * 298 * Returns: 299 * True if the insert was successful, False otherwise. 300 */ 301static Bool 302InsertFileNamed(Widget tw, String str) 303{ 304 FILE *file; 305 XawTextBlock text; 306 XawTextPosition pos; 307 308 if (str == NULL || strlen(str) == 0 || (file = fopen(str, "r")) == NULL) 309 return (False); 310 311 pos = XawTextGetInsertionPoint(tw); 312 313 fseek(file, 0L, SEEK_END); 314 315 text.firstPos = 0; 316 text.length = (int)ftell(file); 317 text.ptr = XtMalloc((Cardinal)(text.length + 1)); 318 text.format = XawFmt8Bit; 319 320 fseek(file, 0L, SEEK_SET); 321 if (fread(text.ptr, 1, (size_t)text.length, file) != (size_t)text.length) 322 XtErrorMsg("readError", "insertFileNamed", "XawError", 323 "fread returned error", NULL, NULL); 324 325 if (XawTextReplace(tw, pos, pos, &text) != XawEditDone) { 326 XtFree(text.ptr); 327 fclose(file); 328 return (False); 329 } 330 pos += text.length; 331 XtFree(text.ptr); 332 fclose(file); 333 XawTextSetInsertionPoint(tw, pos); 334 _XawTextShowPosition((TextWidget)tw); 335 336 return (True); 337} 338 339/* 340 * Function: 341 * AddInsertFileChildren 342 * 343 * Parameters: 344 * form - form widget for the insert dialog widget 345 * ptr - pointer to the initial string for the Text Widget 346 * tw - main text widget 347 * 348 * Description: 349 * Adds all children to the InsertFile dialog widget. 350 */ 351static void 352AddInsertFileChildren(Widget form, String ptr, Widget tw) 353{ 354 Arg args[10]; 355 Cardinal num_args; 356 Widget label, text, cancel, insert; 357 XtTranslations trans; 358 359 num_args = 0; 360 XtSetArg(args[num_args], XtNlabel, INSERT_FILE); num_args++; 361 XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; 362 XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++; 363 XtSetArg(args[num_args], XtNresizable, True); num_args++; 364 XtSetArg(args[num_args], XtNborderWidth, 0); num_args++; 365 label = XtCreateManagedWidget(LABEL_NAME, labelWidgetClass, form, 366 args, num_args); 367 368 num_args = 0; 369 XtSetArg(args[num_args], XtNfromVert, label); num_args++; 370 XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; 371 XtSetArg(args[num_args], XtNright, XtChainRight); num_args++; 372 XtSetArg(args[num_args], XtNeditType, XawtextEdit); num_args++; 373 XtSetArg(args[num_args], XtNresizable, True); num_args++; 374 XtSetArg(args[num_args], XtNstring, ptr); num_args++; 375 text = XtCreateManagedWidget(TEXT_NAME, asciiTextWidgetClass, form, 376 args, num_args); 377 378 num_args = 0; 379 XtSetArg(args[num_args], XtNlabel, "Insert File"); num_args++; 380 XtSetArg(args[num_args], XtNfromVert, text); num_args++; 381 XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; 382 XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++; 383 insert = XtCreateManagedWidget("insert", commandWidgetClass, form, 384 args, num_args); 385 386 num_args = 0; 387 XtSetArg(args[num_args], XtNlabel, "Cancel"); num_args++; 388 XtSetArg(args[num_args], XtNfromVert, text); num_args++; 389 XtSetArg(args[num_args], XtNfromHoriz, insert); num_args++; 390 XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; 391 XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++; 392 cancel = XtCreateManagedWidget(DISMISS_NAME, commandWidgetClass, form, 393 args, num_args); 394 395 XtAddCallback(cancel, XtNcallback, PopdownFileInsert, (XtPointer)tw); 396 XtAddCallback(insert, XtNcallback, DoInsert, (XtPointer)tw); 397 398 XtSetKeyboardFocus(form, text); 399 400 /* 401 * Bind <CR> to insert file 402 */ 403 trans = XtParseTranslationTable("<Key>Return:InsertFileAction()"); 404 XtOverrideTranslations(text, trans); 405} 406 407/* 408 * This section of the file contains all the functions that 409 * the search dialog box uses 410 */ 411/* 412 * Function: 413 * _XawTextDoSearchAction 414 * 415 * Description: 416 * Action routine that can be bound to dialog box's Text Widget that 417 * will search for a string in the main Text Widget. 418 * 419 * Note: 420 * If the search was successful and the argument popdown is passed to 421 * this action routine then the widget will automatically popdown the 422 * search widget 423 */ 424/*ARGSUSED*/ 425void 426_XawTextDoSearchAction(Widget w, XEvent *event _X_UNUSED, 427 String *params, Cardinal *num_params) 428{ 429 TextWidget tw = (TextWidget)XtParent(XtParent(XtParent(w))); 430 Bool popdown = False; 431 432 if (*num_params == 1 && (params[0][0] == 'p' || params[0][0] == 'P')) 433 popdown = True; 434 435 if (DoSearch(tw->text.search) && popdown) 436 PopdownSearch(w, (XtPointer)tw->text.search, NULL); 437} 438 439/* 440 * Function: 441 * _XawTextPopdownSearchAction 442 * 443 * Description: 444 * Action routine that can be bound to dialog box's Text Widget that 445 * will popdown the search widget. 446 */ 447/*ARGSUSED*/ 448void 449_XawTextPopdownSearchAction(Widget w, XEvent *event _X_UNUSED, 450 String *params _X_UNUSED, Cardinal *num_params _X_UNUSED) 451{ 452 TextWidget tw = (TextWidget)XtParent(XtParent(XtParent(w))); 453 454 PopdownSearch(w, (XtPointer)tw->text.search, NULL); 455} 456 457/* 458 * Function: 459 * PopdownSearch 460 * 461 * Parameters: 462 * w - (not used) 463 * closure - pointer to the search structure 464 * call_data - (not used) 465 * 466 * Description: 467 * Pops down the search widget and resets it 468 */ 469/*ARGSUSED*/ 470static void 471PopdownSearch(Widget w _X_UNUSED, XtPointer closure, XtPointer call_data _X_UNUSED) 472{ 473 struct SearchAndReplace *search = (struct SearchAndReplace *)closure; 474 475 XtPopdown(search->search_popup); 476 SetSearchLabels(search, SEARCH_LABEL_1, SEARCH_LABEL_2, False); 477} 478 479/* 480 * Function: 481 * SearchButton 482 * 483 * Arguments: 484 * w - (not used) 485 * closure - pointer to the search info 486 * call_data - (not used) 487 * 488 * Description: 489 * Performs a search when the button is clicked. 490 */ 491/*ARGSUSED*/ 492static void 493SearchButton(Widget w _X_UNUSED, XtPointer closure, XtPointer call_data _X_UNUSED) 494{ 495 (void)DoSearch((struct SearchAndReplace *)closure); 496} 497 498/* 499 * Function: 500 * _XawTextSearch 501 * 502 * Parameters: 503 * w - text widget 504 * event - X Event (used to get x and y location) 505 * params - parameter list 506 * num_params - "" 507 * 508 * Description: 509 * Action routine that can be bound to the text widget 510 * it will popup the search dialog box. 511 * 512 * Note: 513 * The parameter list contains one or two entries that may be 514 * the following. 515 * 516 * First Entry: 517 * The first entry is the direction to search by default. 518 * This argument must be specified and may have a value of 519 * "left" or "right". 520 * 521 * Second Entry: 522 * This entry is optional and contains the value of the default 523 * string to search for. 524 */ 525 526#define SEARCH_HEADER "Text Widget - Search():" 527void 528_XawTextSearch(Widget w, XEvent *event, String *params, Cardinal *num_params) 529{ 530 TextWidget ctx = (TextWidget)w; 531 XawTextScanDirection dir; 532 String ptr; 533 char buf[BUFSIZ]; 534 XawTextEditType edit_mode; 535 Arg args[1]; 536 wchar_t wcs[1]; 537 538 if (*num_params < 1 || *num_params > 2) { 539 snprintf(buf, sizeof(buf), "%s %s\n%s", SEARCH_HEADER, 540 "This action must have only", 541 "one or two parameters"); 542 XtAppWarning(XtWidgetToApplicationContext(w), buf); 543 return; 544 } 545 546 if (*num_params == 2) 547 ptr = params[1]; 548 else if (XawTextFormat(ctx, XawFmtWide)) { 549 /* This just does the equivalent of 550 ptr = ""L, a waste because params[1] isn't W aligned */ 551 ptr = (char *)wcs; 552 wcs[0] = 0; 553 } 554 else 555 ptr = ""; 556 557 switch(params[0][0]) { 558 case 'b': /* Left */ 559 case 'B': 560 dir = XawsdLeft; 561 break; 562 case 'f': /* Right */ 563 case 'F': 564 dir = XawsdRight; 565 break; 566 default: 567 snprintf(buf, sizeof(buf), "%s %s\n%s", SEARCH_HEADER, 568 "The first parameter must be", 569 "Either 'backward' or 'forward'"); 570 XtAppWarning(XtWidgetToApplicationContext(w), buf); 571 return; 572 } 573 574 if (ctx->text.search== NULL) { 575 ctx->text.search = XtNew(struct SearchAndReplace); 576 ctx->text.search->search_popup = CreateDialog(w, ptr, "search", 577 AddSearchChildren); 578 XtRealizeWidget(ctx->text.search->search_popup); 579 SetWMProtocolTranslations(ctx->text.search->search_popup); 580 } 581 else if (*num_params > 1) 582 XtVaSetValues(ctx->text.search->search_text, XtNstring, ptr, NULL); 583 584 XtSetArg(args[0], XtNeditType,&edit_mode); 585 XtGetValues(ctx->text.source, args, 1); 586 587 InitializeSearchWidget(ctx->text.search, dir, (edit_mode == XawtextEdit)); 588 589 CenterWidgetOnPoint(ctx->text.search->search_popup, event); 590 XtPopup(ctx->text.search->search_popup, XtGrabNone); 591} 592 593/* 594 * Function: 595 * InitializeSearchWidget 596 * 597 * Parameters: 598 * search - search widget structure 599 * dir - direction to search 600 * replace_active - state of the sensitivity for the replace button 601 * 602 * Description: 603 * This function initializes the search widget and 604 * is called each time the search widget is popped up. 605 */ 606static void 607InitializeSearchWidget(struct SearchAndReplace *search, 608 XawTextScanDirection dir, Bool replace_active) 609{ 610 SetResource(search->rep_one, XtNsensitive, (XtArgVal)replace_active); 611 SetResource(search->rep_all, XtNsensitive, (XtArgVal)replace_active); 612 SetResource(search->rep_label, XtNsensitive, (XtArgVal)replace_active); 613 SetResource(search->rep_text, XtNsensitive, (XtArgVal)replace_active); 614 615 switch (dir) { 616 case XawsdLeft: 617 SetResource(search->left_toggle, XtNstate, (XtArgVal)True); 618 break; 619 case XawsdRight: 620 SetResource(search->right_toggle, XtNstate, (XtArgVal)True); 621 break; 622 } 623} 624 625/* 626 * Function: 627 * AddSearchChildren 628 * 629 * Parameters: 630 * form - form widget for the search widget 631 * ptr - pointer to the initial string for the Text Widget 632 * tw - main text widget 633 * 634 * Description: 635 * Adds all children to the Search Dialog Widget. 636 */ 637static void 638AddSearchChildren(Widget form, String ptr, Widget tw) 639{ 640 Arg args[10]; 641 Cardinal num_args; 642 Widget cancel, search_button, s_label, s_text, r_text; 643 XtTranslations trans; 644 struct SearchAndReplace *search = ((TextWidget)tw)->text.search; 645 646 num_args = 0; 647 XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; 648 XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++; 649 XtSetArg(args[num_args], XtNresizable, True); num_args++; 650 XtSetArg(args[num_args], XtNborderWidth, 0); num_args++; 651 search->label1 = XtCreateManagedWidget("label1", labelWidgetClass, form, 652 args, num_args); 653 654 num_args = 0; 655 XtSetArg(args[num_args], XtNfromVert, search->label1); num_args++; 656 XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; 657 XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++; 658 XtSetArg(args[num_args], XtNresizable, True); num_args++; 659 XtSetArg(args[num_args], XtNborderWidth, 0); num_args++; 660 search->label2 = XtCreateManagedWidget("label2", labelWidgetClass, form, 661 args, num_args); 662 663 /* 664 * We need to add R_OFFSET to the radio_data, because the value zero (0) 665 * has special meaning 666 */ 667 num_args = 0; 668 XtSetArg(args[num_args], XtNlabel, "Backward"); num_args++; 669 XtSetArg(args[num_args], XtNfromVert, search->label2); num_args++; 670 XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; 671 XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++; 672 XtSetArg(args[num_args], XtNradioData, (XPointer)XawsdLeft + R_OFFSET); 673 num_args++; 674 search->left_toggle = XtCreateManagedWidget("backwards", toggleWidgetClass, 675 form, args, num_args); 676 677 num_args = 0; 678 XtSetArg(args[num_args], XtNlabel, "Forward"); num_args++; 679 XtSetArg(args[num_args], XtNfromVert, search->label2); num_args++; 680 XtSetArg(args[num_args], XtNfromHoriz, search->left_toggle); num_args++; 681 XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; 682 XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++; 683 XtSetArg(args[num_args], XtNradioGroup, search->left_toggle); num_args++; 684 XtSetArg(args[num_args], XtNradioData, (XPointer)XawsdRight + R_OFFSET); 685 num_args++; 686 search->right_toggle = XtCreateManagedWidget("forwards", toggleWidgetClass, 687 form, args, num_args); 688 689 { 690 XtTranslations radio_translations; 691 692 radio_translations = XtParseTranslationTable(radio_trans_string); 693 XtOverrideTranslations(search->left_toggle, radio_translations); 694 XtOverrideTranslations(search->right_toggle, radio_translations); 695 } 696 697#ifndef OLDXAW 698 if (XawTextFormat((TextWidget)tw, XawFmt8Bit)) { 699 num_args = 0; 700 XtSetArg(args[num_args], XtNlabel, "Case Sensitive"); num_args++; 701 XtSetArg(args[num_args], XtNfromVert, search->label2); num_args++; 702 XtSetArg(args[num_args], XtNfromHoriz, search->right_toggle); num_args++; 703 XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; 704 XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++; 705 XtSetArg(args[num_args], XtNstate, True); num_args++; 706 search->case_sensitive = XtCreateManagedWidget("case", toggleWidgetClass, 707 form, args, num_args); 708 } 709 else 710 search->case_sensitive = NULL; 711#endif 712 713 num_args = 0; 714 XtSetArg(args[num_args], XtNfromVert, search->left_toggle); num_args++; 715 XtSetArg(args[num_args], XtNlabel, "Search for: "); num_args++; 716 XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; 717 XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++; 718 XtSetArg(args[num_args], XtNborderWidth, 0 ); num_args++; 719 s_label = XtCreateManagedWidget("searchLabel", labelWidgetClass, form, 720 args, num_args); 721 722 num_args = 0; 723 XtSetArg(args[num_args], XtNfromVert, search->left_toggle); num_args++; 724 XtSetArg(args[num_args], XtNfromHoriz, s_label); num_args++; 725 XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; 726 XtSetArg(args[num_args], XtNright, XtChainRight); num_args++; 727 XtSetArg(args[num_args], XtNeditType, XawtextEdit); num_args++; 728 XtSetArg(args[num_args], XtNresizable, True); num_args++; 729 XtSetArg(args[num_args], XtNstring, ptr); num_args++; 730 s_text = XtCreateManagedWidget("searchText", asciiTextWidgetClass, form, 731 args, num_args); 732 search->search_text = s_text; 733 734 num_args = 0; 735 XtSetArg(args[num_args], XtNfromVert, s_text); num_args++; 736 XtSetArg(args[num_args], XtNlabel, "Replace with:"); num_args++; 737 XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; 738 XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++; 739 XtSetArg(args[num_args], XtNborderWidth, 0); num_args++; 740 search->rep_label = XtCreateManagedWidget("replaceLabel", labelWidgetClass, 741 form, args, num_args); 742 743 num_args = 0; 744 XtSetArg(args[num_args], XtNfromHoriz, s_label); num_args++; 745 XtSetArg(args[num_args], XtNfromVert, s_text); num_args++; 746 XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; 747 XtSetArg(args[num_args], XtNright, XtChainRight); num_args++; 748 XtSetArg(args[num_args], XtNeditType, XawtextEdit); num_args++; 749 XtSetArg(args[num_args], XtNresizable, True); num_args++; 750 XtSetArg(args[num_args], XtNstring, ""); num_args++; 751 r_text = XtCreateManagedWidget("replaceText", asciiTextWidgetClass, 752 form, args, num_args); 753 search->rep_text = r_text; 754 755 num_args = 0; 756 XtSetArg(args[num_args], XtNlabel, "Search"); num_args++; 757 XtSetArg(args[num_args], XtNfromVert, r_text); num_args++; 758 XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; 759 XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++; 760 search_button = XtCreateManagedWidget("search", commandWidgetClass, form, 761 args, num_args); 762 763 num_args = 0; 764 XtSetArg(args[num_args], XtNlabel, "Replace"); num_args++; 765 XtSetArg(args[num_args], XtNfromVert, r_text); num_args++; 766 XtSetArg(args[num_args], XtNfromHoriz, search_button); num_args++; 767 XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; 768 XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++; 769 search->rep_one = XtCreateManagedWidget("replaceOne", commandWidgetClass, 770 form, args, num_args); 771 772 num_args = 0; 773 XtSetArg(args[num_args], XtNlabel, "Replace All"); num_args++; 774 XtSetArg(args[num_args], XtNfromVert, r_text); num_args++; 775 XtSetArg(args[num_args], XtNfromHoriz, search->rep_one); num_args++; 776 XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; 777 XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++; 778 search->rep_all = XtCreateManagedWidget("replaceAll", commandWidgetClass, 779 form, args, num_args); 780 781 num_args = 0; 782 XtSetArg(args[num_args], XtNlabel, "Cancel"); num_args++; 783 XtSetArg(args[num_args], XtNfromVert, r_text); num_args++; 784 XtSetArg(args[num_args], XtNfromHoriz, search->rep_all); num_args++; 785 XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; 786 XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++; 787 cancel = XtCreateManagedWidget(DISMISS_NAME, commandWidgetClass, form, 788 args, num_args); 789 790 XtAddCallback(search_button, XtNcallback, SearchButton, (XtPointer)search); 791 XtAddCallback(search->rep_one, XtNcallback, DoReplaceOne, (XtPointer)search); 792 XtAddCallback(search->rep_all, XtNcallback, DoReplaceAll, (XtPointer)search); 793 XtAddCallback(cancel, XtNcallback, PopdownSearch, (XtPointer)search); 794 795 /* 796 * Initialize the text entry fields 797 */ 798 { 799 Pixel color; 800 801 num_args = 0; 802 XtSetArg(args[num_args], XtNbackground, &color); num_args++; 803 XtGetValues(search->rep_text, args, num_args); 804 num_args = 0; 805 XtSetArg(args[num_args], XtNborderColor, color); num_args++; 806 XtSetValues(search->rep_text, args, num_args); 807 XtSetKeyboardFocus(form, search->search_text); 808 } 809 810 SetSearchLabels(search, SEARCH_LABEL_1, SEARCH_LABEL_2, False); 811 812 /* 813 * Bind Extra translations 814 */ 815 trans = XtParseTranslationTable(search_text_trans); 816 XtOverrideTranslations(search->search_text, trans); 817 818 trans = XtParseTranslationTable(rep_text_trans); 819 XtOverrideTranslations(search->rep_text, trans); 820} 821 822/* 823 * Function: 824 * DoSearch 825 * 826 * Parameters: 827 * search - search structure 828 * 829 * Description: 830 * Performs a search 831 * 832 * Returns: 833 * True if successful 834 */ 835/*ARGSUSED*/ 836static Bool 837DoSearch(struct SearchAndReplace *search) 838{ 839 char msg[37]; 840 Widget tw = XtParent(search->search_popup); 841 XawTextPosition pos; 842 XawTextScanDirection dir; 843 XawTextBlock text; 844 TextWidget ctx = (TextWidget)tw; 845 846 text.firstPos = 0; 847 text.ptr = GetStringRaw(search->search_text); 848 if ((text.format = (unsigned long)_XawTextFormat(ctx)) == XawFmtWide) 849 text.length = (int)wcslen((wchar_t*)text.ptr); 850 else { 851 text.length = (int)strlen(text.ptr); 852 853#ifndef OLDXAW 854 if (search->case_sensitive) { 855 /* text.firstPos isn't useful here, so I'll use it as an 856 * options flag. 857 */ 858 Arg args[1]; 859 Boolean case_sensitive; 860 861 XtSetArg(args[0], XtNstate, &case_sensitive); 862 XtGetValues(search->case_sensitive, args, 1); 863 text.firstPos = !case_sensitive; 864 } 865#endif /* OLDXAW */ 866 } 867 868 dir = (XawTextScanDirection)(unsigned long) 869 ((XPointer)XawToggleGetCurrent(search->left_toggle) - R_OFFSET); 870 871 pos = XawTextSearch(tw, dir, &text); 872 873 /* The Raw string in find.ptr may be WC I can't use here, so I re - call 874 GetString to get a tame version */ 875 876 if (pos == XawTextSearchError) { 877 String ptr; 878 int len; 879 880 ptr = GetString(search->search_text); 881 len = (int)strlen(ptr); 882 snprintf(msg, sizeof(msg), "%s", ptr); 883 884 ptr = strchr(msg, '\n'); 885 if (ptr != NULL || sizeof(msg) - 1 < (size_t)len) { 886 if (ptr != NULL) 887 len = (int)(ptr - msg + 4); 888 else 889 len = (int)strlen(msg); 890 891 if (len < 4) 892 strcpy(msg, "..."); 893 else 894 strcpy(msg + len - 4, "..."); 895 } 896 XawTextUnsetSelection(tw); 897 SetSearchLabels(search, "Could not find string", msg, True); 898 899 return (False); 900 } 901 XawTextDisableRedisplay(tw); 902 XawTextSetSelection(tw, pos, pos + text.length); 903 search->selection_changed = False; /* selection is good */ 904 905 if (dir == XawsdRight) 906 XawTextSetInsertionPoint(tw, pos + text.length); 907 else 908 XawTextSetInsertionPoint(tw, pos); 909 _XawTextShowPosition(ctx); 910 XawTextEnableRedisplay(tw); 911 912 return (True); 913} 914 915/* 916 * This section of the file contains all the functions that 917 * the replace dialog box uses 918 */ 919/* 920 * Function: 921 * _XawTextDoReplaceAction 922 * 923 * Description: 924 * Action routine that can be bound to dialog box's 925 * Text Widget that will replace a string in the main Text Widget. 926 */ 927/*ARGSUSED*/ 928void 929_XawTextDoReplaceAction(Widget w, XEvent *event _X_UNUSED, 930 String *params, Cardinal *num_params) 931{ 932 TextWidget ctx = (TextWidget)XtParent(XtParent(XtParent(w))); 933 Bool popdown = False; 934 935 if (*num_params == 1 && (params[0][0] == 'p' || params[0][0] == 'P')) 936 popdown = True; 937 938 if (Replace( ctx->text.search, True, popdown) && popdown) 939 PopdownSearch(w, (XtPointer)ctx->text.search, NULL); 940} 941 942/* 943 * Function: 944 * DoReplaceOne 945 * 946 * Arguments: 947 * w - *** Not Used *** 948 * closure - a pointer to the search structure 949 * call_data - *** Not Used *** 950 * 951 * Description: 952 * Replaces the first instance of the string in the search 953 * dialog's text widget with the one in the replace dialog's text widget. 954 */ 955/*ARGSUSED*/ 956static void 957DoReplaceOne(Widget w _X_UNUSED, XtPointer closure, XtPointer call_data _X_UNUSED) 958{ 959 Replace((struct SearchAndReplace *)closure, True, False); 960} 961 962/* 963 * Function: 964 * DoReplaceAll 965 * 966 * Parameters: 967 * w - (not used) 968 * closure - pointer to the search structure 969 * call_data - (not used) 970 * 971 * Description: 972 * Replaces every instance of the string in the search dialog's 973 * text widget with the one in the replace dialog's text widget. 974 */ 975/*ARGSUSED*/ 976static void 977DoReplaceAll(Widget w _X_UNUSED, XtPointer closure, XtPointer call_data _X_UNUSED) 978{ 979 Replace((struct SearchAndReplace *)closure, False, False); 980} 981 982/* 983 * Function: 984 * Replace 985 * 986 * Parameters: 987 * tw - Text Widget to replce the string in 988 * once_only - if True then only replace the first one found, 989 * else replace all of them 990 * show_current - if true then leave the selection on the 991 * string that was just replaced, otherwise 992 * move it onto the next one 993 * 994 * Description: 995 * This is the function that does the real work of 996 * replacing strings in the main text widget. 997 */ 998static Bool 999Replace(struct SearchAndReplace *search, Bool once_only, Bool show_current) 1000{ 1001 XawTextPosition pos, new_pos, end_pos, ipos; 1002 XawTextScanDirection dir; 1003 XawTextBlock find, replace; 1004 Widget tw = XtParent(search->search_popup); 1005 int count = 0; 1006 TextWidget ctx = (TextWidget)tw; 1007 Bool redisplay; 1008 1009 find.ptr = GetStringRaw(search->search_text); 1010 if ((find.format = (unsigned long)_XawTextFormat(ctx)) == XawFmtWide) 1011 find.length = (int)(XawTextPosition)wcslen((wchar_t*)find.ptr); 1012 else 1013 find.length = (int)(XawTextPosition)strlen(find.ptr); 1014 find.firstPos = 0; 1015 1016 replace.ptr = GetStringRaw(search->rep_text); 1017 replace.firstPos = 0; 1018 if ((replace.format = (unsigned long)_XawTextFormat(ctx)) == XawFmtWide) 1019 replace.length = (int)wcslen((wchar_t*)replace.ptr); 1020 else 1021 replace.length = (int)strlen(replace.ptr); 1022 1023 dir = (XawTextScanDirection)(unsigned long) 1024 ((XPointer)XawToggleGetCurrent(search->left_toggle) - R_OFFSET); 1025 1026 redisplay = !once_only || (once_only && !show_current); 1027 ipos = XawTextGetInsertionPoint(tw); 1028 if (redisplay) 1029 XawTextDisableRedisplay(tw); 1030 /*CONSTCOND*/ 1031 while (True) { 1032 if (count != 0) { 1033 new_pos = XawTextSearch(tw, dir, &find); 1034 1035 if (new_pos == XawTextSearchError) { 1036 if (count == 0) { 1037 char msg[37]; 1038 String ptr; 1039 int len; 1040 1041 ptr = GetString(search->search_text); 1042 len = (int)strlen(ptr); 1043 snprintf(msg, sizeof(msg), "%s", ptr); 1044 ptr = strchr(msg, '\n'); 1045 if (ptr != NULL || sizeof(msg) - 1 < (size_t)len) { 1046 if (ptr != NULL) 1047 len = (int)(ptr - msg + 4); 1048 else 1049 len = (int)strlen(msg); 1050 1051 if (len < 4) 1052 strcpy(msg, "..."); 1053 else 1054 strcpy(msg + len - 4, "..."); 1055 } 1056 SetSearchLabels(search, "Could not find string", msg, True); 1057 1058 if (redisplay) { 1059 XawTextSetInsertionPoint(tw, ipos); 1060 _XawTextShowPosition(ctx); 1061 XawTextEnableRedisplay(tw); 1062 } 1063 1064 return (False); 1065 } 1066 else 1067 break; 1068 } 1069 pos = new_pos; 1070 end_pos = pos + find.length; 1071 } 1072 else { 1073 XawTextGetSelectionPos(tw, &pos, &end_pos); 1074 1075 if (search->selection_changed) { 1076 SetSearchLabels(search, "Selection modified, aborting.", 1077 "", True); 1078 if (redisplay) { 1079 XawTextSetInsertionPoint(tw, ipos); 1080 XawTextEnableRedisplay(tw); 1081 } 1082 1083 return (False); 1084 } 1085 if (pos == end_pos) { 1086 if (redisplay) { 1087 XawTextSetInsertionPoint(tw, ipos); 1088 XawTextEnableRedisplay(tw); 1089 } 1090 1091 return (False); 1092 } 1093 } 1094 1095 if (XawTextReplace(tw, pos, end_pos, &replace) != XawEditDone) { 1096 SetSearchLabels(search, "Error while replacing.", "", True); 1097 if (redisplay) { 1098 XawTextSetInsertionPoint(tw, ipos); 1099 XawTextEnableRedisplay(tw); 1100 } 1101 1102 return (False); 1103 } 1104 1105 if (dir == XawsdRight) 1106 ipos = pos + replace.length; 1107 else 1108 ipos = pos; 1109 1110 if (once_only) { 1111 if (show_current) 1112 break; 1113 else { 1114 DoSearch(search); 1115 XawTextEnableRedisplay(tw); 1116 1117 return (True); 1118 } 1119 } 1120 else 1121 ctx->text.insertPos = ipos; 1122 count++; 1123 } 1124 1125 if (replace.length == 0) 1126 XawTextUnsetSelection(tw); 1127 else 1128 XawTextSetSelection(tw, pos, pos + replace.length); 1129 1130 XawTextSetInsertionPoint(tw, ipos); 1131 _XawTextShowPosition(ctx); 1132 XawTextEnableRedisplay(tw); 1133 1134 return (True); 1135} 1136 1137/* 1138 * Function: 1139 * SetSearchLabels 1140 * 1141 * Parameters: 1142 * search - search structure 1143 * msg1 - message to put in each search label 1144 * msg2 - "" 1145 * bell - if True then ring bell 1146 * 1147 * Description: 1148 * Sets both the search labels, and also rings the bell. 1149 */ 1150static void 1151SetSearchLabels(struct SearchAndReplace *search, String msg1, String msg2, 1152 Bool bell) 1153{ 1154 (void)SetResource(search->label1, XtNlabel, (XtArgVal)msg1); 1155 (void)SetResource(search->label2, XtNlabel, (XtArgVal)msg2); 1156 if (bell) 1157 XBell(XtDisplay(search->search_popup), 0); 1158} 1159 1160/* 1161 * This section of the file contains utility routines used by 1162 * other functions in this file 1163 */ 1164/* 1165 * Function: 1166 * _XawTextSetField 1167 * 1168 * Description: 1169 * Action routine that can be bound to dialog box's 1170 * Text Widget that will send input to the field specified. 1171 */ 1172/*ARGSUSED*/ 1173void 1174_XawTextSetField(Widget w, XEvent *event _X_UNUSED, String *params, Cardinal *num_params) 1175{ 1176 struct SearchAndReplace *search; 1177 Widget cnew, old; 1178 1179 search = ((TextWidget)XtParent(XtParent(XtParent(w))))->text.search; 1180 1181 if (*num_params != 1) { 1182 SetSearchLabels(search, "Error: SetField Action must have", 1183 "exactly one argument", True); 1184 return; 1185 } 1186 switch (params[0][0]) { 1187 case 's': 1188 case 'S': 1189 cnew = search->search_text; 1190 old = search->rep_text; 1191 break; 1192 case 'r': 1193 case 'R': 1194 old = search->search_text; 1195 cnew = search->rep_text; 1196 break; 1197 default: 1198 SetSearchLabels(search, 1199 "Error: SetField Action's first Argument must", 1200 "be either 'Search' or 'Replace'", True); 1201 return; 1202 } 1203 _SetField(cnew, old); 1204} 1205 1206/* 1207 * Function: 1208 * _SetField 1209 * 1210 * Parameters: 1211 * cnew - new and old text fields 1212 * old - "" 1213 * 1214 * Description: 1215 * Sets the current text field. 1216 */ 1217static void 1218_SetField(Widget cnew, Widget old) 1219{ 1220 Arg args[2]; 1221 Pixel new_border, old_border, old_bg; 1222 1223 if (!XtIsSensitive(cnew)) { 1224 XBell(XtDisplay(old), 0); /* Don't set field to an inactive Widget */ 1225 return; 1226 } 1227 1228 XtSetKeyboardFocus(XtParent(cnew), cnew); 1229 1230 XtSetArg(args[0], XtNborderColor, &old_border); 1231 XtSetArg(args[1], XtNbackground, &old_bg); 1232 XtGetValues(cnew, args, 2); 1233 1234 XtSetArg(args[0], XtNborderColor, &new_border); 1235 XtGetValues(old, args, 1); 1236 1237 if (old_border != old_bg) /* Colors are already correct, return */ 1238 return; 1239 1240 SetResource(old, XtNborderColor, (XtArgVal)old_border); 1241 SetResource(cnew, XtNborderColor, (XtArgVal)new_border); 1242} 1243 1244/* 1245 * Function: 1246 * SetResourceByName 1247 * 1248 * Parameters: 1249 * shell - shell widget of the popup 1250 * name - name of the child 1251 * res_name - name of the resource 1252 * value - value of the resource 1253 * 1254 * Description: 1255 * Sets a resource in any of the dialog children given 1256 * name of the child and the shell widget of the dialog. 1257 * 1258 * Returns: 1259 * True if successful 1260 */ 1261static Bool 1262SetResourceByName(Widget shell, String name, String res_name, XtArgVal value) 1263{ 1264 Widget temp_widget; 1265 char buf[BUFSIZ]; 1266 1267 snprintf(buf, sizeof(buf), "%s.%s", FORM_NAME, name); 1268 1269 if ((temp_widget = XtNameToWidget(shell, buf)) != NULL) { 1270 SetResource(temp_widget, res_name, value); 1271 return (True); 1272 } 1273 return (False); 1274} 1275 1276/* 1277 * Function: 1278 * SetResource 1279 * 1280 * Parameters: 1281 * w - widget 1282 * res_name - name of the resource 1283 * value - value of the resource 1284 * 1285 * Description: 1286 * Sets a resource in a widget 1287 */ 1288static void 1289SetResource(Widget w, String res_name, XtArgVal value) 1290{ 1291 Arg args[1]; 1292 1293 XtSetArg(args[0], res_name, value); 1294 XtSetValues( w, args, 1); 1295} 1296 1297/* 1298 * Function: 1299 * GetString{Raw} 1300 * 1301 * Parameters: 1302 * text - text widget whose string we will get 1303 * 1304 * Description: 1305 * Gets the value for the string in the popup. 1306 * 1307 * Returns: 1308 * GetString: the string as a MB 1309 * GetStringRaw: the exact buffer contents suitable for a search 1310 */ 1311static String 1312GetString(Widget text) 1313{ 1314 String string; 1315 Arg args[1]; 1316 1317 XtSetArg(args[0], XtNstring, &string); 1318 XtGetValues(text, args, 1); 1319 1320 return (string); 1321} 1322 1323static _XtString 1324GetStringRaw(Widget tw) 1325{ 1326 TextWidget ctx = (TextWidget)tw; 1327 XawTextPosition last; 1328 1329 last = XawTextSourceScan(ctx->text.source, 0, XawstAll, XawsdRight, 1330 ctx->text.mult, True); 1331 return (_XawTextGetText(ctx, 0, last)); 1332} 1333 1334/* 1335 * Function: 1336 * CenterWidgetOnPoint 1337 * 1338 * Parameters: 1339 * w - shell widget 1340 * event - event containing the location of the point 1341 * 1342 * Description: 1343 * Centers a shell widget on a point relative to the root window. 1344 * 1345 * Note: 1346 * The widget is not allowed to go off the screen 1347 */ 1348static void 1349CenterWidgetOnPoint(Widget w, XEvent *event) 1350{ 1351 Arg args[3]; 1352 Cardinal num_args; 1353 Dimension width, height, b_width; 1354 Position x, y, max_x, max_y; 1355 1356 if (event != NULL) { 1357 switch (event->type) { 1358 case ButtonPress: 1359 case ButtonRelease: 1360 x = (Position)event->xbutton.x_root; 1361 y = (Position)event->xbutton.y_root; 1362 break; 1363 case KeyPress: 1364 case KeyRelease: 1365 x = (Position)event->xkey.x_root; 1366 y = (Position)event->xkey.y_root; 1367 break; 1368 default: 1369 return; 1370 } 1371 } 1372 else 1373 return; 1374 1375 num_args = 0; 1376 XtSetArg(args[num_args], XtNwidth, &width); num_args++; 1377 XtSetArg(args[num_args], XtNheight, &height); num_args++; 1378 XtSetArg(args[num_args], XtNborderWidth, &b_width); num_args++; 1379 XtGetValues(w, args, num_args); 1380 1381 width = (Dimension)(width + (b_width << 1)); 1382 height = (Dimension)(height + (b_width << 1)); 1383 1384 x = (Position)(x - (width >> 1)); 1385 if (x < 0) 1386 x = 0; 1387 if (x > (max_x = (Position)(XtScreen(w)->width - width))) 1388 x = max_x; 1389 1390 y = (Position)(y - (height >> 1)); 1391 if (y < 0) 1392 y = 0; 1393 if (y > (max_y = (Position)(XtScreen(w)->height - height))) 1394 y = max_y; 1395 1396 num_args = 0; 1397 XtSetArg(args[num_args], XtNx, x); num_args++; 1398 XtSetArg(args[num_args], XtNy, y); num_args++; 1399 XtSetValues(w, args, num_args); 1400} 1401 1402/* 1403 * Function: 1404 * CreateDialog 1405 * 1406 * Parameters: 1407 * parent - parent of the dialog - the main text widget 1408 * ptr - initial_string for the dialog 1409 * name - name of the dialog 1410 * func - function to create the children of the dialog 1411 * 1412 * Returns: 1413 * Popup shell of the dialog 1414 * 1415 * Note: 1416 * The function argument is passed the following arguments: 1417 * form - from widget that is the dialog 1418 * ptr - initial string for the dialog's text widget 1419 * parent - parent of the dialog - the main text widget 1420 */ 1421static Widget 1422CreateDialog(Widget parent, String ptr, String name, AddFunc func) 1423{ 1424 Widget popup, form; 1425 Arg args[5]; 1426 Cardinal num_args; 1427 1428 num_args = 0; 1429 XtSetArg(args[num_args], XtNiconName, name); num_args++; 1430 XtSetArg(args[num_args], XtNgeometry, NULL); num_args++; 1431 XtSetArg(args[num_args], XtNallowShellResize, True); num_args++; 1432 XtSetArg(args[num_args], XtNtransientFor, GetShell(parent));num_args++; 1433 popup = XtCreatePopupShell(name, transientShellWidgetClass, 1434 parent, args, num_args); 1435 1436 form = XtCreateManagedWidget(FORM_NAME, formWidgetClass, popup, NULL, 0); 1437 XtManageChild (form); 1438 1439 (*func)(form, ptr, parent); 1440 1441 return (popup); 1442} 1443 1444/* 1445 * Function 1446 * GetShell 1447 * nearest shell widget. 1448 * 1449 * Parameters: 1450 * w - widget whose parent shell should be returned 1451 * 1452 * Returns: 1453 * The shell widget among the ancestors of w that is the 1454 * fewest levels up in the widget hierarchy. 1455 * 1456 * Description: 1457 * Walks up the widget hierarchy to find the topmost shell widget. 1458 */ 1459static Widget 1460GetShell(Widget w) 1461{ 1462 while (w != NULL && !XtIsShell(w)) 1463 w = XtParent(w); 1464 1465 return (w); 1466} 1467 1468static Bool 1469InParams(String str, String *p, unsigned int n) 1470{ 1471 unsigned int i; 1472 1473 for (i = 0; i < n; p++, i++) 1474 if (!XmuCompareISOLatin1(*p, str)) 1475 return (True); 1476 return (False); 1477} 1478 1479static const char *WM_DELETE_WINDOW = "WM_DELETE_WINDOW"; 1480 1481static void 1482WMProtocols(Widget w, XEvent *event, String *params, Cardinal *num_params) 1483{ 1484 Atom wm_delete_window; 1485 Atom wm_protocols; 1486 1487 wm_delete_window = XInternAtom(XtDisplay(w), WM_DELETE_WINDOW, True); 1488 wm_protocols = XInternAtom(XtDisplay(w), "WM_PROTOCOLS", True); 1489 1490 /* Respond to a recognized WM protocol request if 1491 * event type is ClientMessage and no parameters are passed, or 1492 * event type is ClientMessage and event data is matched to parameters, or 1493 * event type isn't ClientMessage and parameters make a request 1494 */ 1495#define DO_DELETE_WINDOW InParams(WM_DELETE_WINDOW, params, *num_params) 1496 1497 if ((event->type == ClientMessage 1498 && event->xclient.message_type == wm_protocols 1499 && (Atom)event->xclient.data.l[0] == wm_delete_window 1500 && (*num_params == 0 || DO_DELETE_WINDOW)) 1501 || (event->type != ClientMessage && DO_DELETE_WINDOW)) { 1502#undef DO_DELETE_WINDOW 1503 Widget cancel; 1504 char descendant[DISMISS_NAME_LEN + 2]; 1505 1506 snprintf(descendant, sizeof(descendant), "*%s", DISMISS_NAME); 1507 cancel = XtNameToWidget(w, descendant); 1508 if (cancel) 1509 XtCallCallbacks(cancel, XtNcallback, NULL); 1510 } 1511} 1512 1513static void 1514SetWMProtocolTranslations(Widget w) 1515{ 1516 static XtTranslations compiled_table; 1517 static XtAppContext *app_context_list; 1518 static Cardinal list_size; 1519 1520 unsigned int i; 1521 XtAppContext app_context; 1522 Atom wm_delete_window; 1523 1524 app_context = XtWidgetToApplicationContext(w); 1525 1526 /* parse translation table once */ 1527 if (!compiled_table) 1528 compiled_table = 1529 XtParseTranslationTable("<Message>WM_PROTOCOLS:XawWMProtocols()\n"); 1530 1531 /* add actions once per application context */ 1532 for (i = 0; i < list_size && app_context_list[i] != app_context; i++) 1533 ; 1534 if (i == list_size) { 1535 XtActionsRec actions[1]; 1536 1537 actions[0].string = "XawWMProtocols"; 1538 actions[0].proc = WMProtocols; 1539 list_size++; 1540 app_context_list = (XtAppContext *)XtRealloc 1541 ((char *)app_context_list, (Cardinal)(list_size * sizeof(XtAppContext))); 1542 XtAppAddActions(app_context, actions, 1); 1543 app_context_list[i] = app_context; 1544 } 1545 1546 /* establish communication between the window manager and each shell */ 1547 XtAugmentTranslations(w, compiled_table); 1548 wm_delete_window = XInternAtom(XtDisplay(w), WM_DELETE_WINDOW, False); 1549 (void)XSetWMProtocols(XtDisplay(w), XtWindow(w), &wm_delete_window, 1); 1550} 1551