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