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