UNIXworkcode

1 /******************************************************************************* 2 * * 3 * windowTitle.c -- Nirvana Editor window title customization * 4 * * 5 * Copyright (C) 2001, Arne Forlie * 6 * * 7 * This is free software; you can redistribute it and/or modify it under the * 8 * terms of the GNU General Public License as published by the Free Software * 9 * Foundation; either version 2 of the License, or (at your option) any later * 10 * version. In addition, you may distribute versions of this program linked to * 11 * Motif or Open Motif. See README for details. * 12 * * 13 * This software is distributed in the hope that it will be useful, but WITHOUT * 14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * 15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * 16 * more details. * 17 * * 18 * You should have received a copy of the GNU General Public License along with * 19 * software; if not, write to the Free Software Foundation, Inc., 59 Temple * 20 * Place, Suite 330, Boston, MA 02111-1307 USA * 21 * * 22 * Nirvana Text Editor * 23 * July 31, 2001 * 24 * * 25 * Written by Arne Forlie, http://arne.forlie.com * 26 * * 27 *******************************************************************************/ 28 29 #ifdef HAVE_CONFIG_H 30 #include "../config.h" 31 #endif 32 33 #include "windowTitle.h" 34 #include "textBuf.h" 35 #include "nedit.h" 36 #include "preferences.h" 37 #include "help.h" 38 #include "../util/prefFile.h" 39 #include "../util/misc.h" 40 #include "../util/DialogF.h" 41 #include "../util/utils.h" 42 #include "../util/fileUtils.h" 43 #include "../util/nedit_malloc.h" 44 45 #include <stdlib.h> 46 #include <stdio.h> 47 #include <ctype.h> 48 #include <string.h> 49 #include <sys/param.h> 50 #include "../util/clearcase.h" 51 52 #include <Xm/Xm.h> 53 #include <Xm/SelectioB.h> 54 #include <Xm/Form.h> 55 #include <Xm/List.h> 56 #include <Xm/SeparatoG.h> 57 #include <Xm/LabelG.h> 58 #include <Xm/PushBG.h> 59 #include <Xm/PushB.h> 60 #include <Xm/ToggleBG.h> 61 #include <Xm/ToggleB.h> 62 #include <Xm/RowColumn.h> 63 #include <Xm/CascadeBG.h> 64 #include <Xm/Frame.h> 65 #include <Xm/Text.h> 66 #include <Xm/TextF.h> 67 68 #ifdef HAVE_DEBUG_H 69 #include "../debug.h" 70 #endif 71 72 73 #define WINDOWTITLE_MAX_LEN 500 74 75 /* Customize window title dialog information */ 76 static struct { 77 Widget form; 78 Widget shell; 79 WindowInfo* window; 80 Widget previewW; 81 Widget formatW; 82 83 Widget ccW; 84 Widget fileW; 85 Widget hostW; 86 Widget dirW; 87 Widget statusW; 88 Widget shortStatusW; 89 Widget serverW; 90 Widget nameW; 91 Widget mdirW; 92 Widget ndirW; 93 Widget encW; 94 95 Widget oDirW; 96 Widget oCcViewTagW; 97 Widget oServerNameW; 98 Widget oFileChangedW; 99 Widget oFileLockedW; 100 Widget oFileReadOnlyW; 101 Widget oServerEqualViewW; 102 103 char filename[MAXPATHLEN]; 104 char path[MAXPATHLEN]; 105 char viewTag[MAXPATHLEN]; 106 char serverName[MAXPATHLEN]; 107 int isServer; 108 int filenameSet; 109 int lockReasons; 110 int fileChanged; 111 112 int suppressFormatUpdate; 113 } etDialog = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, 114 NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, 115 NULL,NULL,NULL,"","","","",0,0,0,0,0}; 116 117 118 119 static char* removeSequence(char* sourcePtr, char c) 120 { 121 while (*sourcePtr == c) { 122 sourcePtr++; 123 } 124 return(sourcePtr); 125 } 126 127 128 /* 129 ** Two functions for performing safe insertions into a finite 130 ** size buffer so that we don't get any memory overruns. 131 */ 132 static char* safeStrCpy(char* dest, char* destEnd, const char* source) 133 { 134 int len = (int)strlen(source); 135 if (len <= (destEnd - dest)) { 136 strcpy(dest, source); 137 return(dest + len); 138 } 139 else { 140 strncpy(dest, source, destEnd - dest); 141 *destEnd = '\0'; 142 return(destEnd); 143 } 144 } 145 146 static char* safeCharAdd(char* dest, const char* destEnd, char c) 147 { 148 if (destEnd - dest > 0) 149 { 150 *dest++ = c; 151 *dest = '\0'; 152 } 153 return(dest); 154 } 155 156 /* 157 ** Remove empty paranthesis pairs and multiple spaces in a row 158 ** with one space. 159 ** Also remove leading and trailing spaces and dashes. 160 */ 161 static void compressWindowTitle(char *title) 162 { 163 /* Compress the title */ 164 int modified; 165 do { 166 char *sourcePtr = title; 167 char *destPtr = sourcePtr; 168 char c = *sourcePtr++; 169 170 modified = False; 171 172 /* Remove leading spaces and dashes */ 173 while (c == ' ' || c == '-') { 174 c= *sourcePtr++; 175 } 176 177 /* Remove empty constructs */ 178 while (c != '\0') { 179 switch (c) { 180 /* remove sequences */ 181 case ' ': 182 case '-': 183 sourcePtr = removeSequence(sourcePtr, c); 184 *destPtr++ = c; /* leave one */ 185 break; 186 187 /* remove empty paranthesis pairs */ 188 case '(': 189 if (*sourcePtr == ')') { 190 modified = True; 191 sourcePtr++; 192 } 193 else *destPtr++ = c; 194 sourcePtr = removeSequence(sourcePtr, ' '); 195 break; 196 197 case '[': 198 if (*sourcePtr == ']') { 199 modified = True; 200 sourcePtr++; 201 } 202 else *destPtr++ = c; 203 sourcePtr = removeSequence(sourcePtr, ' '); 204 break; 205 206 case '{': 207 if (*sourcePtr == '}') { 208 modified = True; 209 sourcePtr++; 210 } 211 else *destPtr++ = c; 212 sourcePtr = removeSequence(sourcePtr, ' '); 213 break; 214 215 default: 216 *destPtr++ = c; 217 break; 218 } 219 c = *sourcePtr++; 220 *destPtr = '\0'; 221 } 222 223 /* Remove trailing spaces and dashes */ 224 while (destPtr-- > title) { 225 if (*destPtr != ' ' && *destPtr != '-') 226 break; 227 *destPtr = '\0'; 228 } 229 } while (modified == True); 230 } 231 232 233 /* 234 ** Format the windows title using a printf like formatting string. 235 ** The following flags are recognised: 236 ** %c : ClearCase view tag 237 ** %s : server name 238 ** %[n]d : directory, with one optional digit specifying the max number 239 ** of trailing directory components to display. Skipped components are 240 ** replaced by an ellipsis (...). 241 ** %f : file name 242 ** %h : host name 243 ** %S : file status 244 ** %u : user name 245 ** %e : file encoding 246 ** 247 ** if the ClearCase view tag and server name are identical, only the first one 248 ** specified in the formatting string will be displayed. 249 */ 250 char *FormatWindowTitle(const char* filename, 251 const char* path, 252 const char* clearCaseViewTag, 253 const char* serverName, 254 const char* encoding, 255 int isServer, 256 int filenameSet, 257 int lockReasons, 258 int fileChanged, 259 const char* titleFormat) 260 { 261 static char title[WINDOWTITLE_MAX_LEN]; 262 title[WINDOWTITLE_MAX_LEN-1] = 0; 263 char *titlePtr = title; 264 char* titleEnd = title + WINDOWTITLE_MAX_LEN - 1; 265 266 267 /* Flags to supress one of these if both are specified and they are identical */ 268 int serverNameSeen = False; 269 int clearCaseViewTagSeen = False; 270 271 int fileNamePresent = False; 272 int hostNamePresent = False; 273 int userNamePresent = False; 274 int serverNamePresent = False; 275 int clearCasePresent = False; 276 int encodingPresent = False; 277 int fileStatusPresent = False; 278 int dirNamePresent = False; 279 int noOfComponents = -1; 280 int shortStatus = False; 281 size_t enc_len = 0; 282 const char *enc = NULL; 283 284 *titlePtr = '\0'; /* always start with an empty string */ 285 286 while (*titleFormat != '\0' && titlePtr < titleEnd) { 287 char c = *titleFormat++; 288 if (c == '%') { 289 c = *titleFormat++; 290 if (c == '\0') 291 { 292 titlePtr = safeCharAdd(titlePtr, titleEnd, '%'); 293 break; 294 } 295 switch (c) { 296 case 'c': /* ClearCase view tag */ 297 clearCasePresent = True; 298 if (clearCaseViewTag != NULL) { 299 if (serverNameSeen == False || 300 strcmp(serverName, clearCaseViewTag) != 0) { 301 titlePtr = safeStrCpy(titlePtr, titleEnd, clearCaseViewTag); 302 clearCaseViewTagSeen = True; 303 } 304 } 305 break; 306 307 case 's': /* server name */ 308 serverNamePresent = True; 309 if (isServer && serverName[0] != '\0') { /* only applicable for servers */ 310 if (clearCaseViewTagSeen == False || 311 strcmp(serverName, clearCaseViewTag) != 0) { 312 titlePtr = safeStrCpy(titlePtr, titleEnd, serverName); 313 serverNameSeen = True; 314 } 315 } 316 break; 317 318 case 'd': /* directory without any limit to no. of components */ 319 dirNamePresent = True; 320 if (filenameSet) { 321 titlePtr = safeStrCpy(titlePtr, titleEnd, path); 322 } 323 break; 324 case 'e': /* file encoding */ 325 encodingPresent = True; 326 enc_len = encoding ? strlen(encoding) : 0; 327 enc = encoding; 328 if(enc_len == 0) { 329 enc = GetPrefDefaultCharset(); 330 } 331 titlePtr = safeStrCpy(titlePtr, titleEnd, enc); 332 break; 333 case '0': /* directory with limited no. of components */ 334 case '1': 335 case '2': 336 case '3': 337 case '4': 338 case '5': 339 case '6': 340 case '7': 341 case '8': 342 case '9': 343 if (*titleFormat == 'd') { 344 dirNamePresent = True; 345 noOfComponents = c - '0'; 346 titleFormat++; /* delete the argument */ 347 348 if (filenameSet) { 349 const char* trailingPath = GetTrailingPathComponents(path, 350 noOfComponents); 351 352 /* prefix with ellipsis if components were skipped */ 353 if (trailingPath > path) { 354 titlePtr = safeStrCpy(titlePtr, titleEnd, "..."); 355 } 356 titlePtr = safeStrCpy(titlePtr, titleEnd, trailingPath); 357 } 358 } 359 break; 360 361 case 'f': /* file name */ 362 fileNamePresent = True; 363 titlePtr = safeStrCpy(titlePtr, titleEnd, filename); 364 break; 365 366 case 'h': /* host name */ 367 hostNamePresent = True; 368 titlePtr = safeStrCpy(titlePtr, titleEnd, GetNameOfHost()); 369 break; 370 371 case 'S': /* file status */ 372 fileStatusPresent = True; 373 if (IS_ANY_LOCKED_IGNORING_USER(lockReasons) && fileChanged) 374 titlePtr = safeStrCpy(titlePtr, titleEnd, "read only, modified"); 375 else if (IS_ANY_LOCKED_IGNORING_USER(lockReasons)) 376 titlePtr = safeStrCpy(titlePtr, titleEnd, "read only"); 377 else if (IS_USER_LOCKED(lockReasons) && fileChanged) 378 titlePtr = safeStrCpy(titlePtr, titleEnd, "locked, modified"); 379 else if (IS_USER_LOCKED(lockReasons)) 380 titlePtr = safeStrCpy(titlePtr, titleEnd, "locked"); 381 else if (fileChanged) 382 titlePtr = safeStrCpy(titlePtr, titleEnd, "modified"); 383 break; 384 385 case 'u': /* user name */ 386 userNamePresent = True; 387 titlePtr = safeStrCpy(titlePtr, titleEnd, GetUserName()); 388 break; 389 390 case '%': /* escaped % */ 391 titlePtr = safeCharAdd(titlePtr, titleEnd, '%'); 392 break; 393 394 case '*': /* short file status ? */ 395 fileStatusPresent = True; 396 if (*titleFormat == 'S') 397 { 398 ++titleFormat; 399 shortStatus = True; 400 if (IS_ANY_LOCKED_IGNORING_USER(lockReasons) && fileChanged) 401 titlePtr = safeStrCpy(titlePtr, titleEnd, "RO*"); 402 else if (IS_ANY_LOCKED_IGNORING_USER(lockReasons)) 403 titlePtr = safeStrCpy(titlePtr, titleEnd, "RO"); 404 else if (IS_USER_LOCKED(lockReasons) && fileChanged) 405 titlePtr = safeStrCpy(titlePtr, titleEnd, "LO*"); 406 else if (IS_USER_LOCKED(lockReasons)) 407 titlePtr = safeStrCpy(titlePtr, titleEnd, "LO"); 408 else if (fileChanged) 409 titlePtr = safeStrCpy(titlePtr, titleEnd, "*"); 410 break; 411 } 412 /* fall-through */ 413 default: 414 titlePtr = safeCharAdd(titlePtr, titleEnd, c); 415 break; 416 } 417 } 418 else { 419 titlePtr = safeCharAdd(titlePtr, titleEnd, c); 420 } 421 } 422 423 compressWindowTitle(title); 424 425 if (title[0] == 0) 426 { 427 snprintf(&title[0], WINDOWTITLE_MAX_LEN-1, "<empty>"); /* For preview purposes only */ 428 } 429 430 if (etDialog.form) 431 { 432 /* Prevent recursive callback loop */ 433 etDialog.suppressFormatUpdate = True; 434 435 /* Sync radio buttons with format string (in case the user entered 436 the format manually) */ 437 XmToggleButtonSetState(etDialog.fileW, fileNamePresent, False); 438 XmToggleButtonSetState(etDialog.statusW, fileStatusPresent, False); 439 XmToggleButtonSetState(etDialog.serverW, serverNamePresent, False); 440 XmToggleButtonSetState(etDialog.ccW, clearCasePresent, False); 441 XmToggleButtonSetState(etDialog.encW, encodingPresent, False); 442 XmToggleButtonSetState(etDialog.dirW, dirNamePresent, False); 443 XmToggleButtonSetState(etDialog.hostW, hostNamePresent, False); 444 XmToggleButtonSetState(etDialog.nameW, userNamePresent, False); 445 446 XtSetSensitive(etDialog.shortStatusW, fileStatusPresent); 447 if (fileStatusPresent) 448 { 449 XmToggleButtonSetState(etDialog.shortStatusW, shortStatus, False); 450 } 451 452 /* Directory components are also sensitive to presence of dir */ 453 XtSetSensitive(etDialog.ndirW, dirNamePresent); 454 XtSetSensitive(etDialog.mdirW, dirNamePresent); 455 456 if (dirNamePresent) /* Avoid erasing number when not active */ 457 { 458 if (noOfComponents >= 0) 459 { 460 char* value = XmTextGetString(etDialog.ndirW); 461 char buf[16]; 462 snprintf(&buf[0], 16, "%d", noOfComponents); 463 if (strcmp(&buf[0], value)) /* Don't overwrite unless diff. */ 464 SetIntText(etDialog.ndirW, noOfComponents); 465 NEditFree(value); 466 } 467 else 468 { 469 XmTextSetString(etDialog.ndirW, ""); 470 } 471 } 472 473 /* Enable/disable test buttons, depending on presence of codes */ 474 XtSetSensitive(etDialog.oFileChangedW, fileStatusPresent); 475 XtSetSensitive(etDialog.oFileReadOnlyW, fileStatusPresent); 476 XtSetSensitive(etDialog.oFileLockedW, fileStatusPresent && 477 !IS_PERM_LOCKED(etDialog.lockReasons)); 478 479 XtSetSensitive(etDialog.oServerNameW, serverNamePresent); 480 481 #ifndef VMS 482 XtSetSensitive(etDialog.oCcViewTagW, clearCasePresent); 483 XtSetSensitive(etDialog.oServerEqualViewW, clearCasePresent && 484 serverNamePresent); 485 #endif /* VMS */ 486 487 XtSetSensitive(etDialog.oDirW, dirNamePresent); 488 489 etDialog.suppressFormatUpdate = False; 490 } 491 492 return(title); 493 } 494 495 496 497 /* a utility that sets the values of all toggle buttons */ 498 static void setToggleButtons(void) 499 { 500 XmToggleButtonSetState(etDialog.oDirW, 501 etDialog.filenameSet == True, False); 502 XmToggleButtonSetState(etDialog.oFileChangedW, 503 etDialog.fileChanged == True, False); 504 XmToggleButtonSetState(etDialog.oFileReadOnlyW, 505 IS_PERM_LOCKED(etDialog.lockReasons), False); 506 XmToggleButtonSetState(etDialog.oFileLockedW, 507 IS_USER_LOCKED(etDialog.lockReasons), False); 508 /* Read-only takes precedence on locked */ 509 XtSetSensitive(etDialog.oFileLockedW, !IS_PERM_LOCKED(etDialog.lockReasons)); 510 511 #ifdef VMS 512 XmToggleButtonSetState(etDialog.oServerNameW, etDialog.isServer, False); 513 #else 514 XmToggleButtonSetState(etDialog.oCcViewTagW, 515 GetClearCaseViewTag() != NULL, False); 516 XmToggleButtonSetState(etDialog.oServerNameW, 517 etDialog.isServer, False); 518 519 if (GetClearCaseViewTag() != NULL && etDialog.isServer 520 && GetPrefServerName()[0] != '\0' 521 && strcmp(GetClearCaseViewTag(), GetPrefServerName()) == 0) { 522 XmToggleButtonSetState(etDialog.oServerEqualViewW, True, False); 523 } else { 524 XmToggleButtonSetState(etDialog.oServerEqualViewW, False, False); 525 } 526 #endif /* VMS */ 527 } 528 529 static void formatChangedCB(Widget w, XtPointer clientData, XtPointer callData) 530 { 531 char *format; 532 int filenameSet = XmToggleButtonGetState(etDialog.oDirW); 533 char *title; 534 const char* serverName; 535 536 if (etDialog.suppressFormatUpdate) 537 { 538 return; /* Prevent recursive feedback */ 539 } 540 541 format = XmTextGetString(etDialog.formatW); 542 543 #ifndef VMS 544 if (XmToggleButtonGetState(etDialog.oServerEqualViewW) && 545 XmToggleButtonGetState(etDialog.ccW)) { 546 serverName = etDialog.viewTag; 547 } else 548 #endif /* VMS */ 549 { 550 serverName = XmToggleButtonGetState(etDialog.oServerNameW) ? 551 etDialog.serverName : ""; 552 } 553 554 title = FormatWindowTitle( 555 etDialog.filename, 556 etDialog.filenameSet == True ? 557 etDialog.path : 558 "/a/very/long/path/used/as/example/", 559 XmToggleButtonGetState(etDialog.oCcViewTagW) ? 560 etDialog.viewTag : NULL, 561 serverName, 562 NULL, 563 etDialog.isServer, 564 filenameSet, 565 etDialog.lockReasons, 566 XmToggleButtonGetState(etDialog.oFileChangedW), 567 format); 568 NEditFree(format); 569 XmTextFieldSetString(etDialog.previewW, title); 570 } 571 572 #ifndef VMS 573 static void ccViewTagCB(Widget w, XtPointer clientData, XtPointer callData) 574 { 575 if (XmToggleButtonGetState(w) == False) { 576 XmToggleButtonSetState(etDialog.oServerEqualViewW, False, False); 577 } 578 formatChangedCB(w, clientData, callData); 579 } 580 #endif /* VMS */ 581 582 static void serverNameCB(Widget w, XtPointer clientData, XtPointer callData) 583 { 584 if (XmToggleButtonGetState(w) == False) { 585 XmToggleButtonSetState(etDialog.oServerEqualViewW, False, False); 586 } 587 etDialog.isServer = XmToggleButtonGetState(w); 588 formatChangedCB(w, clientData, callData); 589 } 590 591 static void fileChangedCB(Widget w, XtPointer clientData, XtPointer callData) 592 { 593 etDialog.fileChanged = XmToggleButtonGetState(w); 594 formatChangedCB(w, clientData, callData); 595 } 596 597 static void fileLockedCB(Widget w, XtPointer clientData, XtPointer callData) 598 { 599 SET_USER_LOCKED(etDialog.lockReasons, XmToggleButtonGetState(w)); 600 formatChangedCB(w, clientData, callData); 601 } 602 603 static void fileReadOnlyCB(Widget w, XtPointer clientData, XtPointer callData) 604 { 605 SET_PERM_LOCKED(etDialog.lockReasons, XmToggleButtonGetState(w)); 606 formatChangedCB(w, clientData, callData); 607 } 608 609 #ifndef VMS 610 static void serverEqualViewCB(Widget w, XtPointer clientData, XtPointer callData) 611 { 612 if (XmToggleButtonGetState(w) == True) { 613 XmToggleButtonSetState(etDialog.oCcViewTagW, True, False); 614 XmToggleButtonSetState(etDialog.oServerNameW, True, False); 615 etDialog.isServer = True; 616 } 617 formatChangedCB(w, clientData, callData); 618 } 619 #endif /* VMS */ 620 621 static void applyCB(Widget w, XtPointer clientData, XtPointer callData) 622 { 623 char *format = XmTextGetString(etDialog.formatW); 624 625 /* pop down the dialog */ 626 /* XtUnmanageChild(etDialog.form); */ 627 628 if (strcmp(format, GetPrefTitleFormat()) != 0) { 629 SetPrefTitleFormat(format); 630 } 631 NEditFree(format); 632 } 633 634 static void closeCB(Widget w, XtPointer clientData, XtPointer callData) 635 { 636 /* pop down the dialog */ 637 XtUnmanageChild(etDialog.form); 638 } 639 640 static void restoreCB(Widget w, XtPointer clientData, XtPointer callData) 641 { 642 XmTextSetString(etDialog.formatW, "{%c} [%s] %f (%S) - %d"); 643 } 644 645 static void helpCB(Widget w, XtPointer clientData, XtPointer callData) 646 { 647 Help(HELP_CUSTOM_TITLE_DIALOG); 648 } 649 650 static void wtDestroyCB(Widget w, XtPointer clientData, XtPointer callData) 651 { 652 if (w == etDialog.form) /* Prevent disconnecting the replacing dialog */ 653 etDialog.form = NULL; 654 } 655 656 static void wtUnmapCB(Widget w, XtPointer clientData, XtPointer callData) 657 { 658 if (etDialog.form == w) /* Prevent destroying the replacing dialog */ 659 XtDestroyWidget(etDialog.form); 660 } 661 662 static void appendToFormat(const char* string) 663 { 664 char *format = XmTextGetString(etDialog.formatW); 665 char *buf = (char*)NEditMalloc(strlen(string) + strlen(format) + 1); 666 strcpy(buf, format); 667 strcat(buf, string); 668 XmTextSetString(etDialog.formatW, buf); 669 NEditFree(format); 670 NEditFree(buf); 671 } 672 673 static void removeFromFormat(const char* string) 674 { 675 char *format = XmTextGetString(etDialog.formatW); 676 char* pos; 677 678 /* There can be multiple occurences */ 679 while ((pos = strstr(format, string))) 680 { 681 /* If the string is preceded or followed by a brace, include 682 the brace(s) for removal */ 683 char* start = pos; 684 char* end = pos + strlen(string); 685 char post = *end; 686 687 if (post == '}' || post == ')' || post == ']' || post == '>') 688 { 689 end += 1; 690 post = *end; 691 } 692 693 if (start > format) 694 { 695 char pre = *(start-1); 696 if (pre == '{' || pre == '(' || pre == '[' || pre == '<') 697 start -= 1; 698 } 699 if (start > format) 700 { 701 char pre = *(start-1); 702 /* If there is a space in front and behind, remove one space 703 (there can be more spaces, but in that case it is likely 704 that the user entered them manually); also remove trailing 705 space */ 706 if (pre == ' ' && post == ' ') 707 { 708 end += 1; 709 } 710 else if (pre == ' ' && post == (char)0) 711 { 712 /* Remove (1) trailing space */ 713 start -= 1; 714 } 715 } 716 717 /* Contract the string: move end to start */ 718 strcpy(start, end); 719 } 720 721 /* Remove leading and trailing space */ 722 pos = format; 723 while (*pos == ' ') ++pos; 724 strcpy(format, pos); 725 726 pos = format + strlen(format) - 1; 727 while (pos >= format && *pos == ' ') 728 { 729 --pos; 730 } 731 *(pos+1) = (char)0; 732 733 XmTextSetString(etDialog.formatW, format); 734 NEditFree(format); 735 } 736 737 738 static void toggleFileCB(Widget w, XtPointer clientData, XtPointer callData) 739 { 740 if (XmToggleButtonGetState(etDialog.fileW)) 741 appendToFormat(" %f"); 742 else 743 removeFromFormat("%f"); 744 } 745 746 static void toggleServerCB(Widget w, XtPointer clientData, XtPointer callData) 747 { 748 if (XmToggleButtonGetState(etDialog.serverW)) 749 appendToFormat(" [%s]"); 750 else 751 removeFromFormat("%s"); 752 } 753 754 static void toggleHostCB(Widget w, XtPointer clientData, XtPointer callData) 755 { 756 if (XmToggleButtonGetState(etDialog.hostW)) 757 appendToFormat(" [%h]"); 758 else 759 removeFromFormat("%h"); 760 } 761 762 #ifndef VMS 763 static void toggleClearCaseCB(Widget w, XtPointer clientData, XtPointer callData) 764 { 765 if (XmToggleButtonGetState(etDialog.ccW)) 766 appendToFormat(" {%c}"); 767 else 768 removeFromFormat("%c"); 769 } 770 #endif /* VMS */ 771 772 static void toggleStatusCB(Widget w, XtPointer clientData, XtPointer callData) 773 { 774 if (XmToggleButtonGetState(etDialog.statusW)) 775 { 776 if (XmToggleButtonGetState(etDialog.shortStatusW)) 777 appendToFormat(" (%*S)"); 778 else 779 appendToFormat(" (%S)"); 780 } 781 else 782 { 783 removeFromFormat("%S"); 784 removeFromFormat("%*S"); 785 } 786 } 787 788 static void toggleShortStatusCB(Widget w, XtPointer clientData, XtPointer callData) 789 { 790 char *format, *pos; 791 792 if (etDialog.suppressFormatUpdate) 793 { 794 return; 795 } 796 797 format = XmTextGetString(etDialog.formatW); 798 799 if (XmToggleButtonGetState(etDialog.shortStatusW)) 800 { 801 /* Find all %S occurrences and replace them by %*S */ 802 do 803 { 804 pos = strstr(format, "%S"); 805 if (pos) 806 { 807 char* tmp = (char*)NEditMalloc((strlen(format)+2)*sizeof(char)); 808 strncpy(tmp, format, (size_t)(pos-format+1)); 809 tmp[pos-format+1] = 0; 810 strcat(tmp, "*"); 811 strcat(tmp, pos+1); 812 NEditFree(format); 813 format = tmp; 814 } 815 } 816 while (pos); 817 } 818 else 819 { 820 /* Replace all %*S occurences by %S */ 821 do 822 { 823 pos = strstr(format, "%*S"); 824 if (pos) 825 { 826 strcpy(pos+1, pos+2); 827 } 828 } 829 while(pos); 830 } 831 832 XmTextSetString(etDialog.formatW, format); 833 NEditFree(format); 834 } 835 836 static void toggleUserCB(Widget w, XtPointer clientData, XtPointer callData) 837 { 838 if (XmToggleButtonGetState(etDialog.nameW)) 839 appendToFormat(" %u"); 840 else 841 removeFromFormat("%u"); 842 } 843 844 static void toggleEncodingCB(Widget w, XtPointer clientData, XtPointer callData) 845 { 846 if (XmToggleButtonGetState(etDialog.encW)) 847 appendToFormat(" %e"); 848 else 849 removeFromFormat("%e"); 850 } 851 852 static void toggleDirectoryCB(Widget w, XtPointer clientData, XtPointer callData) 853 { 854 if (XmToggleButtonGetState(etDialog.dirW)) 855 { 856 char buf[20]; 857 buf[19] = 0; 858 int maxComp; 859 char *value = XmTextGetString(etDialog.ndirW); 860 if (*value) 861 { 862 if (sscanf(value, "%d", &maxComp) > 0) 863 { 864 snprintf(&buf[0], 19, " %%%dd ", maxComp); 865 } 866 else 867 { 868 snprintf(&buf[0], 19, " %%d "); /* Should not be necessary */ 869 } 870 } 871 else 872 { 873 snprintf(&buf[0], 19, " %%d "); 874 } 875 NEditFree(value); 876 appendToFormat(buf); 877 } 878 else 879 { 880 int i; 881 removeFromFormat("%d"); 882 for (i=0; i<=9; ++i) 883 { 884 char buf[20]; 885 snprintf(&buf[0], 19, "%%%dd", i); 886 removeFromFormat(buf); 887 } 888 } 889 } 890 891 static void enterMaxDirCB(Widget w, XtPointer clientData, XtPointer callData) 892 { 893 int maxComp = -1; 894 char *format; 895 char *value; 896 897 if (etDialog.suppressFormatUpdate) 898 { 899 return; 900 } 901 902 format = XmTextGetString(etDialog.formatW); 903 value = XmTextGetString(etDialog.ndirW); 904 905 if (*value) 906 { 907 if (sscanf(value, "%d", &maxComp) <= 0) 908 { 909 /* Don't allow non-digits to be entered */ 910 XBell(XtDisplay(w), 0); 911 XmTextSetString(etDialog.ndirW, ""); 912 } 913 } 914 915 if (maxComp >= 0) 916 { 917 char *pos; 918 int found = False; 919 char insert[2]; 920 insert[0] = (char)('0' + maxComp); 921 insert[1] = (char)0; /* '0' digit and 0 char ! */ 922 923 /* Find all %d and %nd occurrences and replace them by the new value */ 924 do 925 { 926 int i; 927 found = False; 928 pos = strstr(format, "%d"); 929 if (pos) 930 { 931 char* tmp = (char*)NEditMalloc((strlen(format)+2)*sizeof(char)); 932 strncpy(tmp, format, (size_t)(pos-format+1)); 933 tmp[pos-format+1] = 0; 934 strcat(tmp, &insert[0]); 935 strcat(tmp, pos+1); 936 NEditFree(format); 937 format = tmp; 938 found = True; 939 } 940 941 for (i=0; i<=9; ++i) 942 { 943 char buf[20]; 944 snprintf(&buf[0], 20, "%%%dd", i); 945 if (i != maxComp) 946 { 947 pos = strstr(format, &buf[0]); 948 if (pos) 949 { 950 *(pos+1) = insert[0]; 951 found = True; 952 } 953 } 954 } 955 } 956 while (found); 957 } 958 else 959 { 960 int found = True; 961 962 /* Replace all %nd occurences by %d */ 963 do 964 { 965 int i; 966 found = False; 967 for (i=0; i<=9; ++i) 968 { 969 char buf[20]; 970 char *pos; 971 snprintf(&buf[0], 20, "%%%dd", i); 972 pos = strstr(format, &buf[0]); 973 if (pos) 974 { 975 strcpy(pos+1, pos+2); 976 found = True; 977 } 978 } 979 } 980 while(found); 981 } 982 983 XmTextSetString(etDialog.formatW, format); 984 NEditFree(format); 985 NEditFree(value); 986 } 987 988 static void createEditTitleDialog(Widget parent) 989 { 990 #define LEFT_MARGIN_POS 2 991 #define RIGHT_MARGIN_POS 98 992 #define V_MARGIN 5 993 #define RADIO_INDENT 3 994 995 Widget buttonForm, formatLbl, previewFrame; 996 Widget previewForm, previewBox, selectFrame, selectBox, selectForm; 997 Widget testLbl, selectLbl; 998 Widget applyBtn, closeBtn, restoreBtn, helpBtn; 999 XmString s1; 1000 XmFontList fontList; 1001 Arg args[20]; 1002 int defaultBtnOffset; 1003 Dimension shadowThickness; 1004 Dimension radioHeight, textHeight; 1005 Pixel background; 1006 1007 int ac = 0; 1008 XtSetArg(args[ac], XmNautoUnmanage, False); ac++; 1009 XtSetArg(args[ac], XmNtitle, "Customize Window Title"); ac++; 1010 etDialog.form = CreateFormDialog(parent, "customizeTitle", args, ac); 1011 1012 /* 1013 * Destroy the dialog every time it is unmapped (otherwise it 'sticks' 1014 * to the window for which it was created originally). 1015 */ 1016 XtAddCallback(etDialog.form, XmNunmapCallback, wtUnmapCB, NULL); 1017 XtAddCallback(etDialog.form, XmNdestroyCallback, wtDestroyCB, NULL); 1018 1019 etDialog.shell = XtParent(etDialog.form); 1020 1021 /* Definition form */ 1022 selectFrame = XtVaCreateManagedWidget("selectionFrame", xmFrameWidgetClass, 1023 etDialog.form, 1024 XmNleftAttachment, XmATTACH_POSITION, 1025 XmNleftPosition, LEFT_MARGIN_POS, 1026 XmNtopAttachment, XmATTACH_FORM, 1027 XmNtopOffset, V_MARGIN, 1028 XmNrightAttachment, XmATTACH_POSITION, 1029 XmNrightPosition, RIGHT_MARGIN_POS, NULL); 1030 1031 XtVaCreateManagedWidget("titleLabel", xmLabelGadgetClass, 1032 selectFrame, 1033 XmNlabelString, 1034 s1=XmStringCreateSimple("Title definition"), 1035 XmNchildType, XmFRAME_TITLE_CHILD, 1036 XmNchildHorizontalAlignment, XmALIGNMENT_BEGINNING, NULL); 1037 XmStringFree(s1); 1038 1039 selectForm = XtVaCreateManagedWidget("selectForm", xmFormWidgetClass, 1040 selectFrame , 1041 XmNleftAttachment, XmATTACH_POSITION, 1042 XmNleftPosition, LEFT_MARGIN_POS, 1043 XmNtopAttachment, XmATTACH_FORM, 1044 XmNtopOffset, V_MARGIN, 1045 XmNrightAttachment, XmATTACH_POSITION, 1046 XmNrightPosition, RIGHT_MARGIN_POS, NULL); 1047 1048 selectLbl = XtVaCreateManagedWidget("selectLabel", xmLabelGadgetClass, 1049 selectForm, 1050 XmNlabelString, s1=XmStringCreateSimple("Select title components to include: "), 1051 XmNleftAttachment, XmATTACH_POSITION, 1052 XmNleftPosition, LEFT_MARGIN_POS, 1053 XmNtopOffset, 5, 1054 XmNbottomOffset, 5, 1055 XmNtopAttachment, XmATTACH_FORM, NULL); 1056 XmStringFree(s1); 1057 1058 selectBox = XtVaCreateManagedWidget("selectBox", xmFormWidgetClass, 1059 selectForm, 1060 XmNorientation, XmHORIZONTAL, 1061 XmNpacking, XmPACK_TIGHT, 1062 XmNradioBehavior, False, 1063 XmNleftAttachment, XmATTACH_FORM, 1064 XmNrightAttachment, XmATTACH_FORM, 1065 XmNtopOffset, 5, 1066 XmNtopAttachment, XmATTACH_WIDGET, 1067 XmNtopWidget, selectLbl, 1068 NULL); 1069 1070 etDialog.fileW = XtVaCreateManagedWidget("file", 1071 xmToggleButtonWidgetClass, selectBox, 1072 XmNleftAttachment, XmATTACH_POSITION, 1073 XmNleftPosition, RADIO_INDENT, 1074 XmNtopAttachment, XmATTACH_FORM, 1075 XmNlabelString, s1=XmStringCreateSimple("File name (%f)"), 1076 XmNmnemonic, 'F', NULL); 1077 XtAddCallback(etDialog.fileW, XmNvalueChangedCallback, toggleFileCB, NULL); 1078 XmStringFree(s1); 1079 1080 etDialog.statusW = XtVaCreateManagedWidget("status", 1081 xmToggleButtonWidgetClass, selectBox, 1082 XmNleftAttachment, XmATTACH_POSITION, 1083 XmNleftPosition, RADIO_INDENT, 1084 XmNtopAttachment, XmATTACH_WIDGET, 1085 XmNtopWidget, etDialog.fileW, 1086 XmNlabelString, s1=XmStringCreateSimple("File status (%S) "), 1087 XmNmnemonic, 't', NULL); 1088 XtAddCallback(etDialog.statusW, XmNvalueChangedCallback, toggleStatusCB, NULL); 1089 XmStringFree(s1); 1090 1091 etDialog.shortStatusW = XtVaCreateManagedWidget("shortStatus", 1092 xmToggleButtonWidgetClass, selectBox, 1093 XmNleftAttachment, XmATTACH_WIDGET, 1094 XmNleftWidget, etDialog.statusW, 1095 XmNtopAttachment, XmATTACH_WIDGET, 1096 XmNtopWidget, etDialog.fileW, 1097 XmNlabelString, s1=XmStringCreateSimple("brief"), 1098 XmNmnemonic, 'b', NULL); 1099 XtAddCallback(etDialog.shortStatusW, XmNvalueChangedCallback, toggleShortStatusCB, NULL); 1100 XmStringFree(s1); 1101 1102 etDialog.ccW = XtVaCreateManagedWidget("ccView", 1103 xmToggleButtonWidgetClass, selectBox, 1104 XmNleftAttachment, XmATTACH_POSITION, 1105 XmNleftPosition, RADIO_INDENT, 1106 XmNtopAttachment, XmATTACH_WIDGET, 1107 XmNtopWidget, etDialog.statusW, 1108 XmNlabelString, s1=XmStringCreateSimple("ClearCase view tag (%c) "), 1109 XmNmnemonic, 'C', NULL); 1110 XtAddCallback(etDialog.ccW, XmNvalueChangedCallback, toggleClearCaseCB, NULL); 1111 XmStringFree(s1); 1112 1113 etDialog.encW = XtVaCreateManagedWidget("encoding", 1114 xmToggleButtonWidgetClass, selectBox, 1115 XmNleftAttachment, XmATTACH_POSITION, 1116 XmNleftPosition, RADIO_INDENT, 1117 XmNtopAttachment, XmATTACH_WIDGET, 1118 XmNtopWidget, etDialog.ccW, 1119 XmNlabelString, s1=XmStringCreateSimple("Encoding (%e)"), 1120 XmNmnemonic, 'E', NULL); 1121 XtAddCallback(etDialog.encW, XmNvalueChangedCallback, toggleEncodingCB, NULL); 1122 XmStringFree(s1); 1123 1124 etDialog.dirW = XtVaCreateManagedWidget("directory", 1125 xmToggleButtonWidgetClass, selectBox, 1126 XmNleftAttachment, XmATTACH_POSITION, 1127 XmNleftPosition, RADIO_INDENT, 1128 XmNtopAttachment, XmATTACH_WIDGET, 1129 XmNtopWidget, etDialog.encW, 1130 XmNlabelString, s1=XmStringCreateSimple("Directory (%d),"), 1131 XmNmnemonic, 'D', NULL); 1132 XtAddCallback(etDialog.dirW, XmNvalueChangedCallback, toggleDirectoryCB, NULL); 1133 XmStringFree(s1); 1134 1135 XtVaGetValues(etDialog.fileW, XmNheight, &radioHeight, NULL); 1136 etDialog.mdirW = XtVaCreateManagedWidget("componentLab", 1137 xmLabelGadgetClass, selectBox, 1138 XmNheight, radioHeight, 1139 XmNleftAttachment, XmATTACH_WIDGET, 1140 XmNleftWidget, etDialog.dirW, 1141 XmNtopAttachment, XmATTACH_WIDGET, 1142 XmNtopWidget, etDialog.encW, 1143 XmNlabelString, s1=XmStringCreateSimple("max. components: "), 1144 XmNmnemonic, 'x', NULL); 1145 XmStringFree(s1); 1146 1147 etDialog.ndirW = XtVaCreateManagedWidget("dircomp", 1148 xmTextWidgetClass, selectBox, 1149 XmNcolumns, 1, 1150 XmNmaxLength, 1, 1151 XmNleftAttachment, XmATTACH_WIDGET, 1152 XmNleftWidget, etDialog.mdirW, 1153 XmNtopAttachment, XmATTACH_WIDGET, 1154 XmNtopWidget, etDialog.encW, 1155 NULL); 1156 XtAddCallback(etDialog.ndirW, XmNvalueChangedCallback, enterMaxDirCB, NULL); 1157 RemapDeleteKey(etDialog.ndirW); 1158 XtVaSetValues(etDialog.mdirW, XmNuserData, etDialog.ndirW, NULL); /* mnemonic processing */ 1159 1160 XtVaGetValues(etDialog.ndirW, XmNheight, &textHeight, NULL); 1161 XtVaSetValues(etDialog.dirW, XmNheight, textHeight, NULL); 1162 XtVaSetValues(etDialog.mdirW, XmNheight, textHeight, NULL); 1163 1164 etDialog.hostW = XtVaCreateManagedWidget("host", 1165 xmToggleButtonWidgetClass, selectBox, 1166 XmNleftAttachment, XmATTACH_POSITION, 1167 XmNleftPosition, 50 + RADIO_INDENT, 1168 XmNtopAttachment, XmATTACH_FORM, 1169 XmNlabelString, s1=XmStringCreateSimple("Host name (%h)"), 1170 XmNmnemonic, 'H', NULL); 1171 XtAddCallback(etDialog.hostW, XmNvalueChangedCallback, toggleHostCB, NULL); 1172 XmStringFree(s1); 1173 1174 etDialog.nameW = XtVaCreateManagedWidget("name", 1175 xmToggleButtonWidgetClass, selectBox, 1176 XmNleftAttachment, XmATTACH_POSITION, 1177 XmNleftPosition, 50 + RADIO_INDENT, 1178 XmNtopAttachment, XmATTACH_WIDGET, 1179 XmNtopWidget, etDialog.hostW, 1180 XmNlabelString, s1=XmStringCreateSimple("User name (%u)"), 1181 XmNmnemonic, 'U', NULL); 1182 XtAddCallback(etDialog.nameW, XmNvalueChangedCallback, toggleUserCB, NULL); 1183 XmStringFree(s1); 1184 1185 etDialog.serverW = XtVaCreateManagedWidget("server", 1186 xmToggleButtonWidgetClass, selectBox, 1187 XmNleftAttachment, XmATTACH_POSITION, 1188 XmNleftPosition, 50 + RADIO_INDENT, 1189 XmNtopAttachment, XmATTACH_WIDGET, 1190 XmNtopWidget, etDialog.nameW, 1191 XmNlabelString, s1=XmStringCreateSimple("NEdit server name (%s)"), 1192 XmNmnemonic, 's', NULL); 1193 XtAddCallback(etDialog.serverW, XmNvalueChangedCallback, toggleServerCB, NULL); 1194 XmStringFree(s1); 1195 1196 formatLbl = XtVaCreateManagedWidget("formatLbl", xmLabelGadgetClass, 1197 selectForm, 1198 XmNlabelString, s1=XmStringCreateSimple("Format: "), 1199 XmNmnemonic, 'r', 1200 XmNleftAttachment, XmATTACH_POSITION, 1201 XmNleftPosition, LEFT_MARGIN_POS, 1202 XmNtopAttachment, XmATTACH_WIDGET, 1203 XmNtopWidget, selectBox, 1204 XmNbottomAttachment, XmATTACH_FORM, NULL); 1205 XmStringFree(s1); 1206 etDialog.formatW = XtVaCreateManagedWidget("format", xmTextWidgetClass, 1207 selectForm, 1208 XmNmaxLength, WINDOWTITLE_MAX_LEN, 1209 XmNtopAttachment, XmATTACH_WIDGET, 1210 XmNtopWidget, selectBox, 1211 XmNtopOffset, 5, 1212 XmNleftAttachment, XmATTACH_WIDGET, 1213 XmNleftWidget, formatLbl, 1214 XmNrightAttachment, XmATTACH_POSITION, 1215 XmNrightPosition, RIGHT_MARGIN_POS, 1216 XmNbottomAttachment, XmATTACH_FORM, 1217 XmNbottomOffset, 5, NULL); 1218 RemapDeleteKey(etDialog.formatW); 1219 XtVaSetValues(formatLbl, XmNuserData, etDialog.formatW, NULL); 1220 XtAddCallback(etDialog.formatW, XmNvalueChangedCallback, formatChangedCB, NULL); 1221 1222 XtVaGetValues(etDialog.formatW, XmNheight, &textHeight, NULL); 1223 XtVaSetValues(formatLbl, XmNheight, textHeight, NULL); 1224 1225 previewFrame = XtVaCreateManagedWidget("previewFrame", xmFrameWidgetClass, 1226 etDialog.form, 1227 XmNtopAttachment, XmATTACH_WIDGET, 1228 XmNtopWidget, selectFrame, 1229 XmNleftAttachment, XmATTACH_POSITION, 1230 XmNleftPosition, LEFT_MARGIN_POS, 1231 XmNrightAttachment, XmATTACH_POSITION, 1232 XmNrightPosition, RIGHT_MARGIN_POS, NULL); 1233 1234 XtVaCreateManagedWidget("previewLabel", xmLabelGadgetClass, 1235 previewFrame, 1236 XmNlabelString, s1=XmStringCreateSimple("Preview"), 1237 XmNchildType, XmFRAME_TITLE_CHILD, 1238 XmNchildHorizontalAlignment, XmALIGNMENT_BEGINNING, NULL); 1239 XmStringFree(s1); 1240 1241 previewForm = XtVaCreateManagedWidget("previewForm", xmFormWidgetClass, 1242 previewFrame, 1243 XmNleftAttachment, XmATTACH_FORM, 1244 XmNleftPosition, LEFT_MARGIN_POS, 1245 XmNtopAttachment, XmATTACH_FORM, 1246 XmNtopOffset, V_MARGIN, 1247 XmNrightAttachment, XmATTACH_FORM, 1248 XmNrightPosition, RIGHT_MARGIN_POS, NULL); 1249 1250 /* Copy a variable width font from one of the labels to use for the 1251 preview (no editing is allowed, and with a fixed size font the 1252 preview easily gets partially obscured). Also copy the form background 1253 color to make it clear that this field is not editable */ 1254 XtVaGetValues(formatLbl, XmNfontList, &fontList, NULL); 1255 XtVaGetValues(previewForm, XmNbackground, &background, NULL); 1256 1257 etDialog.previewW = XtVaCreateManagedWidget("sample", 1258 xmTextFieldWidgetClass, previewForm, 1259 XmNeditable, False, 1260 XmNcursorPositionVisible, False, 1261 XmNtopAttachment, XmATTACH_FORM, 1262 XmNleftAttachment, XmATTACH_FORM, 1263 XmNleftOffset, V_MARGIN, 1264 XmNrightAttachment, XmATTACH_FORM, 1265 XmNrightOffset, V_MARGIN, 1266 XmNfontList, fontList, 1267 XmNbackground, background, 1268 NULL); 1269 1270 previewBox = XtVaCreateManagedWidget("previewBox", xmFormWidgetClass, 1271 previewForm, 1272 XmNorientation, XmHORIZONTAL, 1273 XmNpacking, XmPACK_TIGHT, 1274 XmNradioBehavior, False, 1275 XmNleftAttachment, XmATTACH_FORM, 1276 XmNrightAttachment, XmATTACH_FORM, 1277 XmNtopAttachment, XmATTACH_WIDGET, 1278 XmNtopWidget, etDialog.previewW, NULL); 1279 1280 testLbl = XtVaCreateManagedWidget("testLabel", xmLabelGadgetClass, 1281 previewBox, 1282 XmNlabelString, s1=XmStringCreateSimple("Test settings: "), 1283 XmNleftAttachment, XmATTACH_POSITION, 1284 XmNleftPosition, LEFT_MARGIN_POS, 1285 XmNtopOffset, 5, 1286 XmNbottomOffset, 5, 1287 XmNtopAttachment, XmATTACH_FORM, NULL); 1288 XmStringFree(s1); 1289 1290 etDialog.oFileChangedW = XtVaCreateManagedWidget("fileChanged", 1291 xmToggleButtonWidgetClass, previewBox, 1292 XmNleftAttachment, XmATTACH_POSITION, 1293 XmNleftPosition, RADIO_INDENT, 1294 XmNtopAttachment, XmATTACH_WIDGET, 1295 XmNtopWidget, testLbl, 1296 XmNlabelString, s1=XmStringCreateSimple("File modified"), 1297 XmNmnemonic, 'o', NULL); 1298 XtAddCallback(etDialog.oFileChangedW, XmNvalueChangedCallback, fileChangedCB, NULL); 1299 XmStringFree(s1); 1300 1301 etDialog.oFileReadOnlyW = XtVaCreateManagedWidget("fileReadOnly", 1302 xmToggleButtonWidgetClass, previewBox, 1303 XmNleftAttachment, XmATTACH_WIDGET, 1304 XmNleftWidget, etDialog.oFileChangedW, 1305 XmNtopAttachment, XmATTACH_WIDGET, 1306 XmNtopWidget, testLbl, 1307 XmNlabelString, s1=XmStringCreateSimple("File read only"), 1308 XmNmnemonic, 'n', NULL); 1309 XtAddCallback(etDialog.oFileReadOnlyW, XmNvalueChangedCallback, fileReadOnlyCB, NULL); 1310 XmStringFree(s1); 1311 1312 etDialog.oFileLockedW = XtVaCreateManagedWidget("fileLocked", 1313 xmToggleButtonWidgetClass, previewBox, 1314 XmNleftAttachment, XmATTACH_WIDGET, 1315 XmNleftWidget, etDialog.oFileReadOnlyW, 1316 XmNtopAttachment, XmATTACH_WIDGET, 1317 XmNtopWidget, testLbl, 1318 XmNlabelString, s1=XmStringCreateSimple("File locked"), 1319 XmNmnemonic, 'l', NULL); 1320 XtAddCallback(etDialog.oFileLockedW, XmNvalueChangedCallback, fileLockedCB, NULL); 1321 XmStringFree(s1); 1322 1323 etDialog.oServerNameW = XtVaCreateManagedWidget("servernameSet", 1324 xmToggleButtonWidgetClass, previewBox, 1325 XmNleftAttachment, XmATTACH_POSITION, 1326 XmNleftPosition, RADIO_INDENT, 1327 XmNtopAttachment, XmATTACH_WIDGET, 1328 XmNtopWidget, etDialog.oFileChangedW, 1329 XmNlabelString, s1=XmStringCreateSimple("Server name present"), 1330 XmNmnemonic, 'v', NULL); 1331 XtAddCallback(etDialog.oServerNameW, XmNvalueChangedCallback, serverNameCB, NULL); 1332 XmStringFree(s1); 1333 1334 etDialog.oCcViewTagW = XtVaCreateManagedWidget("ccViewTagSet", 1335 xmToggleButtonWidgetClass, previewBox, 1336 XmNleftAttachment, XmATTACH_POSITION, 1337 XmNleftPosition, RADIO_INDENT, 1338 XmNtopAttachment, XmATTACH_WIDGET, 1339 XmNtopWidget, etDialog.oServerNameW, 1340 XmNlabelString, s1=XmStringCreateSimple("CC view tag present"), 1341 #ifdef VMS 1342 XmNset, False, 1343 #else 1344 XmNset, GetClearCaseViewTag() != NULL, 1345 #endif /* VMS */ 1346 XmNmnemonic, 'w', NULL); 1347 #ifdef VMS 1348 XtSetSensitive(etDialog.oCcViewTagW, False); 1349 #else 1350 XtAddCallback(etDialog.oCcViewTagW, XmNvalueChangedCallback, ccViewTagCB, NULL); 1351 #endif /* VMS */ 1352 XmStringFree(s1); 1353 1354 etDialog.oServerEqualViewW = XtVaCreateManagedWidget("serverEqualView", 1355 xmToggleButtonWidgetClass, previewBox, 1356 XmNleftAttachment, XmATTACH_WIDGET, 1357 XmNleftWidget, etDialog.oCcViewTagW, 1358 XmNtopAttachment, XmATTACH_WIDGET, 1359 XmNtopWidget, etDialog.oServerNameW, 1360 XmNlabelString, s1=XmStringCreateSimple("Server name equals CC view tag "), 1361 XmNmnemonic, 'q', NULL); 1362 #ifdef VMS 1363 XtSetSensitive(etDialog.oServerEqualViewW, False); 1364 #else 1365 XtAddCallback(etDialog.oServerEqualViewW, XmNvalueChangedCallback, serverEqualViewCB, NULL); 1366 #endif /* VMS */ 1367 XmStringFree(s1); 1368 1369 etDialog.oDirW = XtVaCreateManagedWidget("pathSet", 1370 xmToggleButtonWidgetClass, previewBox, 1371 XmNleftAttachment, XmATTACH_POSITION, 1372 XmNleftPosition, RADIO_INDENT, 1373 XmNtopAttachment, XmATTACH_WIDGET, 1374 XmNtopWidget, etDialog.oCcViewTagW, 1375 XmNlabelString, s1=XmStringCreateSimple("Directory present"), 1376 XmNmnemonic, 'i', NULL); 1377 XtAddCallback(etDialog.oDirW, XmNvalueChangedCallback, formatChangedCB, NULL); 1378 XmStringFree(s1); 1379 1380 /* Button box */ 1381 buttonForm = XtVaCreateManagedWidget("buttonForm", xmFormWidgetClass, 1382 etDialog.form, 1383 XmNleftAttachment, XmATTACH_POSITION, 1384 XmNleftPosition, LEFT_MARGIN_POS, 1385 XmNtopAttachment, XmATTACH_WIDGET, 1386 XmNtopWidget, previewFrame, 1387 XmNtopOffset, V_MARGIN, 1388 XmNbottomOffset, V_MARGIN, 1389 XmNbottomAttachment, XmATTACH_FORM, 1390 XmNrightAttachment, XmATTACH_POSITION, 1391 XmNrightPosition, RIGHT_MARGIN_POS, NULL); 1392 1393 applyBtn = XtVaCreateManagedWidget("apply", xmPushButtonWidgetClass, 1394 buttonForm, 1395 XmNhighlightThickness, 2, 1396 XmNlabelString, s1=XmStringCreateSimple("Apply"), 1397 XmNshowAsDefault, (short)1, 1398 XmNleftAttachment, XmATTACH_POSITION, 1399 XmNleftPosition, 6, 1400 XmNrightAttachment, XmATTACH_POSITION, 1401 XmNrightPosition, 25, 1402 XmNbottomAttachment, XmATTACH_FORM, 1403 NULL); 1404 XtAddCallback(applyBtn, XmNactivateCallback, applyCB, NULL); 1405 XmStringFree(s1); 1406 XtVaGetValues(applyBtn, XmNshadowThickness, &shadowThickness, NULL); 1407 defaultBtnOffset = shadowThickness + 4; 1408 1409 closeBtn = XtVaCreateManagedWidget("close", xmPushButtonWidgetClass, 1410 buttonForm, 1411 XmNhighlightThickness, 2, 1412 XmNlabelString, s1=XmStringCreateSimple("Close"), 1413 XmNleftAttachment, XmATTACH_POSITION, 1414 XmNleftPosition, 52, 1415 XmNrightAttachment, XmATTACH_POSITION, 1416 XmNrightPosition, 71, 1417 XmNbottomAttachment, XmATTACH_FORM, 1418 XmNbottomOffset, defaultBtnOffset, 1419 NULL); 1420 XtAddCallback(closeBtn, XmNactivateCallback, closeCB, NULL); 1421 XmStringFree(s1); 1422 1423 restoreBtn = XtVaCreateManagedWidget("restore", xmPushButtonWidgetClass, 1424 buttonForm, 1425 XmNhighlightThickness, 2, 1426 XmNlabelString, s1=XmStringCreateSimple("Default"), 1427 XmNleftAttachment, XmATTACH_POSITION, 1428 XmNleftPosition, 29, 1429 XmNrightAttachment, XmATTACH_POSITION, 1430 XmNrightPosition, 48, 1431 XmNbottomAttachment, XmATTACH_FORM, 1432 XmNbottomOffset, defaultBtnOffset, 1433 XmNmnemonic, 'e', NULL); 1434 XtAddCallback(restoreBtn, XmNactivateCallback, restoreCB, NULL); 1435 XmStringFree(s1); 1436 1437 helpBtn = XtVaCreateManagedWidget("help", xmPushButtonWidgetClass, 1438 buttonForm, 1439 XmNhighlightThickness, 2, 1440 XmNlabelString, s1=XmStringCreateSimple("Help"), 1441 XmNleftAttachment, XmATTACH_POSITION, 1442 XmNleftPosition, 75, 1443 XmNrightAttachment, XmATTACH_POSITION, 1444 XmNrightPosition, 94, 1445 XmNbottomAttachment, XmATTACH_FORM, 1446 XmNbottomOffset, defaultBtnOffset, 1447 XmNmnemonic, 'p', NULL); 1448 XtAddCallback(helpBtn, XmNactivateCallback, helpCB, NULL); 1449 XmStringFree(s1); 1450 1451 /* Set initial default button */ 1452 XtVaSetValues(etDialog.form, XmNdefaultButton, applyBtn, NULL); 1453 XtVaSetValues(etDialog.form, XmNcancelButton, closeBtn, NULL); 1454 1455 /* Handle mnemonic selection of buttons and focus to dialog */ 1456 AddDialogMnemonicHandler(etDialog.form, FALSE); 1457 1458 etDialog.suppressFormatUpdate = FALSE; 1459 } 1460 1461 void EditCustomTitleFormat(WindowInfo *window) 1462 { 1463 /* copy attributes from current window so that we can use as many 1464 * 'real world' defaults as possible when testing the effect 1465 * of different formatting strings. 1466 */ 1467 strcpy(etDialog.path, window->path); 1468 strcpy(etDialog.filename, window->filename); 1469 #ifndef VMS 1470 strcpy(etDialog.viewTag, GetClearCaseViewTag() != NULL ? 1471 GetClearCaseViewTag() : 1472 "viewtag"); 1473 #endif /* VMS */ 1474 strcpy(etDialog.serverName, IsServer ? 1475 GetPrefServerName() : 1476 "servername"); 1477 etDialog.isServer = IsServer; 1478 etDialog.filenameSet = window->filenameSet; 1479 etDialog.lockReasons = window->lockReasons; 1480 etDialog.fileChanged = window->fileChanged; 1481 1482 if (etDialog.window != window && etDialog.form) 1483 { 1484 /* Destroy the dialog owned by the other window. 1485 Note: don't rely on the destroy event handler to reset the 1486 form. Events are handled asynchronously, so the old dialog 1487 may continue to live for a while. */ 1488 XtDestroyWidget(etDialog.form); 1489 etDialog.form = NULL; 1490 } 1491 1492 etDialog.window = window; 1493 1494 /* Create the dialog if it doesn't already exist */ 1495 if (etDialog.form == NULL) 1496 { 1497 createEditTitleDialog(window->shell); 1498 } 1499 else 1500 { 1501 /* If the window is already up, just pop it to the top */ 1502 if (XtIsManaged(etDialog.form)) { 1503 1504 RaiseDialogWindow(XtParent(etDialog.form)); 1505 1506 /* force update of the dialog */ 1507 setToggleButtons(); 1508 formatChangedCB(0, 0, 0); 1509 return; 1510 } 1511 } 1512 1513 /* set initial value of format field */ 1514 XmTextSetString(etDialog.formatW, (char *)GetPrefTitleFormat()); 1515 1516 /* force update of the dialog */ 1517 setToggleButtons(); 1518 formatChangedCB(0, 0, 0); 1519 1520 /* put up dialog and wait for user to press ok or cancel */ 1521 ManageDialogCenteredOnPointer(etDialog.form); 1522 } 1523