home *** CD-ROM | disk | FTP | other *** search
/ Media Share 9 / MEDIASHARE_09.ISO / cprog / dflt14.zip / HELPBOX.C < prev    next >
Text File  |  1992-08-12  |  23KB  |  718 lines

  1. /* ------------ helpbox.c ----------- */
  2.  
  3. #include "dflat.h"
  4. #include "htree.h"
  5.  
  6. extern DBOX HelpBox;
  7.  
  8. /* -------- strings of D-Flat classes for calling default
  9.       help text collections -------- */
  10. char *ClassNames[] = {
  11.     #undef ClassDef
  12.     #define ClassDef(c,b,p,a) #c,
  13.     #include "classes.h"
  14.     NULL
  15. };
  16.  
  17. #define MAXHEIGHT (SCREENHEIGHT-10)
  18.  
  19. /* --------- linked list of help text collections -------- */
  20. struct helps {
  21.     char *hname;
  22.     char *NextName;
  23.     char *PrevName;
  24.     long hptr;
  25.     int bit;
  26.     int hheight;
  27.     int hwidth;
  28.     WINDOW hwnd;
  29.     struct helps *NextHelp;
  30. };
  31. static struct helps *FirstHelp;
  32. static struct helps *LastHelp;
  33. static struct helps *ThisHelp;
  34.  
  35. /* --- linked stack of help windows that have beed used --- */
  36. struct HelpStack {
  37.     char *hname;
  38.     struct HelpStack *PrevStack;
  39. };
  40. static struct HelpStack *LastStack;
  41. static struct HelpStack *ThisStack;
  42.  
  43. /* --- linked list of keywords in the current help
  44.            text collection (listhead is in window) -------- */
  45. struct keywords {
  46.     char *hname;
  47.     int lineno;
  48.     int off1, off2, off3;
  49.     int isDefinition;
  50.     struct keywords *nextword;
  51.     struct keywords *prevword;
  52. };
  53.  
  54. static FILE *helpfp;
  55. static char hline [160];
  56. static BOOL Helping;
  57.  
  58. static void SelectHelp(WINDOW, char *);
  59. static void ReadHelp(WINDOW);
  60. static void FindHelp(char *);
  61. static void FindHelpWindow(WINDOW);
  62. static void DisplayDefinition(WINDOW, char *);
  63. static void BestFit(WINDOW, DIALOGWINDOW *);
  64.  
  65. /* ------------- CREATE_WINDOW message ------------ */
  66. static void CreateWindowMsg(WINDOW wnd)
  67. {
  68.     Helping = TRUE;
  69.     GetClass(wnd) = HELPBOX;
  70.     InitWindowColors(wnd);
  71.     if (ThisHelp != NULL)
  72.         ThisHelp->hwnd = wnd;
  73. }
  74.  
  75. /* ------------- COMMAND message ------------ */
  76. static BOOL CommandMsg(WINDOW wnd, PARAM p1)
  77. {
  78.     switch ((int)p1)    {
  79.         case ID_CANCEL:
  80.             ThisStack = LastStack;
  81.             while (ThisStack != NULL)    {
  82.                 LastStack = ThisStack->PrevStack;
  83.                 if (ThisStack->hname != NULL)
  84.                     free(ThisStack->hname);
  85.                 free(ThisStack);
  86.                 ThisStack = LastStack;
  87.             }
  88.             break;
  89.         case ID_PREV:
  90.             FindHelpWindow(wnd);
  91.             if (ThisHelp != NULL)
  92.                 SelectHelp(wnd, ThisHelp->PrevName);
  93.             return TRUE;
  94.         case ID_NEXT:
  95.             FindHelpWindow(wnd);
  96.             if (ThisHelp != NULL)
  97.                 SelectHelp(wnd, ThisHelp->NextName);
  98.             return TRUE;
  99.         case ID_BACK:
  100.             if (LastStack != NULL)    {
  101.                 if (LastStack->PrevStack != NULL)    {
  102.                     ThisStack = LastStack->PrevStack;
  103.                     if (LastStack->hname != NULL)
  104.                         free(LastStack->hname);
  105.                     free(LastStack);
  106.                     LastStack = ThisStack;
  107.                     SelectHelp(wnd, ThisStack->hname);
  108.                 }
  109.             }
  110.             return TRUE;
  111.         default:
  112.             break;
  113.     }
  114.     return FALSE;
  115. }
  116.  
  117. /* ------------- KEYBOARD message ------------ */
  118. static BOOL KeyboardMsg(WINDOW wnd, PARAM p1)
  119. {
  120.     WINDOW cwnd;
  121.     struct keywords *thisword;
  122.     static char HelpName[50];
  123.  
  124.     cwnd = ControlWindow(wnd->extension, ID_HELPTEXT);
  125.     if (cwnd == NULL || inFocus != cwnd)
  126.         return FALSE;
  127.     thisword = cwnd->thisword;
  128.     switch ((int)p1)    {
  129.         case '\r':
  130.             if (thisword != NULL)    {
  131.                 if (thisword->isDefinition)
  132.                     DisplayDefinition(GetParent(wnd),
  133.                                         thisword->hname);
  134.                 else    {
  135.                     strncpy(HelpName, thisword->hname,
  136.                         sizeof HelpName);
  137.                     SelectHelp(wnd, HelpName);
  138.                 }
  139.             }
  140.             return TRUE;
  141.         case '\t':
  142.             if (thisword == NULL)
  143.                 thisword = cwnd->firstword;
  144.             else {
  145.                 if (thisword->nextword == NULL)
  146.                     thisword = cwnd->firstword;
  147.                 else
  148.                     thisword = thisword->nextword;
  149.             }
  150.             break;
  151.         case SHIFT_HT:
  152.             if (thisword == NULL)
  153.                 thisword = cwnd->lastword;
  154.             else {
  155.                 if (thisword->prevword == NULL)
  156.                     thisword = cwnd->lastword;
  157.                 else
  158.                     thisword = thisword->prevword;
  159.             }
  160.             break;
  161.         default:
  162.             thisword = NULL;
  163.             break;
  164.     }
  165.     if (thisword != NULL)    {
  166.         cwnd->thisword = thisword;
  167.         if (thisword->lineno < cwnd->wtop ||
  168.                 thisword->lineno >=
  169.                     cwnd->wtop + ClientHeight(cwnd))  {
  170.             int distance = ClientHeight(cwnd)/2;
  171.             do    {
  172.                 cwnd->wtop = thisword->lineno-distance;
  173.                 distance /= 2;
  174.             }
  175.             while (cwnd->wtop < 0);
  176.         }
  177.         SendMessage(cwnd, PAINT, 0, 0);
  178.         return TRUE;
  179.     }
  180.     return FALSE;
  181. }
  182.  
  183. /* ---- window processing module for the HELPBOX ------- */
  184. int HelpBoxProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
  185. {
  186.     DBOX *db = wnd->extension;
  187.  
  188.     switch (msg)    {
  189.         case CREATE_WINDOW:
  190.             CreateWindowMsg(wnd);
  191.             break;
  192.         case INITIATE_DIALOG:
  193.             ReadHelp(wnd);
  194.             break;
  195.         case COMMAND:
  196.             if (p2 != 0)
  197.                 break;
  198.             if (CommandMsg(wnd, p1))
  199.                 return TRUE;
  200.             break;
  201.         case KEYBOARD:
  202.             if (WindowMoving)
  203.                 break;
  204.             if (KeyboardMsg(wnd, p1))
  205.                 return TRUE;
  206.             break;
  207.         case CLOSE_WINDOW:
  208.             if (db != NULL)    {
  209.                 if (db->dwnd.title != NULL)    {
  210.                     free(db->dwnd.title);
  211.                     db->dwnd.title = NULL;
  212.                 }
  213.             }
  214.             FindHelpWindow(wnd);
  215.             if (ThisHelp != NULL)
  216.                 ThisHelp->hwnd = NULL;
  217.             Helping = FALSE;
  218.             break;
  219.         default:
  220.             break;
  221.     }
  222.     return BaseWndProc(HELPBOX, wnd, msg, p1, p2);
  223. }
  224.  
  225. /* ----- select a new help window from its name ----- */
  226. static void SelectHelp(WINDOW wnd, char *hname)
  227. {
  228.     if (hname != NULL)    {
  229.         WINDOW pwnd = GetParent(wnd);
  230.         PostMessage(wnd, ENDDIALOG, 0, 0);
  231.         PostMessage(pwnd, DISPLAY_HELP, (PARAM) hname, 0);
  232.     }
  233. }
  234.  
  235. /* ---- PAINT message for the helpbox text editbox ---- */
  236. static int PaintMsg(WINDOW wnd, PARAM p1, PARAM p2)
  237. {
  238.     struct keywords *thisword;
  239.     int rtn;
  240.     if (wnd->thisword != NULL)    {
  241.         WINDOW pwnd = GetParent(wnd);
  242.         char *cp;
  243.         thisword = wnd->thisword;
  244.         cp = TextLine(wnd, thisword->lineno);
  245.         cp += thisword->off1;
  246.         *(cp+1) =
  247.             (pwnd->WindowColors[SELECT_COLOR][FG] & 255) | 0x80;
  248.         *(cp+2) =
  249.             (pwnd->WindowColors[SELECT_COLOR][BG] & 255) | 0x80;
  250.         rtn = DefaultWndProc(wnd, PAINT, p1, p2);
  251.         *(cp+1) =
  252.             (pwnd->WindowColors[HILITE_COLOR][FG] & 255) | 0x80;
  253.         *(cp+2) =
  254.             (pwnd->WindowColors[HILITE_COLOR][BG] & 255) | 0x80;
  255.         return rtn;
  256.     }
  257.     return DefaultWndProc(wnd, PAINT, p1, p2);
  258. }
  259.  
  260. /* ---- LEFT_BUTTON message for the helpbox text editbox ---- */
  261. static int LeftButtonMsg(WINDOW wnd, PARAM p1, PARAM p2)
  262. {
  263.     struct keywords *thisword;
  264.     int rtn, mx, my;
  265.  
  266.     rtn = DefaultWndProc(wnd, LEFT_BUTTON, p1, p2);
  267.     mx = (int)p1 - GetClientLeft(wnd);
  268.     my = (int)p2 - GetClientTop(wnd);
  269.     my += wnd->wtop;
  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.                 SendMessage(wnd, PAINT, 0, 0);
  277.                 if (thisword->isDefinition)    {
  278.                     WINDOW pwnd = GetParent(wnd);
  279.                     if (pwnd != NULL)
  280.                         DisplayDefinition(GetParent(pwnd),
  281.                             thisword->hname);
  282.                 }
  283.                 break;
  284.             }
  285.         }
  286.         thisword = thisword->nextword;
  287.     }
  288.     return rtn;
  289. }
  290.  
  291. /* --- window processing module for HELPBOX's text EDITBOX -- */
  292. int HelpTextProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
  293. {
  294.     struct keywords *thisword;
  295.     switch (msg)    {
  296.         case PAINT:
  297.             return PaintMsg(wnd, p1, p2);
  298.         case LEFT_BUTTON:
  299.             return LeftButtonMsg(wnd, p1, p2);
  300.         case DOUBLE_CLICK:
  301.             PostMessage(wnd, KEYBOARD, '\r', 0);
  302.             break;
  303.         case CLOSE_WINDOW:
  304.             thisword = wnd->firstword;
  305.             while (thisword != NULL)    {
  306.                 struct keywords *nextword = thisword->nextword;
  307.                 if (thisword->hname != NULL)
  308.                     free(thisword->hname);
  309.                 free(thisword);
  310.                 thisword = nextword;
  311.             }
  312.             break;
  313.         default:
  314.             break;
  315.     }
  316.     return DefaultWndProc(wnd, msg, p1, p2);
  317. }
  318.  
  319. /* -------- read the help text into the editbox ------- */
  320. static void ReadHelp(WINDOW wnd)
  321. {
  322.     WINDOW cwnd = ControlWindow(wnd->extension, ID_HELPTEXT);
  323.     int linectr = 0;
  324.     if (cwnd == NULL)
  325.         return;
  326.     cwnd->wndproc = HelpTextProc;
  327.     /* ----- read the help text ------- */
  328.     while (TRUE)    {
  329.         unsigned char *cp = hline, *cp1;
  330.         int colorct = 0;
  331.         if (GetHelpLine(hline) == NULL)
  332.             break;
  333.         if (*hline == '<')
  334.             break;
  335.         hline[strlen(hline)-1] = '\0';
  336.         /* --- add help text to the help window --- */
  337.         while (cp != NULL)    {
  338.             if ((cp = strchr(cp, '[')) != NULL)    {
  339.                 /* ----- hit a new key word ----- */
  340.                 struct keywords *thisword;
  341.                 if (*(cp+1) != '.' && *(cp+1) != '*')    {
  342.                     cp++;
  343.                     continue;
  344.                 }
  345.                 thisword = DFcalloc(1, sizeof(struct keywords));
  346.                 if (cwnd->firstword == NULL)
  347.                     cwnd->firstword = thisword;
  348.                 if (cwnd->lastword != NULL)    {
  349.                     ((struct keywords *)
  350.                         (cwnd->lastword))->nextword = thisword;
  351.                     thisword->prevword = cwnd->lastword;
  352.                 }
  353.                 cwnd->lastword = thisword;
  354.                 thisword->lineno = cwnd->wlines;
  355.                 thisword->off1 = (int) (cp - hline);
  356.                 thisword->off2 = thisword->off1 - colorct * 4;
  357.                 thisword->isDefinition = *(cp+1) == '*';
  358.                 colorct++;
  359.                 *cp++ = CHANGECOLOR;
  360.                 *cp++ =
  361.             (wnd->WindowColors [HILITE_COLOR] [FG] & 255) | 0x80;
  362.                 *cp++ =
  363.             (wnd->WindowColors [HILITE_COLOR] [BG] & 255) | 0x80;
  364.                 cp1 = cp;
  365.                 if ((cp = strchr(cp, ']')) != NULL)    {
  366.                     if (thisword != NULL)
  367.                         thisword->off3 =
  368.                             thisword->off2 + (int) (cp - cp1);
  369.                     *cp++ = RESETCOLOR;
  370.                 }
  371.                 if ((cp = strchr(cp, '<')) != NULL)    {
  372.                     char *cp1 = strchr(cp, '>');
  373.                     if (cp1 != NULL)    {
  374.                         int len = (int) (cp1 - cp);
  375.                         thisword->hname = DFcalloc(1, len);
  376.                         strncpy(thisword->hname, cp+1, len-1);
  377.                         memmove(cp, cp1+1, strlen(cp1));
  378.                     }
  379.                 }
  380.             }
  381.         }
  382.         PutItemText(wnd, ID_HELPTEXT, hline);
  383.         /* -- display help text as soon as window is full -- */
  384.         if (++linectr == ClientHeight(cwnd))
  385.             SendMessage(cwnd, PAINT, 0, 0);
  386.         if (linectr > ClientHeight(cwnd) &&
  387.                 !TestAttribute(cwnd, VSCROLLBAR))    {
  388.             AddAttribute(cwnd, VSCROLLBAR);
  389.             SendMessage(cwnd, BORDER, 0, 0);
  390.         }
  391.     }
  392. }
  393.  
  394. /* ---- compute the displayed length of a help text line --- */
  395. static int HelpLength(char *s)
  396. {
  397.     int len = strlen(s);
  398.     char *cp = strchr(s, '[');
  399.     while (cp != NULL)    {
  400.         len -= 4;
  401.         cp = strchr(cp+1, '[');
  402.     }
  403.     cp = strchr(s, '<');
  404.     while (cp != NULL)    {
  405.         char *cp1 = strchr(cp, '>');
  406.         if (cp1 != NULL)
  407.             len -= (int) (cp1-cp)+1;
  408.         cp = strchr(cp1, '<');
  409.     }
  410.     return len;
  411. }
  412.  
  413. /* ----------- load the help text file ------------ */
  414. void LoadHelpFile()
  415. {
  416.     char *cp;
  417.  
  418.     if (Helping)
  419.         return;
  420.     UnLoadHelpFile();
  421.     if ((helpfp = OpenHelpFile()) == NULL)
  422.         return;
  423.     *hline = '\0';
  424.     while (*hline != '<')    {
  425.         if (GetHelpLine(hline) == NULL)    {
  426.             fclose(helpfp);
  427.             return;
  428.         }
  429.     }
  430.     while (*hline == '<')   {
  431.         if (strncmp(hline, "<end>", 5) == 0)
  432.             break;
  433.  
  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;
  439.             *cp = '\0';
  440.             ThisHelp->hname=DFmalloc(strlen(hline+1)+1);
  441.             strcpy(ThisHelp->hname, hline+1);
  442.  
  443.             HelpFilePosition(&ThisHelp->hptr, &ThisHelp->bit);
  444.  
  445.             if (GetHelpLine(hline) == NULL)
  446.                 break;
  447.  
  448.             /* ------- build the help linked list entry --- */
  449.             while (*hline == '[')    {
  450.                 HelpFilePosition(&ThisHelp->hptr,
  451.                                             &ThisHelp->bit);
  452.                 /* ---- parse the <<prev button pointer ---- */
  453.                 if (strncmp(hline, "[<<]", 4) == 0)    {
  454.                     char *cp = strchr(hline+4, '<');
  455.                     if (cp != NULL)    {
  456.                         char *cp1 = strchr(cp, '>');
  457.                         if (cp1 != NULL)    {
  458.                             int len = (int) (cp1-cp);
  459.                             ThisHelp->PrevName=DFcalloc(1,len);
  460.                             strncpy(ThisHelp->PrevName,
  461.                                 cp+1,len-1);
  462.                         }
  463.                     }
  464.                     if (GetHelpLine(hline) == NULL)
  465.                         break;
  466.                     continue;
  467.                 }
  468.                 /* ---- parse the next>> button pointer ---- */
  469.                 else if (strncmp(hline, "[>>]", 4) == 0)    {
  470.                     char *cp = strchr(hline+4, '<');
  471.                     if (cp != NULL)    {
  472.                         char *cp1 = strchr(cp, '>');
  473.                         if (cp1 != NULL)    {
  474.                             int len = (int) (cp1-cp);
  475.                             ThisHelp->NextName=DFcalloc(1,len);
  476.                             strncpy(ThisHelp->NextName,
  477.                                             cp+1,len-1);
  478.                         }
  479.                     }
  480.                     if (GetHelpLine(hline) == NULL)
  481.                         break;
  482.                     continue;
  483.                 }
  484.                 else
  485.                     break;
  486.             }
  487.             ThisHelp->hheight = 0;
  488.             ThisHelp->hwidth = 0;
  489.             ThisHelp->NextHelp = NULL;
  490.  
  491.             /* ------ append entry to the linked list ------ */
  492.             if (LastHelp != NULL)
  493.                 LastHelp->NextHelp = ThisHelp;
  494.             LastHelp = ThisHelp;
  495.         }
  496.         /* -------- move to the next <helpname> token ------ */
  497.         if (GetHelpLine(hline) == NULL)
  498.             strcpy(hline, "<end>");
  499.         while (*hline != '<')    {
  500.             ThisHelp->hwidth =
  501.                 max(ThisHelp->hwidth, HelpLength(hline));
  502.             ThisHelp->hheight++;
  503.             if (GetHelpLine(hline) == NULL)
  504.                 strcpy(hline, "<end>");
  505.         }
  506.     }
  507.     fclose(helpfp);
  508. }
  509.  
  510. /* ------ free the memory used by the help file table ------ */
  511. void UnLoadHelpFile(void)
  512. {
  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;
  522.         free(ThisHelp);
  523.     }
  524.     ThisHelp = LastHelp = NULL;
  525.     free(HelpTree);
  526.     HelpTree = NULL;
  527. }
  528.  
  529. /* ---------- display a specified help text ----------- */
  530. BOOL DisplayHelp(WINDOW wnd, char *Help)
  531. {
  532.     if (Helping)
  533.         return TRUE;
  534.     FindHelp(Help);
  535.     if (ThisHelp != NULL)    {
  536.         if (LastStack == NULL ||
  537.                 stricmp(Help, LastStack->hname))    {
  538.             /* ---- add the window to the history stack ---- */
  539.             ThisStack = DFcalloc(1,sizeof(struct HelpStack));
  540.             ThisStack->hname = DFmalloc(strlen(Help)+1);
  541.             if (ThisStack->hname != NULL)
  542.                 strcpy(ThisStack->hname, Help);
  543.             ThisStack->PrevStack = LastStack;
  544.             LastStack = ThisStack;
  545.         }
  546.         if ((helpfp = OpenHelpFile()) != NULL)    {
  547.             DBOX *db;
  548.             int offset, i;
  549.  
  550.             db = DFcalloc(1,sizeof HelpBox);
  551.             memcpy(db, &HelpBox, sizeof HelpBox);
  552.             /* -- seek to the first line of the help text -- */
  553.             SeekHelpLine(ThisHelp->hptr, ThisHelp->bit);
  554.             /* ----- read the title ----- */
  555.             GetHelpLine(hline);
  556.             hline[strlen(hline)-1] = '\0';
  557.             db->dwnd.title = DFmalloc(strlen(hline)+1);
  558.             strcpy(db->dwnd.title, hline);
  559.             /* ----- set the height and width ----- */
  560.             db->dwnd.h = min(ThisHelp->hheight, MAXHEIGHT)+7;
  561.             db->dwnd.w = max(45, ThisHelp->hwidth+6);
  562.             /* ------ position the help window ----- */
  563.             BestFit(wnd, &db->dwnd);
  564.             /* ------- position the command buttons ------ */
  565.             db->ctl[0].dwnd.w = max(40, ThisHelp->hwidth+2);
  566.             db->ctl[0].dwnd.h =
  567.                         min(ThisHelp->hheight, MAXHEIGHT)+2;
  568.             offset = (db->dwnd.w-40) / 2;
  569.             for (i = 1; i < 5; i++)    {
  570.                 db->ctl[i].dwnd.y =
  571.                         min(ThisHelp->hheight, MAXHEIGHT)+3;
  572.                 db->ctl[i].dwnd.x += offset;
  573.             }
  574.             /* ---- disable ineffective buttons ---- */
  575.             if (ThisStack != NULL)
  576.                 if (ThisStack->PrevStack == NULL)
  577.                     DisableButton(db, ID_BACK);
  578.             if (ThisHelp->NextName == NULL)
  579.                 DisableButton(db, ID_NEXT);
  580.             if (ThisHelp->PrevName == NULL)
  581.                 DisableButton(db, ID_PREV);
  582.             /* ------- display the help window ----- */
  583.             DialogBox(NULL, db, TRUE, HelpBoxProc);
  584.             free(db);
  585.             fclose(helpfp);
  586.             return TRUE;
  587.         }
  588.     }
  589.     return FALSE;
  590. }
  591.  
  592. /* ------- display a definition window --------- */
  593. static void DisplayDefinition(WINDOW wnd, char *def)
  594. {
  595.     WINDOW dwnd;
  596.     WINDOW hwnd = wnd;
  597.     int y;
  598.  
  599.     if (GetClass(wnd) == POPDOWNMENU)
  600.         hwnd = GetParent(wnd);
  601.     y = GetClass(hwnd) == MENUBAR ? 2 : 1;
  602.     FindHelp(def);
  603.     if (ThisHelp != NULL)    {
  604.         clearBIOSbuffer();
  605.         if ((helpfp = OpenHelpFile()) != NULL)    {
  606.             clearBIOSbuffer();
  607.             dwnd = CreateWindow(
  608.                         TEXTBOX,
  609.                         NULL,
  610.                         GetClientLeft(hwnd),
  611.                         GetClientTop(hwnd)+y,
  612.                         min(ThisHelp->hheight, MAXHEIGHT)+3,
  613.                         ThisHelp->hwidth+2,
  614.                         NULL,
  615.                         wnd,
  616.                         NULL,
  617.                         HASBORDER | NOCLIP | SAVESELF);
  618.             if (dwnd != NULL)    {
  619.                 clearBIOSbuffer();
  620.                 /* ----- read the help text ------- */
  621.                 SeekHelpLine(ThisHelp->hptr, ThisHelp->bit);
  622.                 while (TRUE)    {
  623.                     clearBIOSbuffer();
  624.                     if (GetHelpLine(hline) == NULL)
  625.                         break;
  626.                     if (*hline == '<')
  627.                         break;
  628.                     hline[strlen(hline)-1] = '\0';
  629.                     SendMessage(dwnd,ADDTEXT,(PARAM)hline,0);
  630.                 }
  631.                 SendMessage(dwnd, SHOW_WINDOW, 0, 0);
  632.                 SendMessage(NULL, WAITKEYBOARD, 0, 0);
  633.                 SendMessage(NULL, WAITMOUSE, 0, 0);
  634.                 SendMessage(dwnd, CLOSE_WINDOW, 0, 0);
  635.             }
  636.             fclose(helpfp);
  637.         }
  638.     }
  639. }
  640.  
  641. /* ------ compare help names with wild cards ----- */
  642. static BOOL wildcmp(char *s1, char *s2)
  643. {
  644.     while (*s1 || *s2)    {
  645.         if (tolower(*s1) != tolower(*s2))
  646.             if (*s1 != '?' && *s2 != '?')
  647.                 return TRUE;
  648.         s1++, s2++;
  649.     }
  650.     return FALSE;
  651. }
  652.  
  653. /* --- ThisHelp = the help window matching specified name --- */
  654. static void FindHelp(char *Help)
  655. {
  656.     ThisHelp = FirstHelp;
  657.     while (ThisHelp != NULL)    {
  658.         if (wildcmp(Help, ThisHelp->hname) == FALSE)
  659.             break;
  660.         ThisHelp = ThisHelp->NextHelp;
  661.     }
  662. }
  663.  
  664. /* --- ThisHelp = the help window matching specified wnd --- */
  665. static void FindHelpWindow(WINDOW wnd)
  666. {
  667.     ThisHelp = FirstHelp;
  668.     while (ThisHelp != NULL)    {
  669.         if (wnd == ThisHelp->hwnd)
  670.             break;
  671.         ThisHelp = ThisHelp->NextHelp;
  672.     }
  673. }
  674.  
  675. static int OverLap(int a, int b)
  676. {
  677.     int ov = a - b;
  678.     if (ov < 0)
  679.         ov = 0;
  680.     return ov;
  681. }
  682.  
  683. /* ----- compute the best location for a help dialogbox ----- */
  684. static void BestFit(WINDOW wnd, DIALOGWINDOW *dwnd)
  685. {
  686.     int above, below, right, left;
  687.     if (GetClass(wnd) == MENUBAR ||
  688.                 GetClass(wnd) == APPLICATION)    {
  689.         dwnd->x = dwnd->y = -1;
  690.         return;
  691.     }
  692.     /* --- compute above overlap ---- */
  693.     above = OverLap(dwnd->h, GetTop(wnd));
  694.     /* --- compute below overlap ---- */
  695.     below = OverLap(GetBottom(wnd), SCREENHEIGHT-dwnd->h);
  696.     /* --- compute right overlap ---- */
  697.     right = OverLap(GetRight(wnd), SCREENWIDTH-dwnd->w);
  698.     /* --- compute left  overlap ---- */
  699.     left = OverLap(dwnd->w, GetLeft(wnd));
  700.  
  701.     if (above < below)
  702.         dwnd->y = max(0, GetTop(wnd)-dwnd->h-2);
  703.     else
  704.         dwnd->y = min(SCREENHEIGHT-dwnd->h, GetBottom(wnd)+2);
  705.     if (right < left)
  706.         dwnd->x = min(GetRight(wnd)+2, SCREENWIDTH-dwnd->w);
  707.     else
  708.         dwnd->x = max(0, GetLeft(wnd)-dwnd->w-2);
  709.  
  710.     if (dwnd->x == GetRight(wnd)+2 ||
  711.             dwnd->x == GetLeft(wnd)-dwnd->w-2)
  712.         dwnd->y = -1;
  713.     if (dwnd->y ==GetTop(wnd)-dwnd->h-2 ||
  714.             dwnd->y == GetBottom(wnd)+2)
  715.         dwnd->x = -1;
  716. }
  717.  
  718.