1 /* ------------ helpbox.c ----------- */
3 #include "dflat32/dflat.h"
4 #include "dflat32/htree.h"
8 /* -------- strings of D-Flat classes for calling default
9 help text collections -------- */
10 char *ClassNames
[] = {
12 #define ClassDef(c,b,p,a) #c,
13 #include "dflat32/classes.h"
17 #define MAXHEIGHT (DfGetScreenHeight()-10)
19 /* --------- linked list of help text collections -------- */
29 struct helps
*NextHelp
;
31 static struct helps
*FirstHelp
;
32 static struct helps
*LastHelp
;
33 static struct helps
*ThisHelp
;
35 /* --- linked stack of help windows that have beed used --- */
38 struct HelpStack
*PrevStack
;
40 static struct HelpStack
*LastStack
;
41 static struct HelpStack
*ThisStack
;
43 /* --- linked list of keywords in the current help
44 text collection (listhead is in window) -------- */
50 struct keywords
*nextword
;
51 struct keywords
*prevword
;
55 static char hline
[160];
58 static void SelectHelp(DFWINDOW
, char *);
59 static void ReadHelp(DFWINDOW
);
60 static void FindHelp(char *);
61 static void FindHelpWindow(DFWINDOW
);
62 static void DisplayDefinition(DFWINDOW
, char *);
63 static void BestFit(DFWINDOW
, DIALOGWINDOW
*);
65 /* ------------- CREATE_WINDOW message ------------ */
66 static void CreateWindowMsg(DFWINDOW wnd
)
69 GetClass(wnd
) = HELPBOX
;
70 InitWindowColors(wnd
);
75 /* ------------- COMMAND message ------------ */
76 static BOOL
CommandMsg(DFWINDOW wnd
, PARAM p1
)
80 ThisStack
= LastStack
;
81 while (ThisStack
!= NULL
) {
82 LastStack
= ThisStack
->PrevStack
;
83 if (ThisStack
->hname
!= NULL
)
84 free(ThisStack
->hname
);
86 ThisStack
= LastStack
;
92 SelectHelp(wnd
, ThisHelp
->PrevName
);
97 SelectHelp(wnd
, ThisHelp
->NextName
);
100 if (LastStack
!= NULL
) {
101 if (LastStack
->PrevStack
!= NULL
) {
102 ThisStack
= LastStack
->PrevStack
;
103 if (LastStack
->hname
!= NULL
)
104 free(LastStack
->hname
);
106 LastStack
= ThisStack
;
107 SelectHelp(wnd
, ThisStack
->hname
);
117 /* ------------- KEYBOARD message ------------ */
118 static BOOL
KeyboardMsg(DFWINDOW wnd
, PARAM p1
)
121 struct keywords
*thisword
;
122 static char HelpName
[50];
124 cwnd
= ControlWindow(wnd
->extension
, ID_HELPTEXT
);
125 if (cwnd
== NULL
|| inFocus
!= cwnd
)
127 thisword
= cwnd
->thisword
;
130 if (thisword
!= NULL
) {
131 if (thisword
->isDefinition
)
132 DisplayDefinition(GetParent(wnd
),
135 strncpy(HelpName
, thisword
->hname
,
137 SelectHelp(wnd
, HelpName
);
142 if (thisword
== NULL
)
143 thisword
= cwnd
->firstword
;
145 if (thisword
->nextword
== NULL
)
146 thisword
= cwnd
->firstword
;
148 thisword
= thisword
->nextword
;
152 if (thisword
== NULL
)
153 thisword
= cwnd
->lastword
;
155 if (thisword
->prevword
== NULL
)
156 thisword
= cwnd
->lastword
;
158 thisword
= thisword
->prevword
;
165 if (thisword
!= NULL
) {
166 cwnd
->thisword
= thisword
;
167 if (thisword
->lineno
< cwnd
->wtop
||
169 cwnd
->wtop
+ ClientHeight(cwnd
)) {
170 int distance
= ClientHeight(cwnd
)/2;
172 cwnd
->wtop
= thisword
->lineno
-distance
;
175 while (cwnd
->wtop
< 0);
177 DfSendMessage(cwnd
, PAINT
, 0, 0);
183 /* ---- window processing module for the HELPBOX ------- */
184 int HelpBoxProc(DFWINDOW wnd
, DFMESSAGE msg
, PARAM p1
, PARAM p2
)
186 DBOX
*db
= wnd
->extension
;
190 CreateWindowMsg(wnd
);
192 case INITIATE_DIALOG
:
198 if (CommandMsg(wnd
, p1
))
204 if (KeyboardMsg(wnd
, p1
))
209 if (db
->dwnd
.title
!= NULL
) {
210 free(db
->dwnd
.title
);
211 db
->dwnd
.title
= NULL
;
215 if (ThisHelp
!= NULL
)
216 ThisHelp
->hwnd
= NULL
;
222 return BaseWndProc(HELPBOX
, wnd
, msg
, p1
, p2
);
225 /* ----- select a new help window from its name ----- */
226 static void SelectHelp(DFWINDOW wnd
, char *hname
)
229 DFWINDOW pwnd
= GetParent(wnd
);
230 DfPostMessage(wnd
, ENDDIALOG
, 0, 0);
231 DfPostMessage(pwnd
, DISPLAY_HELP
, (PARAM
) hname
, 0);
235 /* ---- PAINT message for the helpbox text editbox ---- */
236 static int PaintMsg(DFWINDOW wnd
, PARAM p1
, PARAM p2
)
238 struct keywords
*thisword
;
240 if (wnd
->thisword
!= NULL
) {
241 DFWINDOW pwnd
= GetParent(wnd
);
243 thisword
= wnd
->thisword
;
244 cp
= TextLine(wnd
, thisword
->lineno
);
245 cp
+= thisword
->off1
;
247 (pwnd
->WindowColors
[SELECT_COLOR
][FG
] & 255) | 0x80;
249 (pwnd
->WindowColors
[SELECT_COLOR
][BG
] & 255) | 0x80;
250 rtn
= DefaultWndProc(wnd
, PAINT
, p1
, p2
);
252 (pwnd
->WindowColors
[HILITE_COLOR
][FG
] & 255) | 0x80;
254 (pwnd
->WindowColors
[HILITE_COLOR
][BG
] & 255) | 0x80;
257 return DefaultWndProc(wnd
, PAINT
, p1
, p2
);
260 /* ---- LEFT_BUTTON message for the helpbox text editbox ---- */
261 static int LeftButtonMsg(DFWINDOW wnd
, PARAM p1
, PARAM p2
)
263 struct keywords
*thisword
;
266 rtn
= DefaultWndProc(wnd
, LEFT_BUTTON
, p1
, p2
);
267 mx
= (int)p1
- GetClientLeft(wnd
);
268 my
= (int)p2
- GetClientTop(wnd
);
270 thisword
= wnd
->firstword
;
271 while (thisword
!= NULL
) {
272 if (my
== thisword
->lineno
) {
273 if (mx
>= thisword
->off2
&&
274 mx
< thisword
->off3
) {
275 wnd
->thisword
= thisword
;
276 DfSendMessage(wnd
, PAINT
, 0, 0);
277 if (thisword
->isDefinition
) {
278 DFWINDOW pwnd
= GetParent(wnd
);
280 DisplayDefinition(GetParent(pwnd
),
286 thisword
= thisword
->nextword
;
291 /* --- window processing module for HELPBOX's text EDITBOX -- */
292 int HelpTextProc(DFWINDOW wnd
, DFMESSAGE msg
, PARAM p1
, PARAM p2
)
294 struct keywords
*thisword
;
297 return PaintMsg(wnd
, p1
, p2
);
299 return LeftButtonMsg(wnd
, p1
, p2
);
301 DfPostMessage(wnd
, KEYBOARD
, '\r', 0);
304 thisword
= wnd
->firstword
;
305 while (thisword
!= NULL
) {
306 struct keywords
*nextword
= thisword
->nextword
;
307 if (thisword
->hname
!= NULL
)
308 free(thisword
->hname
);
316 return DefaultWndProc(wnd
, msg
, p1
, p2
);
319 /* -------- read the help text into the editbox ------- */
320 static void ReadHelp(DFWINDOW wnd
)
322 DFWINDOW cwnd
= ControlWindow(wnd
->extension
, ID_HELPTEXT
);
326 cwnd
->wndproc
= HelpTextProc
;
327 /* ----- read the help text ------- */
329 unsigned char *cp
= hline
, *cp1
;
331 if (GetHelpLine(hline
) == NULL
)
335 hline
[strlen(hline
)-1] = '\0';
336 /* --- add help text to the help window --- */
338 if ((cp
= strchr(cp
, '[')) != NULL
) {
339 /* ----- hit a new key word ----- */
340 struct keywords
*thisword
;
341 if (*(cp
+1) != '.' && *(cp
+1) != '*') {
345 thisword
= DFcalloc(1, sizeof(struct keywords
));
346 if (cwnd
->firstword
== NULL
)
347 cwnd
->firstword
= thisword
;
348 if (cwnd
->lastword
!= NULL
) {
350 (cwnd
->lastword
))->nextword
= thisword
;
351 thisword
->prevword
= cwnd
->lastword
;
353 cwnd
->lastword
= thisword
;
354 thisword
->lineno
= cwnd
->wlines
;
355 thisword
->off1
= (int) ((int)cp
- (int)hline
);
356 thisword
->off2
= thisword
->off1
- colorct
* 4;
357 thisword
->isDefinition
= *(cp
+1) == '*';
361 (wnd
->WindowColors
[HILITE_COLOR
] [FG
] & 255) | 0x80;
363 (wnd
->WindowColors
[HILITE_COLOR
] [BG
] & 255) | 0x80;
365 if ((cp
= strchr(cp
, ']')) != NULL
) {
366 if (thisword
!= NULL
)
368 thisword
->off2
+ (int) (cp
- cp1
);
371 if ((cp
= strchr(cp
, '<')) != NULL
) {
372 char *cp1
= strchr(cp
, '>');
374 int len
= (int) ((int)cp1
- (int)cp
);
375 thisword
->hname
= DFcalloc(1, len
);
376 strncpy(thisword
->hname
, cp
+1, len
-1);
377 memmove(cp
, cp1
+1, strlen(cp1
));
382 PutItemText(wnd
, ID_HELPTEXT
, hline
);
383 /* -- display help text as soon as window is full -- */
384 if (++linectr
== ClientHeight(cwnd
))
385 DfSendMessage(cwnd
, PAINT
, 0, 0);
386 if (linectr
> ClientHeight(cwnd
) &&
387 !TestAttribute(cwnd
, VSCROLLBAR
)) {
388 AddAttribute(cwnd
, VSCROLLBAR
);
389 DfSendMessage(cwnd
, BORDER
, 0, 0);
394 /* ---- compute the displayed length of a help text line --- */
395 static int HelpLength(char *s
)
398 char *cp
= strchr(s
, '[');
401 cp
= strchr(cp
+1, '[');
405 char *cp1
= strchr(cp
, '>');
407 len
-= (int) (cp1
-cp
)+1;
408 cp
= strchr(cp1
, '<');
413 /* ----------- load the help text file ------------ */
421 if ((helpfp
= OpenHelpFile()) == NULL
)
424 while (*hline
!= '<') {
425 if (GetHelpLine(hline
) == NULL
) {
430 while (*hline
== '<') {
431 if (strncmp(hline
, "<end>", 5) == 0)
434 /* -------- parse the help window's text name ----- */
435 if ((cp
= strchr(hline
, '>')) != NULL
) {
436 ThisHelp
= DFcalloc(1, sizeof(struct helps
));
437 if (FirstHelp
== NULL
)
438 FirstHelp
= ThisHelp
;
440 ThisHelp
->hname
=DFmalloc(strlen(hline
+1)+1);
441 strcpy(ThisHelp
->hname
, hline
+1);
443 HelpFilePosition(&ThisHelp
->hptr
, &ThisHelp
->bit
);
445 if (GetHelpLine(hline
) == NULL
)
448 /* ------- build the help linked list entry --- */
449 while (*hline
== '[') {
450 HelpFilePosition(&ThisHelp
->hptr
,
452 /* ---- parse the <<prev button pointer ---- */
453 if (strncmp(hline
, "[<<]", 4) == 0) {
454 char *cp
= strchr(hline
+4, '<');
456 char *cp1
= strchr(cp
, '>');
458 int len
= (int) (cp1
-cp
);
459 ThisHelp
->PrevName
=DFcalloc(1,len
);
460 strncpy(ThisHelp
->PrevName
,
464 if (GetHelpLine(hline
) == NULL
)
468 /* ---- parse the next>> button pointer ---- */
469 else if (strncmp(hline
, "[>>]", 4) == 0) {
470 char *cp
= strchr(hline
+4, '<');
472 char *cp1
= strchr(cp
, '>');
474 int len
= (int) (cp1
-cp
);
475 ThisHelp
->NextName
=DFcalloc(1,len
);
476 strncpy(ThisHelp
->NextName
,
480 if (GetHelpLine(hline
) == NULL
)
487 ThisHelp
->hheight
= 0;
488 ThisHelp
->hwidth
= 0;
489 ThisHelp
->NextHelp
= NULL
;
491 /* ------ append entry to the linked list ------ */
492 if (LastHelp
!= NULL
)
493 LastHelp
->NextHelp
= ThisHelp
;
496 /* -------- move to the next <helpname> token ------ */
497 if (GetHelpLine(hline
) == NULL
)
498 strcpy(hline
, "<end>");
499 while (*hline
!= '<') {
501 max(ThisHelp
->hwidth
, HelpLength(hline
));
503 if (GetHelpLine(hline
) == NULL
)
504 strcpy(hline
, "<end>");
510 /* ------ free the memory used by the help file table ------ */
511 void UnLoadHelpFile(void)
513 while (FirstHelp
!= NULL
) {
514 ThisHelp
= FirstHelp
;
515 if (ThisHelp
->hname
!= NULL
)
516 free(ThisHelp
->hname
);
517 if (ThisHelp
->PrevName
!= NULL
)
518 free(ThisHelp
->PrevName
);
519 if (ThisHelp
->NextName
!= NULL
)
520 free(ThisHelp
->NextName
);
521 FirstHelp
= ThisHelp
->NextHelp
;
524 ThisHelp
= LastHelp
= NULL
;
529 /* ---------- display a specified help text ----------- */
530 BOOL
DisplayHelp(DFWINDOW wnd
, char *Help
)
537 if (ThisHelp
!= NULL
) {
538 if (LastStack
== NULL
||
539 stricmp(Help
, LastStack
->hname
)) {
540 /* ---- add the window to the history stack ---- */
541 ThisStack
= DFcalloc(1,sizeof(struct HelpStack
));
542 ThisStack
->hname
= DFmalloc(strlen(Help
)+1);
543 if (ThisStack
->hname
!= NULL
)
544 strcpy(ThisStack
->hname
, Help
);
545 ThisStack
->PrevStack
= LastStack
;
546 LastStack
= ThisStack
;
548 if ((helpfp
= OpenHelpFile()) != NULL
) {
552 db
= DFcalloc(1,sizeof HelpBox
);
553 memcpy(db
, &HelpBox
, sizeof HelpBox
);
554 /* -- seek to the first line of the help text -- */
555 SeekHelpLine(ThisHelp
->hptr
, ThisHelp
->bit
);
556 /* ----- read the title ----- */
558 hline
[strlen(hline
)-1] = '\0';
559 db
->dwnd
.title
= DFmalloc(strlen(hline
)+1);
560 strcpy(db
->dwnd
.title
, hline
);
561 /* ----- set the height and width ----- */
562 db
->dwnd
.h
= min(ThisHelp
->hheight
, MAXHEIGHT
)+7;
563 db
->dwnd
.w
= max(45, ThisHelp
->hwidth
+6);
564 /* ------ position the help window ----- */
565 BestFit(wnd
, &db
->dwnd
);
566 /* ------- position the command buttons ------ */
567 db
->ctl
[0].dwnd
.w
= max(40, ThisHelp
->hwidth
+2);
569 min(ThisHelp
->hheight
, MAXHEIGHT
)+2;
570 offset
= (db
->dwnd
.w
-40) / 2;
571 for (i
= 1; i
< 5; i
++) {
573 min(ThisHelp
->hheight
, MAXHEIGHT
)+3;
574 db
->ctl
[i
].dwnd
.x
+= offset
;
576 /* ---- disable ineffective buttons ---- */
577 if (ThisStack
!= NULL
)
578 if (ThisStack
->PrevStack
== NULL
)
579 DisableButton(db
, ID_BACK
);
580 if (ThisHelp
->NextName
== NULL
)
581 DisableButton(db
, ID_NEXT
);
582 if (ThisHelp
->PrevName
== NULL
)
583 DisableButton(db
, ID_PREV
);
584 /* ------- display the help window ----- */
585 DfDialogBox(NULL
, db
, TRUE
, HelpBoxProc
);
595 /* ------- display a definition window --------- */
596 static void DisplayDefinition(DFWINDOW wnd
, char *def
)
602 if (GetClass(wnd
) == POPDOWNMENU
)
603 hwnd
= GetParent(wnd
);
604 y
= GetClass(hwnd
) == MENUBAR
? 2 : 1;
606 if (ThisHelp
!= NULL
) {
607 if ((helpfp
= OpenHelpFile()) != NULL
) {
608 dwnd
= DfCreateWindow(
612 GetClientTop(hwnd
)+y
,
613 min(ThisHelp
->hheight
, MAXHEIGHT
)+3,
618 HASBORDER
| NOCLIP
| SAVESELF
);
620 /* ----- read the help text ------- */
621 SeekHelpLine(ThisHelp
->hptr
, ThisHelp
->bit
);
623 if (GetHelpLine(hline
) == NULL
)
627 hline
[strlen(hline
)-1] = '\0';
628 DfSendMessage(dwnd
,ADDTEXT
,(PARAM
)hline
,0);
630 DfSendMessage(dwnd
, SHOW_WINDOW
, 0, 0);
631 DfSendMessage(NULL
, WAITKEYBOARD
, 0, 0);
632 DfSendMessage(NULL
, WAITMOUSE
, 0, 0);
633 DfSendMessage(dwnd
, CLOSE_WINDOW
, 0, 0);
640 /* ------ compare help names with wild cards ----- */
641 static BOOL
wildcmp(char *s1
, char *s2
)
644 if (tolower(*s1
) != tolower(*s2
))
645 if (*s1
!= '?' && *s2
!= '?')
652 /* --- ThisHelp = the help window matching specified name --- */
653 static void FindHelp(char *Help
)
655 ThisHelp
= FirstHelp
;
656 while (ThisHelp
!= NULL
) {
657 if (wildcmp(Help
, ThisHelp
->hname
) == FALSE
)
659 ThisHelp
= ThisHelp
->NextHelp
;
663 /* --- ThisHelp = the help window matching specified wnd --- */
664 static void FindHelpWindow(DFWINDOW wnd
)
666 ThisHelp
= FirstHelp
;
667 while (ThisHelp
!= NULL
) {
668 if (wnd
== ThisHelp
->hwnd
)
670 ThisHelp
= ThisHelp
->NextHelp
;
674 static int OverLap(int a
, int b
)
682 /* ----- compute the best location for a help dialogbox ----- */
683 static void BestFit(DFWINDOW wnd
, DIALOGWINDOW
*dwnd
)
685 int above
, below
, right
, left
;
686 if (GetClass(wnd
) == MENUBAR
||
687 GetClass(wnd
) == APPLICATION
) {
688 dwnd
->x
= dwnd
->y
= -1;
691 /* --- compute above overlap ---- */
692 above
= OverLap(dwnd
->h
, GetTop(wnd
));
693 /* --- compute below overlap ---- */
694 below
= OverLap(GetBottom(wnd
), DfGetScreenHeight()-dwnd
->h
);
695 /* --- compute right overlap ---- */
696 right
= OverLap(GetRight(wnd
), DfGetScreenWidth()-dwnd
->w
);
697 /* --- compute left overlap ---- */
698 left
= OverLap(dwnd
->w
, GetLeft(wnd
));
701 dwnd
->y
= max(0, GetTop(wnd
)-dwnd
->h
-2);
703 dwnd
->y
= min(DfGetScreenHeight()-dwnd
->h
, GetBottom(wnd
)+2);
705 dwnd
->x
= min(GetRight(wnd
)+2, DfGetScreenWidth()-dwnd
->w
);
707 dwnd
->x
= max(0, GetLeft(wnd
)-dwnd
->w
-2);
709 if (dwnd
->x
== GetRight(wnd
)+2 ||
710 dwnd
->x
== GetLeft(wnd
)-dwnd
->w
-2)
712 if (dwnd
->y
==GetTop(wnd
)-dwnd
->h
-2 ||
713 dwnd
->y
== GetBottom(wnd
)+2)