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