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