home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / drdobbs / 1991 / 08 / dflat5 / helpbox.c < prev    next >
Text File  |  1991-06-28  |  17KB  |  660 lines

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