home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast2.iso / ddjmag / ddj9209.zip / CPROG.ASC < prev    next >
Text File  |  1992-08-10  |  23KB  |  717 lines

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