TextPop.c revision c8571806
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 begining 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 char* INSERT_FILE = "Enter Filename:"; 65static char* SEARCH_LABEL_1 = "Use <Tab> to change fields."; 66static char* SEARCH_LABEL_2 = "Use ^q<Tab> for <Tab>."; 67static char* DISMISS_NAME = "cancel"; 68#define DISMISS_NAME_LEN 6 69static char* FORM_NAME = "form"; 70static char* LABEL_NAME = "label"; 71static char* TEXT_NAME = "text"; 72 73#define R_OFFSET 1 74 75typedef void (*AddFunc)(Widget, char*, Widget); 76 77/* 78 * Prototypes 79 */ 80static void _SetField(Widget, Widget); 81static void AddSearchChildren(Widget, char*, Widget); 82static void AddInsertFileChildren(Widget, char*, 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 String GetStringRaw(Widget); 92static void InitializeSearchWidget(struct SearchAndReplace*, 93 XawTextScanDirection, Bool); 94static Bool InParams(String, String*, unsigned int); 95static Bool InsertFileNamed(Widget, char*); 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, char*, XtArgVal); 101static Bool SetResourceByName(Widget, char*, char*, 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, 169 String *params, Cardinal *num_params) 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 char *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, XtPointer closure, XtPointer call_data) 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 sucessful, False otherwise. 300 */ 301static Bool 302InsertFileNamed(Widget tw, char *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 = ftell(file); 317 text.ptr = XtMalloc(text.length + 1); 318 text.format = XawFmt8Bit; 319 320 fseek(file, 0L, SEEK_SET); 321 if (fread(text.ptr, 1, text.length, file) != 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, char *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 sucessful 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, 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, 450 String *params, Cardinal *num_params) 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, XtPointer closure, XtPointer call_data) 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, XtPointer closure, XtPointer call_data) 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 arguement 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 char *ptr, buf[BUFSIZ]; 533 XawTextEditType edit_mode; 534 Arg args[1]; 535 wchar_t wcs[1]; 536 537 if (*num_params < 1 || *num_params > 2) { 538 snprintf(buf, sizeof(buf), "%s %s\n%s", SEARCH_HEADER, 539 "This action must have only", 540 "one or two parameters"); 541 XtAppWarning(XtWidgetToApplicationContext(w), buf); 542 return; 543 } 544 545 if (*num_params == 2) 546 ptr = params[1]; 547 else if (XawTextFormat(ctx, XawFmtWide)) { 548 /* This just does the equivalent of 549 ptr = ""L, a waste because params[1] isnt W aligned */ 550 ptr = (char *)wcs; 551 wcs[0] = 0; 552 } 553 else 554 ptr = ""; 555 556 switch(params[0][0]) { 557 case 'b': /* Left */ 558 case 'B': 559 dir = XawsdLeft; 560 break; 561 case 'f': /* Right */ 562 case 'F': 563 dir = XawsdRight; 564 break; 565 default: 566 snprintf(buf, sizeof(buf), "%s %s\n%s", SEARCH_HEADER, 567 "The first parameter must be", 568 "Either 'backward' or 'forward'"); 569 XtAppWarning(XtWidgetToApplicationContext(w), buf); 570 return; 571 } 572 573 if (ctx->text.search== NULL) { 574 ctx->text.search = XtNew(struct SearchAndReplace); 575 ctx->text.search->search_popup = CreateDialog(w, ptr, "search", 576 AddSearchChildren); 577 XtRealizeWidget(ctx->text.search->search_popup); 578 SetWMProtocolTranslations(ctx->text.search->search_popup); 579 } 580 else if (*num_params > 1) 581 XtVaSetValues(ctx->text.search->search_text, XtNstring, ptr, NULL); 582 583 XtSetArg(args[0], XtNeditType,&edit_mode); 584 XtGetValues(ctx->text.source, args, 1); 585 586 InitializeSearchWidget(ctx->text.search, dir, (edit_mode == XawtextEdit)); 587 588 CenterWidgetOnPoint(ctx->text.search->search_popup, event); 589 XtPopup(ctx->text.search->search_popup, XtGrabNone); 590} 591 592/* 593 * Function: 594 * InitializeSearchWidget 595 * 596 * Parameters: 597 * search - search widget structure 598 * dir - direction to search 599 * replace_active - state of the sensitivity for the replace button 600 * 601 * Description: 602 * This function initializes the search widget and 603 * is called each time the search widget is poped up. 604 */ 605static void 606InitializeSearchWidget(struct SearchAndReplace *search, 607 XawTextScanDirection dir, Bool replace_active) 608{ 609 SetResource(search->rep_one, XtNsensitive, (XtArgVal)replace_active); 610 SetResource(search->rep_all, XtNsensitive, (XtArgVal)replace_active); 611 SetResource(search->rep_label, XtNsensitive, (XtArgVal)replace_active); 612 SetResource(search->rep_text, XtNsensitive, (XtArgVal)replace_active); 613 614 switch (dir) { 615 case XawsdLeft: 616 SetResource(search->left_toggle, XtNstate, (XtArgVal)True); 617 break; 618 case XawsdRight: 619 SetResource(search->right_toggle, XtNstate, (XtArgVal)True); 620 break; 621 } 622} 623 624/* 625 * Function: 626 * AddSearchChildren 627 * 628 * Parameters: 629 * form - form widget for the search widget 630 * ptr - pointer to the initial string for the Text Widget 631 * tw - main text widget 632 * 633 * Description: 634 * Adds all children to the Search Dialog Widget. 635 */ 636static void 637AddSearchChildren(Widget form, char *ptr, Widget tw) 638{ 639 Arg args[10]; 640 Cardinal num_args; 641 Widget cancel, search_button, s_label, s_text, r_text; 642 XtTranslations trans; 643 struct SearchAndReplace *search = ((TextWidget)tw)->text.search; 644 645 num_args = 0; 646 XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; 647 XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++; 648 XtSetArg(args[num_args], XtNresizable, True); num_args++; 649 XtSetArg(args[num_args], XtNborderWidth, 0); num_args++; 650 search->label1 = XtCreateManagedWidget("label1", labelWidgetClass, form, 651 args, num_args); 652 653 num_args = 0; 654 XtSetArg(args[num_args], XtNfromVert, search->label1); num_args++; 655 XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; 656 XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++; 657 XtSetArg(args[num_args], XtNresizable, True); num_args++; 658 XtSetArg(args[num_args], XtNborderWidth, 0); num_args++; 659 search->label2 = XtCreateManagedWidget("label2", labelWidgetClass, form, 660 args, num_args); 661 662 /* 663 * We need to add R_OFFSET to the radio_data, because the value zero (0) 664 * has special meaning 665 */ 666 num_args = 0; 667 XtSetArg(args[num_args], XtNlabel, "Backward"); num_args++; 668 XtSetArg(args[num_args], XtNfromVert, search->label2); num_args++; 669 XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; 670 XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++; 671 XtSetArg(args[num_args], XtNradioData, (XPointer)XawsdLeft + R_OFFSET); 672 num_args++; 673 search->left_toggle = XtCreateManagedWidget("backwards", toggleWidgetClass, 674 form, args, num_args); 675 676 num_args = 0; 677 XtSetArg(args[num_args], XtNlabel, "Forward"); num_args++; 678 XtSetArg(args[num_args], XtNfromVert, search->label2); num_args++; 679 XtSetArg(args[num_args], XtNfromHoriz, search->left_toggle); num_args++; 680 XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; 681 XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++; 682 XtSetArg(args[num_args], XtNradioGroup, search->left_toggle); num_args++; 683 XtSetArg(args[num_args], XtNradioData, (XPointer)XawsdRight + R_OFFSET); 684 num_args++; 685 search->right_toggle = XtCreateManagedWidget("forwards", toggleWidgetClass, 686 form, args, num_args); 687 688 { 689 XtTranslations radio_translations; 690 691 radio_translations = XtParseTranslationTable(radio_trans_string); 692 XtOverrideTranslations(search->left_toggle, radio_translations); 693 XtOverrideTranslations(search->right_toggle, radio_translations); 694 } 695 696#ifndef OLDXAW 697 if (XawTextFormat((TextWidget)tw, XawFmt8Bit)) { 698 num_args = 0; 699 XtSetArg(args[num_args], XtNlabel, "Case Sensitive"); num_args++; 700 XtSetArg(args[num_args], XtNfromVert, search->label2); num_args++; 701 XtSetArg(args[num_args], XtNfromHoriz, search->right_toggle); num_args++; 702 XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; 703 XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++; 704 XtSetArg(args[num_args], XtNstate, True); num_args++; 705 search->case_sensitive = XtCreateManagedWidget("case", toggleWidgetClass, 706 form, args, num_args); 707 } 708 else 709 search->case_sensitive = NULL; 710#endif 711 712 num_args = 0; 713 XtSetArg(args[num_args], XtNfromVert, search->left_toggle); num_args++; 714 XtSetArg(args[num_args], XtNlabel, "Search for: "); num_args++; 715 XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; 716 XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++; 717 XtSetArg(args[num_args], XtNborderWidth, 0 ); num_args++; 718 s_label = XtCreateManagedWidget("searchLabel", labelWidgetClass, form, 719 args, num_args); 720 721 num_args = 0; 722 XtSetArg(args[num_args], XtNfromVert, search->left_toggle); num_args++; 723 XtSetArg(args[num_args], XtNfromHoriz, s_label); num_args++; 724 XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; 725 XtSetArg(args[num_args], XtNright, XtChainRight); num_args++; 726 XtSetArg(args[num_args], XtNeditType, XawtextEdit); num_args++; 727 XtSetArg(args[num_args], XtNresizable, True); num_args++; 728 XtSetArg(args[num_args], XtNstring, ptr); num_args++; 729 s_text = XtCreateManagedWidget("searchText", asciiTextWidgetClass, form, 730 args, num_args); 731 search->search_text = s_text; 732 733 num_args = 0; 734 XtSetArg(args[num_args], XtNfromVert, s_text); num_args++; 735 XtSetArg(args[num_args], XtNlabel, "Replace with:"); num_args++; 736 XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; 737 XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++; 738 XtSetArg(args[num_args], XtNborderWidth, 0); num_args++; 739 search->rep_label = XtCreateManagedWidget("replaceLabel", labelWidgetClass, 740 form, args, num_args); 741 742 num_args = 0; 743 XtSetArg(args[num_args], XtNfromHoriz, s_label); num_args++; 744 XtSetArg(args[num_args], XtNfromVert, s_text); num_args++; 745 XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; 746 XtSetArg(args[num_args], XtNright, XtChainRight); num_args++; 747 XtSetArg(args[num_args], XtNeditType, XawtextEdit); num_args++; 748 XtSetArg(args[num_args], XtNresizable, True); num_args++; 749 XtSetArg(args[num_args], XtNstring, ""); num_args++; 750 r_text = XtCreateManagedWidget("replaceText", asciiTextWidgetClass, 751 form, args, num_args); 752 search->rep_text = r_text; 753 754 num_args = 0; 755 XtSetArg(args[num_args], XtNlabel, "Search"); num_args++; 756 XtSetArg(args[num_args], XtNfromVert, r_text); num_args++; 757 XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; 758 XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++; 759 search_button = XtCreateManagedWidget("search", commandWidgetClass, form, 760 args, num_args); 761 762 num_args = 0; 763 XtSetArg(args[num_args], XtNlabel, "Replace"); num_args++; 764 XtSetArg(args[num_args], XtNfromVert, r_text); num_args++; 765 XtSetArg(args[num_args], XtNfromHoriz, search_button); num_args++; 766 XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; 767 XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++; 768 search->rep_one = XtCreateManagedWidget("replaceOne", commandWidgetClass, 769 form, args, num_args); 770 771 num_args = 0; 772 XtSetArg(args[num_args], XtNlabel, "Replace All"); num_args++; 773 XtSetArg(args[num_args], XtNfromVert, r_text); num_args++; 774 XtSetArg(args[num_args], XtNfromHoriz, search->rep_one); num_args++; 775 XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; 776 XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++; 777 search->rep_all = XtCreateManagedWidget("replaceAll", commandWidgetClass, 778 form, args, num_args); 779 780 num_args = 0; 781 XtSetArg(args[num_args], XtNlabel, "Cancel"); num_args++; 782 XtSetArg(args[num_args], XtNfromVert, r_text); num_args++; 783 XtSetArg(args[num_args], XtNfromHoriz, search->rep_all); num_args++; 784 XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; 785 XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++; 786 cancel = XtCreateManagedWidget(DISMISS_NAME, commandWidgetClass, form, 787 args, num_args); 788 789 XtAddCallback(search_button, XtNcallback, SearchButton, (XtPointer)search); 790 XtAddCallback(search->rep_one, XtNcallback, DoReplaceOne, (XtPointer)search); 791 XtAddCallback(search->rep_all, XtNcallback, DoReplaceAll, (XtPointer)search); 792 XtAddCallback(cancel, XtNcallback, PopdownSearch, (XtPointer)search); 793 794 /* 795 * Initialize the text entry fields 796 */ 797 { 798 Pixel color; 799 800 num_args = 0; 801 XtSetArg(args[num_args], XtNbackground, &color); num_args++; 802 XtGetValues(search->rep_text, args, num_args); 803 num_args = 0; 804 XtSetArg(args[num_args], XtNborderColor, color); num_args++; 805 XtSetValues(search->rep_text, args, num_args); 806 XtSetKeyboardFocus(form, search->search_text); 807 } 808 809 SetSearchLabels(search, SEARCH_LABEL_1, SEARCH_LABEL_2, False); 810 811 /* 812 * Bind Extra translations 813 */ 814 trans = XtParseTranslationTable(search_text_trans); 815 XtOverrideTranslations(search->search_text, trans); 816 817 trans = XtParseTranslationTable(rep_text_trans); 818 XtOverrideTranslations(search->rep_text, trans); 819} 820 821/* 822 * Function: 823 * DoSearch 824 * 825 * Parameters: 826 * search - search structure 827 * 828 * Description: 829 * Performs a search 830 * 831 * Returns: 832 * True if sucessful 833 */ 834/*ARGSUSED*/ 835static Bool 836DoSearch(struct SearchAndReplace *search) 837{ 838 char msg[37]; 839 Widget tw = XtParent(search->search_popup); 840 XawTextPosition pos; 841 XawTextScanDirection dir; 842 XawTextBlock text; 843 TextWidget ctx = (TextWidget)tw; 844 845 text.firstPos = 0; 846 text.ptr = GetStringRaw(search->search_text); 847 if ((text.format = _XawTextFormat(ctx)) == XawFmtWide) 848 text.length = wcslen((wchar_t*)text.ptr); 849 else { 850 text.length = strlen(text.ptr); 851 852#ifndef OLDXAW 853 if (search->case_sensitive) { 854 /* text.firstPos isn't useful here, so I'll use it as an 855 * options flag. 856 */ 857 Arg args[1]; 858 Boolean case_sensitive; 859 860 XtSetArg(args[0], XtNstate, &case_sensitive); 861 XtGetValues(search->case_sensitive, args, 1); 862 text.firstPos = !case_sensitive; 863 } 864#endif /* OLDXAW */ 865 } 866 867 dir = (XawTextScanDirection)(unsigned long) 868 ((XPointer)XawToggleGetCurrent(search->left_toggle) - R_OFFSET); 869 870 pos = XawTextSearch(tw, dir, &text); 871 872 /* The Raw string in find.ptr may be WC I can't use here, so I re - call 873 GetString to get a tame version */ 874 875 if (pos == XawTextSearchError) { 876 char *ptr; 877 int len; 878 879 ptr = GetString(search->search_text); 880 len = strlen(ptr); 881 snprintf(msg, sizeof(msg), "%s", ptr); 882 883 ptr = strchr(msg, '\n'); 884 if (ptr != NULL || sizeof(msg) - 1 < len) { 885 if (ptr != NULL) 886 len = ptr - msg + 4; 887 else 888 len = strlen(msg); 889 890 if (len < 4) 891 strcpy(msg, "..."); 892 else 893 strcpy(msg + len - 4, "..."); 894 } 895 XawTextUnsetSelection(tw); 896 SetSearchLabels(search, "Could not find string", msg, True); 897 898 return (False); 899 } 900 XawTextDisableRedisplay(tw); 901 XawTextSetSelection(tw, pos, pos + text.length); 902 search->selection_changed = False; /* selection is good */ 903 904 if (dir == XawsdRight) 905 XawTextSetInsertionPoint(tw, pos + text.length); 906 else 907 XawTextSetInsertionPoint(tw, pos); 908 _XawTextShowPosition(ctx); 909 XawTextEnableRedisplay(tw); 910 911 return (True); 912} 913 914/* 915 * This section of the file contains all the functions that 916 * the replace dialog box uses 917 */ 918/* 919 * Function: 920 * _XawTextDoReplaceAction 921 * 922 * Description: 923 * Action routine that can be bound to dialog box's 924 * Text Widget that will replace a string in the main Text Widget. 925 */ 926/*ARGSUSED*/ 927void 928_XawTextDoReplaceAction(Widget w, XEvent *event, 929 String *params, Cardinal *num_params) 930{ 931 TextWidget ctx = (TextWidget)XtParent(XtParent(XtParent(w))); 932 Bool popdown = False; 933 934 if (*num_params == 1 && (params[0][0] == 'p' || params[0][0] == 'P')) 935 popdown = True; 936 937 if (Replace( ctx->text.search, True, popdown) && popdown) 938 PopdownSearch(w, (XtPointer)ctx->text.search, NULL); 939} 940 941/* 942 * Function: 943 * DoReplaceOne 944 * 945 * Arguments: 946 * w - *** Not Used *** 947 * closure - a pointer to the search structure 948 * call_data - *** Not Used *** 949 * 950 * Description: 951 * Replaces the first instance of the string in the search 952 * dialog's text widget with the one in the replace dialog's text widget. 953 */ 954/*ARGSUSED*/ 955static void 956DoReplaceOne(Widget w, XtPointer closure, XtPointer call_data) 957{ 958 Replace((struct SearchAndReplace *)closure, True, False); 959} 960 961/* 962 * Function: 963 * DoReplaceAll 964 * 965 * Parameters: 966 * w - (not used) 967 * closure - pointer to the search structure 968 * call_data - (not used) 969 * 970 * Description: 971 * Replaces every instance of the string in the search dialog's 972 * text widget with the one in the replace dialog's text widget. 973 */ 974/*ARGSUSED*/ 975static void 976DoReplaceAll(Widget w, XtPointer closure, XtPointer call_data) 977{ 978 Replace((struct SearchAndReplace *)closure, False, False); 979} 980 981/* 982 * Function: 983 * Replace 984 * 985 * Parameters: 986 * tw - Text Widget to replce the string in 987 * once_only - if True then only replace the first one found, 988 * else replace all of them 989 * show_current - if true then leave the selection on the 990 * string that was just replaced, otherwise 991 * move it onto the next one 992 * 993 * Description: 994 * This is the function that does the real work of 995 * replacing strings in the main text widget. 996 */ 997static Bool 998Replace(struct SearchAndReplace *search, Bool once_only, Bool show_current) 999{ 1000 XawTextPosition pos, new_pos, end_pos, ipos; 1001 XawTextScanDirection dir; 1002 XawTextBlock find, replace; 1003 Widget tw = XtParent(search->search_popup); 1004 int count = 0; 1005 TextWidget ctx = (TextWidget)tw; 1006 Bool redisplay; 1007 1008 find.ptr = GetStringRaw(search->search_text); 1009 if ((find.format = _XawTextFormat(ctx)) == XawFmtWide) 1010 find.length = (XawTextPosition)wcslen((wchar_t*)find.ptr); 1011 else 1012 find.length = (XawTextPosition)strlen(find.ptr); 1013 find.firstPos = 0; 1014 1015 replace.ptr = GetStringRaw(search->rep_text); 1016 replace.firstPos = 0; 1017 if ((replace.format = _XawTextFormat(ctx)) == XawFmtWide) 1018 replace.length = wcslen((wchar_t*)replace.ptr); 1019 else 1020 replace.length = strlen(replace.ptr); 1021 1022 dir = (XawTextScanDirection)(unsigned long) 1023 ((XPointer)XawToggleGetCurrent(search->left_toggle) - R_OFFSET); 1024 1025 redisplay = !once_only || (once_only && !show_current); 1026 ipos = XawTextGetInsertionPoint(tw); 1027 if (redisplay) 1028 XawTextDisableRedisplay(tw); 1029 /*CONSTCOND*/ 1030 while (True) { 1031 if (count != 0) { 1032 new_pos = XawTextSearch(tw, dir, &find); 1033 1034 if (new_pos == XawTextSearchError) { 1035 if (count == 0) { 1036 char msg[37]; 1037 char *ptr; 1038 int len; 1039 1040 ptr = GetString(search->search_text); 1041 len = strlen(ptr); 1042 snprintf(msg, sizeof(msg), "%s", ptr); 1043 ptr = strchr(msg, '\n'); 1044 if (ptr != NULL || sizeof(msg) - 1 < len) { 1045 if (ptr != NULL) 1046 len = ptr - msg + 4; 1047 else 1048 len = strlen(msg); 1049 1050 if (len < 4) 1051 strcpy(msg, "..."); 1052 else 1053 strcpy(msg + len - 4, "..."); 1054 } 1055 SetSearchLabels(search, "Could not find string", msg, True); 1056 1057 if (redisplay) { 1058 XawTextSetInsertionPoint(tw, ipos); 1059 _XawTextShowPosition(ctx); 1060 XawTextEnableRedisplay(tw); 1061 } 1062 1063 return (False); 1064 } 1065 else 1066 break; 1067 } 1068 pos = new_pos; 1069 end_pos = pos + find.length; 1070 } 1071 else { 1072 XawTextGetSelectionPos(tw, &pos, &end_pos); 1073 1074 if (search->selection_changed) { 1075 SetSearchLabels(search, "Selection modified, aborting.", 1076 "", True); 1077 if (redisplay) { 1078 XawTextSetInsertionPoint(tw, ipos); 1079 XawTextEnableRedisplay(tw); 1080 } 1081 1082 return (False); 1083 } 1084 if (pos == end_pos) { 1085 if (redisplay) { 1086 XawTextSetInsertionPoint(tw, ipos); 1087 XawTextEnableRedisplay(tw); 1088 } 1089 1090 return (False); 1091 } 1092 } 1093 1094 if (XawTextReplace(tw, pos, end_pos, &replace) != XawEditDone) { 1095 SetSearchLabels(search, "Error while replacing.", "", True); 1096 if (redisplay) { 1097 XawTextSetInsertionPoint(tw, ipos); 1098 XawTextEnableRedisplay(tw); 1099 } 1100 1101 return (False); 1102 } 1103 1104 if (dir == XawsdRight) 1105 ipos = pos + replace.length; 1106 else 1107 ipos = pos; 1108 1109 if (once_only) { 1110 if (show_current) 1111 break; 1112 else { 1113 DoSearch(search); 1114 XawTextEnableRedisplay(tw); 1115 1116 return (True); 1117 } 1118 } 1119 else 1120 ctx->text.insertPos = ipos; 1121 count++; 1122 } 1123 1124 if (replace.length == 0) 1125 XawTextUnsetSelection(tw); 1126 else 1127 XawTextSetSelection(tw, pos, pos + replace.length); 1128 1129 XawTextSetInsertionPoint(tw, ipos); 1130 _XawTextShowPosition(ctx); 1131 XawTextEnableRedisplay(tw); 1132 1133 return (True); 1134} 1135 1136/* 1137 * Function: 1138 * SetSearchLabels 1139 * 1140 * Parameters: 1141 * search - search structure 1142 * msg1 - message to put in each search label 1143 * msg2 - "" 1144 * bell - if True then ring bell 1145 * 1146 * Description: 1147 * Sets both the search labels, and also rings the bell. 1148 */ 1149static void 1150SetSearchLabels(struct SearchAndReplace *search, String msg1, String msg2, 1151 Bool bell) 1152{ 1153 (void)SetResource(search->label1, XtNlabel, (XtArgVal)msg1); 1154 (void)SetResource(search->label2, XtNlabel, (XtArgVal)msg2); 1155 if (bell) 1156 XBell(XtDisplay(search->search_popup), 0); 1157} 1158 1159/* 1160 * This section of the file contains utility routines used by 1161 * other functions in this file 1162 */ 1163/* 1164 * Function: 1165 * _XawTextSetField 1166 * 1167 * Description: 1168 * Action routine that can be bound to dialog box's 1169 * Text Widget that will send input to the field specified. 1170 */ 1171/*ARGSUSED*/ 1172void 1173_XawTextSetField(Widget w, XEvent *event, String *params, Cardinal *num_params) 1174{ 1175 struct SearchAndReplace *search; 1176 Widget cnew, old; 1177 1178 search = ((TextWidget)XtParent(XtParent(XtParent(w))))->text.search; 1179 1180 if (*num_params != 1) { 1181 SetSearchLabels(search, "Error: SetField Action must have", 1182 "exactly one argument", True); 1183 return; 1184 } 1185 switch (params[0][0]) { 1186 case 's': 1187 case 'S': 1188 cnew = search->search_text; 1189 old = search->rep_text; 1190 break; 1191 case 'r': 1192 case 'R': 1193 old = search->search_text; 1194 cnew = search->rep_text; 1195 break; 1196 default: 1197 SetSearchLabels(search, 1198 "Error: SetField Action's first Argument must", 1199 "be either 'Search' or 'Replace'", True); 1200 return; 1201 } 1202 _SetField(cnew, old); 1203} 1204 1205/* 1206 * Function: 1207 * _SetField 1208 * 1209 * Parameters: 1210 * cnew - new and old text fields 1211 * old - "" 1212 * 1213 * Description: 1214 * Sets the current text field. 1215 */ 1216static void 1217_SetField(Widget cnew, Widget old) 1218{ 1219 Arg args[2]; 1220 Pixel new_border, old_border, old_bg; 1221 1222 if (!XtIsSensitive(cnew)) { 1223 XBell(XtDisplay(old), 0); /* Don't set field to an inactive Widget */ 1224 return; 1225 } 1226 1227 XtSetKeyboardFocus(XtParent(cnew), cnew); 1228 1229 XtSetArg(args[0], XtNborderColor, &old_border); 1230 XtSetArg(args[1], XtNbackground, &old_bg); 1231 XtGetValues(cnew, args, 2); 1232 1233 XtSetArg(args[0], XtNborderColor, &new_border); 1234 XtGetValues(old, args, 1); 1235 1236 if (old_border != old_bg) /* Colors are already correct, return */ 1237 return; 1238 1239 SetResource(old, XtNborderColor, (XtArgVal)old_border); 1240 SetResource(cnew, XtNborderColor, (XtArgVal)new_border); 1241} 1242 1243/* 1244 * Function: 1245 * SetResourceByName 1246 * 1247 * Parameters: 1248 * shell - shell widget of the popup 1249 * name - name of the child 1250 * res_name - name of the resource 1251 * value - value of the resource 1252 * 1253 * Description: 1254 * Sets a resource in any of the dialog children given 1255 * name of the child and the shell widget of the dialog. 1256 * 1257 * Returns: 1258 * True if sucessful 1259 */ 1260static Bool 1261SetResourceByName(Widget shell, char *name, char *res_name, XtArgVal value) 1262{ 1263 Widget temp_widget; 1264 char buf[BUFSIZ]; 1265 1266 snprintf(buf, sizeof(buf), "%s.%s", FORM_NAME, name); 1267 1268 if ((temp_widget = XtNameToWidget(shell, buf)) != NULL) { 1269 SetResource(temp_widget, res_name, value); 1270 return (True); 1271 } 1272 return (False); 1273} 1274 1275/* 1276 * Function: 1277 * SetResource 1278 * 1279 * Parameters: 1280 * w - widget 1281 * res_name - name of the resource 1282 * value - value of the resource 1283 * 1284 * Description: 1285 * Sets a resource in a widget 1286 */ 1287static void 1288SetResource(Widget w, char *res_name, XtArgVal value) 1289{ 1290 Arg args[1]; 1291 1292 XtSetArg(args[0], res_name, value); 1293 XtSetValues( w, args, 1); 1294} 1295 1296/* 1297 * Function: 1298 * GetString{Raw} 1299 * 1300 * Parameters: 1301 * text - text widget whose string we will get 1302 * 1303 * Description: 1304 * Gets the value for the string in the popup. 1305 * 1306 * Returns: 1307 * GetString: the string as a MB 1308 * GetStringRaw: the exact buffer contents suitable for a search 1309 */ 1310static String 1311GetString(Widget text) 1312{ 1313 String string; 1314 Arg args[1]; 1315 1316 XtSetArg(args[0], XtNstring, &string); 1317 XtGetValues(text, args, 1); 1318 1319 return (string); 1320} 1321 1322static String 1323GetStringRaw(Widget tw) 1324{ 1325 TextWidget ctx = (TextWidget)tw; 1326 XawTextPosition last; 1327 1328 last = XawTextSourceScan(ctx->text.source, 0, XawstAll, XawsdRight, 1329 ctx->text.mult, True); 1330 return (_XawTextGetText(ctx, 0, last)); 1331} 1332 1333/* 1334 * Function: 1335 * CenterWidgetOnPoint 1336 * 1337 * Parameters: 1338 * w - shell widget 1339 * event - event containing the location of the point 1340 * 1341 * Description: 1342 * Centers a shell widget on a point relative to the root window. 1343 * 1344 * Note: 1345 * The widget is not allowed to go off the screen 1346 */ 1347static void 1348CenterWidgetOnPoint(Widget w, XEvent *event) 1349{ 1350 Arg args[3]; 1351 Cardinal num_args; 1352 Dimension width, height, b_width; 1353 Position x, y, max_x, max_y; 1354 1355 if (event != NULL) { 1356 switch (event->type) { 1357 case ButtonPress: 1358 case ButtonRelease: 1359 x = event->xbutton.x_root; 1360 y = event->xbutton.y_root; 1361 break; 1362 case KeyPress: 1363 case KeyRelease: 1364 x = event->xkey.x_root; 1365 y = event->xkey.y_root; 1366 break; 1367 default: 1368 return; 1369 } 1370 } 1371 else 1372 return; 1373 1374 num_args = 0; 1375 XtSetArg(args[num_args], XtNwidth, &width); num_args++; 1376 XtSetArg(args[num_args], XtNheight, &height); num_args++; 1377 XtSetArg(args[num_args], XtNborderWidth, &b_width); num_args++; 1378 XtGetValues(w, args, num_args); 1379 1380 width += b_width << 1; 1381 height += b_width << 1; 1382 1383 x -= (Position)(width >> 1); 1384 if (x < 0) 1385 x = 0; 1386 if (x > (max_x = (Position)(XtScreen(w)->width - width))) 1387 x = max_x; 1388 1389 y -= (Position)(height >> 1); 1390 if (y < 0) 1391 y = 0; 1392 if (y > (max_y = (Position)(XtScreen(w)->height - height))) 1393 y = max_y; 1394 1395 num_args = 0; 1396 XtSetArg(args[num_args], XtNx, x); num_args++; 1397 XtSetArg(args[num_args], XtNy, y); num_args++; 1398 XtSetValues(w, args, num_args); 1399} 1400 1401/* 1402 * Function: 1403 * CreateDialog 1404 * 1405 * Parameters: 1406 * parent - parent of the dialog - the main text widget 1407 * ptr - initial_string for the dialog 1408 * name - name of the dialog 1409 * func - function to create the children of the dialog 1410 * 1411 * Returns: 1412 * Popup shell of the dialog 1413 * 1414 * Note: 1415 * The function argument is passed the following arguments: 1416 * form - from widget that is the dialog 1417 * ptr - initial string for the dialog's text widget 1418 * parent - parent of the dialog - the main text widget 1419 */ 1420static Widget 1421CreateDialog(Widget parent, String ptr, String name, AddFunc func) 1422{ 1423 Widget popup, form; 1424 Arg args[5]; 1425 Cardinal num_args; 1426 1427 num_args = 0; 1428 XtSetArg(args[num_args], XtNiconName, name); num_args++; 1429 XtSetArg(args[num_args], XtNgeometry, NULL); num_args++; 1430 XtSetArg(args[num_args], XtNallowShellResize, True); num_args++; 1431 XtSetArg(args[num_args], XtNtransientFor, GetShell(parent));num_args++; 1432 popup = XtCreatePopupShell(name, transientShellWidgetClass, 1433 parent, args, num_args); 1434 1435 form = XtCreateManagedWidget(FORM_NAME, formWidgetClass, popup, NULL, 0); 1436 XtManageChild (form); 1437 1438 (*func)(form, ptr, parent); 1439 1440 return (popup); 1441} 1442 1443/* 1444 * Function 1445 * GetShell 1446 * nearest shell widget. 1447 * 1448 * Parameters: 1449 * w - widget whose parent shell should be returned 1450 * 1451 * Returns: 1452 * The shell widget among the ancestors of w that is the 1453 * fewest levels up in the widget hierarchy. 1454 * 1455 * Description: 1456 * Walks up the widget hierarchy to find the topmost shell widget. 1457 */ 1458static Widget 1459GetShell(Widget w) 1460{ 1461 while (w != NULL && !XtIsShell(w)) 1462 w = XtParent(w); 1463 1464 return (w); 1465} 1466 1467static Bool 1468InParams(String str, String *p, unsigned int n) 1469{ 1470 unsigned int i; 1471 1472 for (i = 0; i < n; p++, i++) 1473 if (!XmuCompareISOLatin1(*p, str)) 1474 return (True); 1475 return (False); 1476} 1477 1478static char *WM_DELETE_WINDOW = "WM_DELETE_WINDOW"; 1479 1480static void 1481WMProtocols(Widget w, XEvent *event, String *params, Cardinal *num_params) 1482{ 1483 Atom wm_delete_window; 1484 Atom wm_protocols; 1485 1486 wm_delete_window = XInternAtom(XtDisplay(w), WM_DELETE_WINDOW, True); 1487 wm_protocols = XInternAtom(XtDisplay(w), "WM_PROTOCOLS", True); 1488 1489 /* Respond to a recognized WM protocol request if 1490 * event type is ClientMessage and no parameters are passed, or 1491 * event type is ClientMessage and event data is matched to parameters, or 1492 * event type isn't ClientMessage and parameters make a request 1493 */ 1494#define DO_DELETE_WINDOW InParams(WM_DELETE_WINDOW, params, *num_params) 1495 1496 if ((event->type == ClientMessage 1497 && event->xclient.message_type == wm_protocols 1498 && event->xclient.data.l[0] == wm_delete_window 1499 && (*num_params == 0 || DO_DELETE_WINDOW)) 1500 || (event->type != ClientMessage && DO_DELETE_WINDOW)) { 1501#undef DO_DELETE_WINDOW 1502 Widget cancel; 1503 char descendant[DISMISS_NAME_LEN + 2]; 1504 1505 snprintf(descendant, sizeof(descendant), "*%s", DISMISS_NAME); 1506 cancel = XtNameToWidget(w, descendant); 1507 if (cancel) 1508 XtCallCallbacks(cancel, XtNcallback, NULL); 1509 } 1510} 1511 1512static void 1513SetWMProtocolTranslations(Widget w) 1514{ 1515 static XtTranslations compiled_table; 1516 static XtAppContext *app_context_list; 1517 static Cardinal list_size; 1518 1519 unsigned int i; 1520 XtAppContext app_context; 1521 Atom wm_delete_window; 1522 1523 app_context = XtWidgetToApplicationContext(w); 1524 1525 /* parse translation table once */ 1526 if (!compiled_table) 1527 compiled_table = 1528 XtParseTranslationTable("<Message>WM_PROTOCOLS:XawWMProtocols()\n"); 1529 1530 /* add actions once per application context */ 1531 for (i = 0; i < list_size && app_context_list[i] != app_context; i++) 1532 ; 1533 if (i == list_size) { 1534 XtActionsRec actions[1]; 1535 1536 actions[0].string = "XawWMProtocols"; 1537 actions[0].proc = WMProtocols; 1538 list_size++; 1539 app_context_list = (XtAppContext *)XtRealloc 1540 ((char *)app_context_list, list_size * sizeof(XtAppContext)); 1541 XtAppAddActions(app_context, actions, 1); 1542 app_context_list[i] = app_context; 1543 } 1544 1545 /* establish communication between the window manager and each shell */ 1546 XtAugmentTranslations(w, compiled_table); 1547 wm_delete_window = XInternAtom(XtDisplay(w), WM_DELETE_WINDOW, False); 1548 (void)XSetWMProtocols(XtDisplay(w), XtWindow(w), &wm_delete_window, 1); 1549} 1550