1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 #ifdef HAVE_CONFIG_H
31 #include "../config.h"
32 #endif
33
34 #include "help.h"
35 #include "textBuf.h"
36 #include "text.h"
37 #include "textP.h"
38 #include "textDisp.h"
39 #include "textSel.h"
40 #include "nedit.h"
41 #include "search.h"
42 #include "window.h"
43 #include "preferences.h"
44 #include "help_data.h"
45 #include "file.h"
46 #include "highlight.h"
47 #include "../util/motif.h"
48 #include "../util/misc.h"
49 #include "../util/DialogF.h"
50 #include "../util/system.h"
51 #include "../util/nedit_malloc.h"
52
53 #include <locale.h>
54 #include <stdlib.h>
55 #include <stdio.h>
56 #include <string.h>
57
58 #include "version.h"
59
60 #ifndef __MVS__
61 #include <sys/param.h>
62 #endif
63
64
65 #include <Xm/Xm.h>
66 #include <Xm/XmP.h>
67 #include <Xm/Form.h>
68 #include <Xm/PrimitiveP.h>
69 #include <Xm/ScrolledW.h>
70 #include <Xm/ScrollBar.h>
71 #include <Xm/PushB.h>
72 #ifdef EDITRES
73 #include <X11/Xmu/Editres.h>
74
75 #endif
76
77 #ifdef HAVE_DEBUG_H
78 #include "../debug.h"
79 #endif
80
81
82
83
84
85 #define EOS '\0'
86
87 #define CLICK_THRESHOLD 5
88
89
90
91
92
93
94
95
96 static Widget HelpWindows[
NUM_TOPICS] = {
NULL};
97 static Widget HelpTextPanes[
NUM_TOPICS] = {
NULL};
98 static textBuffer *HelpStyleBuffers[
NUM_TOPICS] = {
NULL};
99 static int navHistForw[
NUM_TOPICS];
100 static int navHistBack[
NUM_TOPICS];
101
102
103 static char LastSearchString[
DF_MAX_PROMPT_LENGTH] =
"";
104 static int LastSearchTopic = -
1;
105 static int LastSearchPos =
0;
106 static int LastSearchWasAllTopics = False;
107
108
109
110
111
112 static enum helpFonts StyleFonts[] =
113 {
114
115 FIXED_HELP_FONT,
BOLD_FIXED_HELP_FONT,
ITALIC_FIXED_HELP_FONT,
116 BOLD_ITALIC_FIXED_HELP_FONT,
117
118
119 FIXED_HELP_FONT,
BOLD_FIXED_HELP_FONT,
ITALIC_FIXED_HELP_FONT,
120 BOLD_ITALIC_FIXED_HELP_FONT,
121
122
123 HELP_FONT,
BOLD_HELP_FONT,
ITALIC_HELP_FONT,
BOLD_ITALIC_HELP_FONT,
124
125
126 HELP_FONT,
BOLD_HELP_FONT,
ITALIC_HELP_FONT,
BOLD_ITALIC_HELP_FONT,
127
128
129 HELP_FONT,
130
131
132 H1_HELP_FONT,
H2_HELP_FONT,
H3_HELP_FONT
133 };
134
135 static int StyleUnderlines[] =
136 {
137
138 False, False, False, False,
139
140
141 True, True, True, True,
142
143
144 False, False, False, False,
145
146
147 True, True, True, True,
148
149
150 True,
151
152
153 False, False, False
154 };
155
156 #define N_STYLES (XtNumber(StyleFonts))
157
158 static styleTableEntry HelpStyleInfo[
N_STYLES ];
159
160 static int HelpZoom;
161
162
163
164
165
166 static unsigned char AlphabetToAsciiTable[
256];
167
168
169
170
171
172 #define STYLE_INDEX(style) \
173 (AlphabetToAsciiTable[(
unsigned char)style] - \
174 AlphabetToAsciiTable[(
unsigned char)
STYLE_PLAIN])
175
176
177
178
179
180 static Widget createHelpPanel(
enum HelpTopic topic);
181 static void closeCB(Widget w, XtPointer clientData, XtPointer callData);
182 static void prevTopicCB(Widget w, XtPointer clientData, XtPointer callData);
183 static void nextTopicCB(Widget w, XtPointer clientData, XtPointer callData);
184 static void bwHistoryCB(Widget w, XtPointer clientData, XtPointer callData);
185 static void fwHistoryCB(Widget w, XtPointer clientData, XtPointer callData);
186 static void searchHelpCB(Widget w, XtPointer clientData, XtPointer callData);
187 static void searchHelpAgainCB(Widget w, XtPointer clientData,
188 XtPointer callData);
189 static void printCB(Widget w, XtPointer clientData, XtPointer callData);
190 static char *stitch(Widget parent,
char **string_list,
char **styleMap);
191 static void searchHelpText(Widget parent,
int parentTopic,
192 const char *searchFor,
int allSections,
int startPos,
int startTopic);
193 static void changeWindowTopic(
int existingTopic,
enum HelpTopic newTopic);
194 static int findTopicFromShellWidget(Widget shellWidget);
195 static void loadFontsAndColors(Widget parent,
int style);
196 static void initNavigationHistory(
void);
197
198 #ifdef HAVE__XMVERSIONSTRING
199 extern char _XmVersionString[];
200 #else
201 static char _XmVersionString[] =
"unknown";
202 #endif
203
204
205
206
207
208
209
210
211
212
213 static char *bldInfoString =
NULL;
214
215 static void freeBuildInfo(
void)
216 {
217
218 NEditFree(bldInfoString);
219 }
220
221 static const char *
const warning =
222 "\nThis XNEdit was built with a known-bad version of Motif. Please "
223 "do not report any bugs you encounter unless you can reproduce "
224 "them with a known-good binary from the unixwork.de/xnedit/ website. "
225 "If this binary was supplied with your Linux distribution please "
226 "file a bug report with them asking them to build XNEdit with a "
227 "known-good version of Motif.\n";
228
229
230 static const char *getBuildInfo(
void)
231 {
232 static const char *bldFormat =
233 "%s\n"
234 " Built on: %s, %s, %s\n"
235 " Built at: %s, %s\n"
236 " With Motif: %s%d.%d.%d [%s]\n"
237 "Running Motif: %d.%d [%s]\n"
238 " Server: %s %d\n"
239 " Visual: %s\n"
240 " Locale: %s\n"
241 ;
242
243 static const char *visualClass[] = {
"StaticGray",
"GrayScale",
244 "StaticColor",
"PseudoColor",
245 "TrueColor",
"DirectColor"};
246
247 static const char *
const stabilities[] = {
"",
"(Untested) ",
"(Known Bad) "};
248
249 if (bldInfoString ==
NULL)
250 {
251 const char *locale;
252 char visualStr[
500] =
"<unknown>";
253 const enum MotifStability stab = GetMotifStability();
254
255 if (TheDisplay) {
256 Visual *visual;
257 int depth;
258 Colormap map;
259 Boolean usingDefaultVisual = FindBestVisual(TheDisplay,
APP_NAME,
260 APP_CLASS, &visual,
261 &depth, &map);
262 sprintf(visualStr,
"%d-bit %s (ID %#lx%s)",
263 depth,
264 visualClass[visual->class],
265 visual->visualid,
266 usingDefaultVisual ?
", Default" :
"");
267 }
268
269 bldInfoString = (
char*)NEditMalloc(strlen(bldFormat) + strlen(warning) +
1024);
270 locale = setlocale(
LC_MESSAGES,
"");
271
272 #if defined(
XNEDIT_IS_RELEASE) || !defined(
XNEDIT_GIT_REV)
273 const char *xneVersion = NEditVersion;
274 #else
275 const char *xneVersion =
XNEDIT_VERSION "\n";
276 #endif
277 sprintf(bldInfoString, bldFormat,
278 xneVersion,
279 COMPILE_OS,
COMPILE_MACHINE,
COMPILE_COMPILER,
280 linkdate, linktime,
281 stabilities[stab], XmVERSION, XmREVISION, XmUPDATE_LEVEL,
282 XmVERSION_STRING,
283 xmUseVersion/
1000, xmUseVersion%
1000,
284 _XmVersionString,
285 (
NULL == TheDisplay ?
"<unknown>" : ServerVendor(TheDisplay)),
286 (
NULL == TheDisplay ?
0 : VendorRelease(TheDisplay)),
287 visualStr,
288 locale ? locale :
"None");
289
290 if (stab == MotifKnownBad)
291 strcat(bldInfoString, warning);
292
293 atexit(freeBuildInfo);
294 }
295
296 return bldInfoString;
297 }
298
299
300
301
302 static void initHelpStyles (Widget parent)
303 {
304 static int styleTableInitialized = False;
305
306 if (! styleTableInitialized)
307 {
308 Pixel fg;
309 int styleIndex;
310 char ** line;
311
312 XtVaGetValues(parent, XtNforeground, &fg,
NULL);
313
314 for (styleIndex =
0; styleIndex <
STL_HD +
MAX_HEADING; styleIndex++)
315 {
316 HelpStyleInfo[ styleIndex ].color = PixelToColor(parent, fg);
317 HelpStyleInfo[ styleIndex ].underline = StyleUnderlines[styleIndex];
318 HelpStyleInfo[ styleIndex ].font =
NULL;
319 }
320
321 styleTableInitialized = True;
322
323
324
325
326
327
328
329 for (line = HelpText[
HELP_VERSION ]; *line !=
NULL; line++)
330 {
331
332
333
334
335
336
337 if (strstr (*line,
"%s") !=
NULL)
338 {
339 const char * bldInfo = getBuildInfo();
340 char * text = (
char*)NEditMalloc(strlen (*line) + strlen (bldInfo));
341 sprintf (text, *line, bldInfo);
342 *line = text;
343 break;
344 }
345 }
346
347
348
349
350
351
352 AlphabetToAsciiTable[(
unsigned char)
'A'] =
ASCII_A +
0;
353 AlphabetToAsciiTable[(
unsigned char)
'B'] =
ASCII_A +
1;
354 AlphabetToAsciiTable[(
unsigned char)
'C'] =
ASCII_A +
2;
355 AlphabetToAsciiTable[(
unsigned char)
'D'] =
ASCII_A +
3;
356 AlphabetToAsciiTable[(
unsigned char)
'E'] =
ASCII_A +
4;
357 AlphabetToAsciiTable[(
unsigned char)
'F'] =
ASCII_A +
5;
358 AlphabetToAsciiTable[(
unsigned char)
'G'] =
ASCII_A +
6;
359 AlphabetToAsciiTable[(
unsigned char)
'H'] =
ASCII_A +
7;
360 AlphabetToAsciiTable[(
unsigned char)
'I'] =
ASCII_A +
8;
361 AlphabetToAsciiTable[(
unsigned char)
'J'] =
ASCII_A +
9;
362 AlphabetToAsciiTable[(
unsigned char)
'K'] =
ASCII_A +
10;
363 AlphabetToAsciiTable[(
unsigned char)
'L'] =
ASCII_A +
11;
364 AlphabetToAsciiTable[(
unsigned char)
'M'] =
ASCII_A +
12;
365 AlphabetToAsciiTable[(
unsigned char)
'N'] =
ASCII_A +
13;
366 AlphabetToAsciiTable[(
unsigned char)
'O'] =
ASCII_A +
14;
367 AlphabetToAsciiTable[(
unsigned char)
'P'] =
ASCII_A +
15;
368 AlphabetToAsciiTable[(
unsigned char)
'Q'] =
ASCII_A +
16;
369 AlphabetToAsciiTable[(
unsigned char)
'R'] =
ASCII_A +
17;
370 AlphabetToAsciiTable[(
unsigned char)
'S'] =
ASCII_A +
18;
371 AlphabetToAsciiTable[(
unsigned char)
'T'] =
ASCII_A +
19;
372 AlphabetToAsciiTable[(
unsigned char)
'U'] =
ASCII_A +
20;
373 AlphabetToAsciiTable[(
unsigned char)
'V'] =
ASCII_A +
21;
374 AlphabetToAsciiTable[(
unsigned char)
'W'] =
ASCII_A +
22;
375 AlphabetToAsciiTable[(
unsigned char)
'X'] =
ASCII_A +
23;
376 AlphabetToAsciiTable[(
unsigned char)
'Y'] =
ASCII_A +
24;
377 AlphabetToAsciiTable[(
unsigned char)
'Z'] =
ASCII_A +
25;
378 }
379 }
380
381
382
383
384
385 static void loadFontsAndColors(Widget parent,
int style)
386 {
387 Display *dp = XtDisplay(parent);
388
389 NFont *font;
390 int r,g,b;
391 if (HelpStyleInfo[
STYLE_INDEX(style)].font ==
NULL)
392 {
393 font = FontFromName(
394 dp,
395 GetPrefHelpFontName(StyleFonts[
STYLE_INDEX(style)]));
396
397 if (font ==
NULL)
398 {
399 fprintf(stderr,
"XNEdit: help font, %s, not available\n",
400 GetPrefHelpFontName(StyleFonts[
STYLE_INDEX(style)]));
401 font = FontFromName(dp,
"Monospace");
402 if (font ==
NULL)
403 {
404 fprintf(stderr,
"XNEdit: fallback help font, \"fixed\", not "
405 "available, cannot continue\n");
406 exit(
EXIT_FAILURE);
407 }
408 }
409 HelpStyleInfo[
STYLE_INDEX(style)].font = font;
410
411 if (style ==
STL_NM_LINK)
412 HelpStyleInfo[
STYLE_INDEX(style)].color = PixelToColor(parent,
413 AllocColor(parent, GetPrefHelpLinkColor(), &r, &g, &b));
414 }
415 }
416
417 static void adaptNavigationButtons(
int topic) {
418 Widget btn;
419
420 if(HelpWindows[topic] ==
NULL)
421 return;
422
423 btn=XtNameToWidget(HelpWindows[topic],
"helpForm.prevTopic");
424 if(btn)
425 {
426 if(topic >
0)
427 XtSetSensitive(btn, True);
428 else
429 XtSetSensitive(btn, False);
430 }
431
432 btn=XtNameToWidget(HelpWindows[topic],
"helpForm.nextTopic");
433 if(btn)
434 {
435 if(topic < (
NUM_TOPICS -
1))
436 XtSetSensitive(btn, True);
437 else
438 XtSetSensitive(btn, False);
439 }
440
441 btn=XtNameToWidget(HelpWindows[topic],
"helpForm.histBack");
442 if(btn)
443 {
444 if(navHistBack[topic] != -
1)
445 XtSetSensitive(btn, True);
446 else
447 XtSetSensitive(btn, False);
448 }
449
450 btn=XtNameToWidget(HelpWindows[topic],
"helpForm.histForw");
451 if(btn)
452 {
453 if(navHistForw[topic] != -
1)
454 XtSetSensitive(btn, True);
455 else
456 XtSetSensitive(btn, False);
457 }
458
459 }
460
461
462
463
464
465 static char * stitch (
466
467 Widget parent,
468 char ** string_list,
469 char ** styleMap
470 )
471 {
472 char * cp;
473 char * section, * sp;
474 char * styleData, * sdp;
475 char style =
STYLE_PLAIN;
476 int total_size =
0;
477 char ** crnt_line;
478
479
480
481
482 for (crnt_line = string_list; *crnt_line !=
NULL; crnt_line++)
483 {
484 for (cp = *crnt_line; *cp !=
EOS; cp++)
485 {
486
487
488
489
490
491
492
493 if (*cp !=
STYLE_MARKER) {
494 total_size++;
495 }
496 else {
497 cp++;
498 }
499 }
500 }
501
502
503
504
505
506 sp = section = (
char*)NEditMalloc(total_size +
1);
507 sdp = styleData = (styleMap) ? (
char*)NEditMalloc(total_size +
1) :
NULL;
508 *sp =
EOS;
509
510
511
512
513
514 for (crnt_line = string_list; *crnt_line !=
NULL; crnt_line++)
515 {
516 for (cp = *crnt_line; *cp !=
EOS; cp++)
517 {
518 if (*cp ==
STYLE_MARKER)
519 {
520 style = *(++cp);
521 loadFontsAndColors(parent, style);
522 }
else
523 {
524 *(sp++) = *cp;
525
526
527 if (styleMap)
528 *(sdp++) = AlphabetToAsciiTable[(
unsigned char)style];
529 }
530 }
531 }
532
533 *sp =
EOS;
534
535
536
537
538 if (styleMap) {
539 *styleMap = styleData;
540 *sdp =
EOS;
541 }
542
543 return section;
544 }
545
546
547
548
549
550
551
552 void Help(
enum HelpTopic topic)
553 {
554 if (HelpWindows[topic] !=
NULL)
555 RaiseShellWindow(HelpWindows[topic], True);
556 else
557 HelpWindows[topic] = createHelpPanel(topic);
558 adaptNavigationButtons(topic);
559 }
560
561
562
563 static void setHelpWinTitle(Widget win,
enum HelpTopic topic)
564 {
565 char * buf, *topStr=HelpTitles[topic];
566
567 buf=(
char*)NEditMalloc(strlen(topStr) +
24);
568 topic++;
569
570 sprintf(buf,
"XNEdit Help (%d)", (
int)topic);
571 XtVaSetValues(win, XmNiconName, buf,
NULL);
572
573 sprintf(buf,
"XNEdit Help: %s (%d)", topStr, (
int)topic);
574 XtVaSetValues(win, XmNtitle, buf,
NULL);
575
576 free(buf);
577 }
578
579
580
581
582
583
584
585
586
587
588 static Widget createHelpPanel(
enum HelpTopic topic)
589 {
590 Arg al[
50];
591 int ac;
592 Widget appShell, btn, closeBtn, form, btnFW;
593 Widget sw, hScrollBar, vScrollBar;
594 XmString st1;
595 char * helpText =
NULL;
596 char * styleData =
NULL;
597
598 ac =
0;
599 XtSetArg(al[ac], XmNdeleteResponse, XmDO_NOTHING); ac++;
600 appShell = CreateWidget(TheAppShell,
"help",
601 topLevelShellWidgetClass, al, ac);
602 AddSmallIcon(appShell);
603
604
605
606
607
608 XtVaSetValues(appShell, XtNminWidth,
50,
NULL);
609 form = XtVaCreateManagedWidget(
"helpForm", xmFormWidgetClass, appShell,
610 NULL);
611 XtVaSetValues(form, XmNshadowThickness,
0,
NULL);
612
613
614 btn = XtVaCreateManagedWidget(
"find", xmPushButtonWidgetClass, form,
615 XmNlabelString, st1=XmStringCreateSimple(
"Find..."),
616 XmNmnemonic,
'F',
617 XmNbottomAttachment, XmATTACH_FORM,
618 XmNleftAttachment, XmATTACH_POSITION,
619 XmNleftPosition,
3,
620 XmNrightAttachment, XmATTACH_POSITION,
621 XmNrightPosition,
25,
622 NULL);
623 XtAddCallback(btn, XmNactivateCallback, searchHelpCB, appShell);
624 XmStringFree(st1);
625
626 btn = XtVaCreateManagedWidget(
"findAgain", xmPushButtonWidgetClass, form,
627 XmNlabelString, st1=XmStringCreateSimple(
"Find Again"),
628 XmNmnemonic,
'A',
629 XmNbottomAttachment, XmATTACH_FORM,
630 XmNleftAttachment, XmATTACH_POSITION,
631 XmNleftPosition,
27,
632 XmNrightAttachment, XmATTACH_POSITION,
633 XmNrightPosition,
49,
634 NULL);
635 XtAddCallback(btn, XmNactivateCallback, searchHelpAgainCB, appShell);
636 XmStringFree(st1);
637
638 btn = XtVaCreateManagedWidget(
"print", xmPushButtonWidgetClass, form,
639 XmNlabelString, st1=XmStringCreateSimple(
"Print..."),
640 XmNmnemonic,
'P',
641 XmNbottomAttachment, XmATTACH_FORM,
642 XmNleftAttachment, XmATTACH_POSITION,
643 XmNleftPosition,
51,
644 XmNrightAttachment, XmATTACH_POSITION,
645 XmNrightPosition,
73,
646 NULL);
647 XtAddCallback(btn, XmNactivateCallback, printCB, appShell);
648 XmStringFree(st1);
649
650 closeBtn = XtVaCreateManagedWidget(
"close",
651 xmPushButtonWidgetClass, form,
652 XmNlabelString, st1=XmStringCreateSimple(
"Close"),
653 XmNbottomAttachment, XmATTACH_FORM,
654 XmNleftAttachment, XmATTACH_POSITION,
655 XmNleftPosition,
75,
656 XmNrightAttachment, XmATTACH_POSITION,
657 XmNrightPosition,
97,
658 NULL);
659 XtAddCallback(closeBtn, XmNactivateCallback, closeCB, appShell);
660 XmStringFree(st1);
661
662
663 btn = XtVaCreateManagedWidget(
"prevTopic", xmPushButtonWidgetClass, form,
664 XmNlabelString, st1=XmStringCreateSimple(
"<< Browse"),
665 XmNmnemonic,
'o',
666 XmNbottomAttachment, XmATTACH_WIDGET,
667 XmNbottomWidget, closeBtn,
668 XmNleftAttachment, XmATTACH_POSITION,
669 XmNleftPosition,
51,
670 XmNrightAttachment, XmATTACH_POSITION,
671 XmNrightPosition,
73,
672 NULL);
673 XtAddCallback(btn, XmNactivateCallback, prevTopicCB, appShell);
674 XmStringFree(st1);
675
676 btn = XtVaCreateManagedWidget(
"nextTopic", xmPushButtonWidgetClass, form,
677 XmNlabelString, st1=XmStringCreateSimple(
"Browse >>"),
678 XmNmnemonic,
'e',
679 XmNbottomAttachment, XmATTACH_WIDGET,
680 XmNbottomWidget, closeBtn,
681 XmNleftAttachment, XmATTACH_POSITION,
682 XmNleftPosition,
75,
683 XmNrightAttachment, XmATTACH_POSITION,
684 XmNrightPosition,
97,
685 NULL);
686 XtAddCallback(btn, XmNactivateCallback, nextTopicCB, appShell);
687 XmStringFree(st1);
688
689 btn = XtVaCreateManagedWidget(
"histBack", xmPushButtonWidgetClass, form,
690 XmNlabelString, st1=XmStringCreateSimple(
"Back"),
691 XmNmnemonic,
'B',
692 XmNbottomAttachment, XmATTACH_WIDGET,
693 XmNbottomWidget, closeBtn,
694 XmNleftAttachment, XmATTACH_POSITION,
695 XmNleftPosition,
3,
696 XmNrightAttachment, XmATTACH_POSITION,
697 XmNrightPosition,
25,
698 NULL);
699 XtAddCallback(btn, XmNactivateCallback, bwHistoryCB, appShell);
700 XmStringFree(st1);
701
702 btnFW = XtVaCreateManagedWidget(
"histForw", xmPushButtonWidgetClass, form,
703 XmNlabelString, st1=XmStringCreateSimple(
"Forward"),
704 XmNmnemonic,
'w',
705 XmNbottomAttachment, XmATTACH_WIDGET,
706 XmNbottomWidget, closeBtn,
707 XmNleftAttachment, XmATTACH_POSITION,
708 XmNleftPosition,
27,
709 XmNrightAttachment, XmATTACH_POSITION,
710 XmNrightPosition,
49,
711 NULL);
712 XtAddCallback(btnFW, XmNactivateCallback, fwHistoryCB, appShell);
713 XmStringFree(st1);
714
715
716 sw = XtVaCreateManagedWidget(
"sw", xmScrolledWindowWidgetClass, form,
717 XmNshadowThickness,
2,
718 XmNtopAttachment, XmATTACH_FORM,
719 XmNleftAttachment, XmATTACH_FORM,
720 XmNrightAttachment, XmATTACH_FORM,
721 XmNbottomAttachment, XmATTACH_WIDGET,
722 XmNbottomWidget, btnFW,
723 NULL);
724 hScrollBar = XtVaCreateManagedWidget(
"hScrollBar",
725 xmScrollBarWidgetClass, sw,
726 XmNorientation, XmHORIZONTAL,
727 XmNrepeatDelay,
10,
728 NULL);
729 vScrollBar = XtVaCreateManagedWidget(
"vScrollBar",
730 xmScrollBarWidgetClass, sw,
731 XmNorientation, XmVERTICAL,
732 XmNrepeatDelay,
10,
733 NULL);
734
735
736 loadFontsAndColors(sw,
'A');
737 HelpTextPanes[topic] = XtVaCreateManagedWidget(
"helpText",
738 textWidgetClass, sw,
739 textNXftFont, HelpStyleInfo[
0].font,
740 textNrows,
30,
741 textNcolumns,
65,
742 textNbacklightCharTypes,
NULL,
743 textNhScrollBar, hScrollBar,
744 textNvScrollBar, vScrollBar,
745 textNreadOnly, True,
746 textNcontinuousWrap, True,
747 textNautoShowInsertPos, True,
748 NULL);
749 XtVaSetValues(sw, XmNworkWindow, HelpTextPanes[topic],
750 XmNhorizontalScrollBar, hScrollBar,
751 XmNverticalScrollBar, vScrollBar,
752 NULL);
753
754
755 initHelpStyles (HelpTextPanes[topic]);
756
757
758
759 helpText = stitch (HelpTextPanes[topic], HelpText[topic], &styleData);
760
761
762 BufSetAll (TextGetBuffer (HelpTextPanes[topic]) , helpText);
763 NEditFree(helpText);
764
765
766
767 HelpStyleBuffers[topic] = BufCreate();
768 BufSetAll(HelpStyleBuffers[topic], styleData);
769 NEditFree(styleData);
770 TextDAttachHighlightData(((TextWidget)HelpTextPanes[topic])->text.textD,
771 HelpStyleBuffers[topic], HelpStyleInfo,
N_STYLES,
'\0',
NULL,
NULL);
772
773
774 HandleXSelections(HelpTextPanes[topic]);
775
776
777 AddDialogMnemonicHandler(form,
FALSE);
778
779
780 XtVaSetValues(form, XmNdefaultButton, closeBtn,
NULL);
781 XtVaSetValues(form, XmNcancelButton, closeBtn,
NULL);
782
783
784 RealizeWithoutForcingPosition(appShell);
785
786
787 XmProcessTraversal(HelpTextPanes[topic], XmTRAVERSE_CURRENT);
788
789
790 AddMotifCloseCallback(appShell, closeCB, appShell);
791
792
793 initNavigationHistory();
794
795
796 setHelpWinTitle(appShell, topic);
797
798
799 #ifdef EDITRES
800 XtAddEventHandler (appShell, (EventMask)
0, True,
801 (XtEventHandler)_XEditResCheckMessages,
NULL);
802 #endif
803
804 return appShell;
805 }
806
807 static void changeTopicOrRaise(
int existingTopic,
int newTopic) {
808 if(HelpWindows[newTopic] ==
NULL)
809 {
810 changeWindowTopic(existingTopic, (
enum HelpTopic) newTopic);
811 adaptNavigationButtons(newTopic);
812 }
else
813 {
814 RaiseShellWindow(HelpWindows[newTopic], True);
815 adaptNavigationButtons(existingTopic);
816 adaptNavigationButtons(newTopic);
817 }
818
819 }
820
821
822
823
824 static void closeCB(Widget w, XtPointer clientData, XtPointer callData)
825 {
826 int topic;
827
828 if ((topic = findTopicFromShellWidget((Widget)clientData)) == -
1)
829 return;
830
831
832
833 XtDestroyWidget(HelpWindows[topic]);
834 HelpWindows[topic] =
NULL;
835 if (HelpStyleBuffers[topic] !=
NULL)
836 {
837 BufFree(HelpStyleBuffers[topic]);
838 HelpStyleBuffers[topic] =
NULL;
839 }
840 }
841
842 static void prevTopicCB(Widget w, XtPointer clientData, XtPointer callData)
843 {
int topic;
844
845 if ((topic = findTopicFromShellWidget((Widget)clientData)) == -
1)
846 return;
847
848 topic--;
849 if(topic >=
0)
850 changeTopicOrRaise(topic+
1, topic);
851 }
852
853 static void nextTopicCB(Widget w, XtPointer clientData, XtPointer callData)
854 {
int topic;
855
856 if ((topic = findTopicFromShellWidget((Widget)clientData)) == -
1)
857 return;
858
859 topic++;
860 if(topic <
NUM_TOPICS)
861 changeTopicOrRaise(topic-
1, topic);
862 }
863
864 static void bwHistoryCB(Widget w, XtPointer clientData, XtPointer callData)
865 {
int topic, goTo;
866
867 if ((topic = findTopicFromShellWidget((Widget)clientData)) == -
1)
868 return;
869
870 goTo=navHistBack[topic];
871 if(goTo >=
0 && goTo <
NUM_TOPICS)
872 {
873 navHistForw[goTo]=topic;
874 changeTopicOrRaise(topic, goTo);
875 }
876 }
877
878 static void fwHistoryCB(Widget w, XtPointer clientData, XtPointer callData)
879 {
int topic, goTo;
880
881 if ((topic = findTopicFromShellWidget((Widget)clientData)) == -
1)
882 return;
883
884 goTo=navHistForw[topic];
885 if(goTo >=
0 && goTo <
NUM_TOPICS)
886 {
887 navHistBack[goTo]=topic;
888 changeTopicOrRaise(topic, goTo);
889 }
890 }
891
892 static void searchHelpCB(Widget w, XtPointer clientData, XtPointer callData)
893 {
894 char promptText[
DF_MAX_PROMPT_LENGTH];
895 int response, topic;
896 static char **searchHistory =
NULL;
897 static int nHistoryStrings =
0;
898
899 if ((topic = findTopicFromShellWidget((Widget)clientData)) == -
1)
900 return;
901 SetDialogFPromptHistory(searchHistory, nHistoryStrings);
902 response = DialogF(
DF_PROMPT, HelpWindows[topic],
3,
"Find",
903 "Search for: (use up arrow key to recall previous)", promptText,
904 "This Section",
"All Sections",
"Cancel");
905 if (response ==
3)
906 return;
907 AddToHistoryList(promptText, &searchHistory, &nHistoryStrings);
908 searchHelpText(HelpWindows[topic], topic, promptText, response ==
2,
0,
0);
909 }
910
911 static void searchHelpAgainCB(Widget w, XtPointer clientData,
912 XtPointer callData)
913 {
914 int topic;
915
916 if ((topic = findTopicFromShellWidget((Widget)clientData)) == -
1)
917 return;
918 searchHelpText(HelpWindows[topic], topic, LastSearchString,
919 LastSearchWasAllTopics, LastSearchPos, LastSearchTopic);
920 }
921
922 static void printCB(Widget w, XtPointer clientData, XtPointer callData)
923 {
924 int topic, helpStringLen;
925 char *helpString;
926
927 if ((topic = findTopicFromShellWidget((Widget)clientData)) == -
1)
928 return;
929
930 helpString = TextGetWrapped(HelpTextPanes[topic],
0,
931 TextGetBuffer(HelpTextPanes[topic])->length, &helpStringLen);
932 PrintString(helpString, helpStringLen, HelpWindows[topic],
933 HelpTitles[topic]);
934 NEditFree(helpString);
935 }
936
937
938
939
940
941
942 static int is_known_link(
char *link_name,
int *topic,
int *textPosition)
943 {
944 Href * hypertext;
945
946
947
948
949 for (*topic=
0; HelpTitles[*topic] !=
NULL; (*topic)++)
950 {
951 if (strcmp (link_name, HelpTitles[*topic]) ==
0)
952 {
953 *textPosition =
0;
954 return 1;
955 }
956 }
957
958
959
960
961 for (hypertext = &
H_R[
0]; hypertext !=
NULL; hypertext = hypertext->next)
962 {
963 if (strcmp (link_name, hypertext->source) ==
0)
964 {
965 *topic = hypertext->topic;
966 *textPosition = hypertext->location;
967 return 1;
968 }
969 }
970
971 return 0;
972 }
973
974
975
976
977
978 static void followHyperlink(
int topic,
int charPosition,
int newWindow)
979 {
980 textDisp *textD = ((TextWidget)HelpTextPanes[topic])->text.textD;
981 char * link_text;
982 int link_topic;
983 int link_pos;
984 int end = charPosition;
985 int begin = charPosition;
986 char whatStyle = BufGetCharacter(textD->styleBuffer, end);
987
988
989
990
991 while (whatStyle == BufGetCharacter(textD->styleBuffer, ++end));
992 while (whatStyle == BufGetCharacter(textD->styleBuffer, begin-
1)) begin--;
993
994 link_text = BufGetRange (textD->buffer, begin, end);
995
996 if (is_known_link (link_text, &link_topic, &link_pos) )
997 {
998 if (HelpWindows[link_topic] !=
NULL)
999 {
1000 RaiseShellWindow(HelpWindows[link_topic], True);
1001 }
else
1002 {
1003 if (newWindow)
1004 {
1005 HelpWindows[link_topic]
1006 = createHelpPanel((
enum HelpTopic) link_topic);
1007 }
else
1008 {
1009 changeWindowTopic(topic, (
enum HelpTopic) link_topic);
1010 }
1011 }
1012 navHistBack[link_topic] = topic;
1013 navHistForw[topic] = link_topic;
1014 TextSetCursorPos(HelpTextPanes[link_topic], link_pos);
1015 adaptNavigationButtons(link_topic);
1016 adaptNavigationButtons(topic);
1017 }
1018 NEditFree(link_text);
1019 }
1020
1021 static void helpFocusButtonsAP(Widget w, XEvent *event, String *args,
1022 Cardinal *nArgs)
1023 {
1024 XmProcessTraversal(w, XmTRAVERSE_NEXT_TAB_GROUP);
1025 }
1026
1027
1028
1029
1030
1031 static void helpButtonActionAP(Widget w, XEvent *event, String *args,
1032 Cardinal *nArgs)
1033 {
1034 char buf[
80];
1035 int topic;
1036 Widget btn;
1037
1038 if(*nArgs !=
1)
1039 {
1040 fprintf(stderr,
"help-button-action: requires exactly one argument.\n");
1041 return;
1042 }
1043
1044
1045 for (topic =
0; topic <
NUM_TOPICS; topic++)
1046 if (HelpTextPanes[topic] == w)
1047 break;
1048
1049 if(topic ==
NUM_TOPICS || HelpWindows[topic] ==
NULL)
1050 return;
1051
1052
1053 strcpy(&buf[
0],
"helpForm.");
1054 if (strlen(args[
0]) <=
70)
1055 {
1056 strcat(&buf[
0], args[
0]);
1057 }
else
1058 {
1059 fprintf(stderr,
"help-button-action: argument too long");
1060 return;
1061 }
1062
1063 btn=XtNameToWidget(HelpWindows[topic], buf);
1064 if (btn)
1065 {
1066 XtCallCallbacks(btn, XmNactivateCallback, HelpWindows[topic]);
1067 }
else
1068 {
1069 fprintf(stderr,
"help-button-action: invalid argument: %s\n", args[
0]);
1070 }
1071 }
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085 static void helpHyperlinkAP(Widget w, XEvent *event, String *args,
1086 Cardinal *nArgs)
1087 {
1088 XButtonEvent *e = (XButtonEvent *)event;
1089 int topic;
1090 textDisp *textD = ((TextWidget)w)->text.textD;
1091 int clickedPos, newWin;
1092 static int pressX=
0, pressY=
0;
1093
1094
1095 if (*nArgs ==
0)
1096 {
1097 pressX = e->x;
1098 pressY = e->y;
1099 return;
1100 }
1101
1102 newWin = !strcmp(args[
0],
"new");
1103
1104 if(!newWin && strcmp(args[
0],
"current")) {
1105 fprintf(stderr,
"help-hyperlink: Unrecognized argument %s\n", args[
0]);
1106 return;
1107 }
1108
1109
1110
1111
1112
1113
1114 if (abs(pressX - e->x) >
CLICK_THRESHOLD
1115 || abs(pressY - e->y) >
CLICK_THRESHOLD)
1116 {
1117 if (*nArgs ==
3)
1118 XtCallActionProc(w, args[
2], event,
NULL,
0);
1119 return;
1120 }
1121
1122 clickedPos = TextDXYToCharPos(textD, e->x, e->y);
1123
1124 if (BufGetCharacter(textD->styleBuffer, clickedPos) !=
1125 (
char)AlphabetToAsciiTable[(
unsigned char)
STL_NM_LINK])
1126 {
1127 if (*nArgs ==
3)
1128 XtCallActionProc(w, args[
2], event,
NULL,
0);
1129 return;
1130 }
1131
1132
1133 for (topic =
0; topic <
NUM_TOPICS; topic++)
1134 if (HelpTextPanes[topic] == w)
1135 break;
1136
1137 if (topic ==
NUM_TOPICS)
1138 {
1139
1140
1141
1142 if (*nArgs ==
3)
1143 XtCallActionProc(w, args[
2], event,
NULL,
0);
1144 return;
1145 }
1146
1147
1148
1149
1150 if (*nArgs ==
3)
1151 XtCallActionProc(w, args[
1], event,
NULL,
0);
1152
1153 followHyperlink(topic, clickedPos, newWin);
1154 }
1155
1156
1157
1158
1159 void InstallHelpLinkActions(XtAppContext context)
1160 {
1161 static XtActionsRec Actions[] =
1162 {
1163 {
"help-hyperlink", helpHyperlinkAP},
1164 {
"help-focus-buttons", helpFocusButtonsAP},
1165 {
"help-button-action", helpButtonActionAP}
1166 };
1167
1168 XtAppAddActions(context, Actions, XtNumber(Actions));
1169 }
1170
1171
1172
1173
1174
1175 static void searchHelpText(Widget parent,
int parentTopic,
1176 const char *searchFor,
int allSections,
int startPos,
int startTopic)
1177 {
1178 int topic, beginMatch, endMatch;
1179 int found = False;
1180 char * helpText =
NULL;
1181
1182
1183 for (topic=startTopic; topic<
NUM_TOPICS; topic++)
1184 {
1185 if (!allSections && topic != parentTopic)
1186 continue;
1187 helpText = stitch(parent, HelpText[topic],
NULL);
1188
1189 if (SearchString(helpText, searchFor,
SEARCH_FORWARD,
SEARCH_LITERAL,
1190 False, topic == startTopic ? startPos :
0, &beginMatch,
1191 &endMatch,
NULL,
NULL, GetPrefDelimiters()))
1192 {
1193 found = True;
1194 NEditFree(helpText);
1195 break;
1196 }
1197 NEditFree(helpText);
1198 }
1199
1200 if (!found)
1201 {
1202 if (startPos !=
0 || (allSections && startTopic !=
0))
1203 {
1204
1205 searchHelpText(parent, parentTopic, searchFor, allSections,
0,
0);
1206 return;
1207 }
1208 DialogF(
DF_INF, parent,
1,
"String Not Found",
"String Not Found",
"OK");
1209 return;
1210 }
1211
1212
1213 if (parentTopic != topic)
1214 {
1215 navHistForw[parentTopic]= topic;
1216 navHistBack[topic]= parentTopic;
1217 }
1218
1219
1220
1221 changeTopicOrRaise(parentTopic, topic);
1222 BufSelect(TextGetBuffer(HelpTextPanes[topic]), beginMatch, endMatch);
1223 TextSetCursorPos(HelpTextPanes[topic], endMatch);
1224
1225
1226 if (searchFor != LastSearchString)
1227 strncpy(LastSearchString, searchFor,
sizeof(LastSearchString)-
1);
1228 LastSearchTopic = topic;
1229 LastSearchPos = endMatch;
1230 LastSearchWasAllTopics = allSections;
1231 }
1232
1233
1234
1235
1236
1237
1238
1239 static void changeWindowTopic(
int existingTopic,
enum HelpTopic newTopic)
1240 {
1241 char *helpText, *styleData;
1242
1243
1244 if (newTopic != existingTopic)
1245 {
1246 HelpWindows[newTopic] = HelpWindows[existingTopic];
1247 HelpWindows[existingTopic] =
NULL;
1248 HelpStyleBuffers[newTopic] = HelpStyleBuffers[existingTopic];
1249 HelpStyleBuffers[existingTopic] =
NULL;
1250 HelpTextPanes[newTopic] = HelpTextPanes[existingTopic];
1251 HelpTextPanes[existingTopic] =
NULL;
1252 setHelpWinTitle(HelpWindows[newTopic], newTopic);
1253 }
1254
1255
1256
1257
1258
1259 helpText = stitch(HelpTextPanes[newTopic], HelpText[newTopic], &styleData);
1260 TextDAttachHighlightData(((TextWidget)HelpTextPanes[newTopic])->text.textD,
1261 NULL,
NULL,
0,
'\0',
NULL,
NULL);
1262 BufSetAll(TextGetBuffer(HelpTextPanes[newTopic]), helpText);
1263 NEditFree(helpText);
1264 BufSetAll(HelpStyleBuffers[newTopic], styleData);
1265 NEditFree(styleData);
1266 TextDAttachHighlightData(((TextWidget)HelpTextPanes[newTopic])->text.textD,
1267 HelpStyleBuffers[newTopic], HelpStyleInfo,
N_STYLES,
'\0',
NULL,
1268 NULL);
1269 }
1270
1271 static int findTopicFromShellWidget(Widget shellWidget)
1272 {
1273 int i;
1274
1275 for (i=
0; i<
NUM_TOPICS; i++)
1276 if (shellWidget == HelpWindows[i])
1277 return i;
1278 return -
1;
1279 }
1280
1281 static void initNavigationHistory(
void) {
1282 static int doInitNavigationHistory = True;
1283 int i;
1284
1285 if (doInitNavigationHistory)
1286 {
1287 for (i=
0; i<
NUM_TOPICS; i++)
1288 navHistBack[i] = navHistForw[i] = -
1;
1289
1290 doInitNavigationHistory = False;
1291 }
1292 }
1293
1294 #if XmVersion ==
2000
1295
1296
1297
1298
1299
1300
1301
1302 extern void XmRegisterConverters(
void);
1303 #endif
1304
1305 void SetHelpZoom(Widget textWidget,
int step)
1306 {
1307 Display *dp = XtDisplay(textWidget);
1308 HelpZoom += step;
1309
1310 for(
int i=
0;i<
N_STYLES;i++) {
1311 if(HelpStyleInfo[i].font) {
1312 int font_sz = HelpStyleInfo[i].font->size + step;
1313 char *fontName = GetPrefHelpFontName(StyleFonts[
STYLE_INDEX(i)]);
1314
1315 char *newFontName = ChangeFontSize(fontName, font_sz);
1316
1317 NFont *newFont = FontFromName(dp, newFontName);
1318 NEditFree(newFontName);
1319
1320 if(newFont) {
1321 FontUnref(HelpStyleInfo[i].font);
1322 HelpStyleInfo[i].font = newFont;
1323 }
1324 }
1325 }
1326
1327 XtVaSetValues(textWidget, textNXftFont, HelpStyleInfo[
0].font,
NULL);
1328 }
1329
1330
1331 void PrintVersion(
void)
1332 {
1333 const char *text;
1334
1335 #if XmVersion <
2001
1336 XmRegisterConverters();
1337 #endif
1338 text = getBuildInfo();
1339 puts (text);
1340 }
1341