home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Utilities / Ph 1.1.1 / PhClient / help.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-10-14  |  22.2 KB  |  843 lines  |  [TEXT/MPS ]

  1. /*_____________________________________________________________________
  2.  
  3.       help.c - Help Window Manager
  4. ____________________________________________________________________*/
  5.  
  6. /*_____________________________________________________________________
  7.  
  8.     Header Files.
  9. _____________________________________________________________________*/
  10.  
  11. #pragma load "precompile"
  12. #include "MacTCPCommonTypes.h"
  13. #include "rez.h"
  14. #include "utl.h"
  15. #include "mtcp.h"
  16. #include "serv.h"
  17. #include "glob.h"
  18. #include "help.h"
  19. #include "oop.h"
  20. #include "wstm.h"
  21. #include "site.h"
  22.  
  23. #pragma segment help
  24.  
  25. /*_____________________________________________________________________
  26.  
  27.     Defines.
  28. _____________________________________________________________________*/
  29.  
  30. #define sBarWidth            16            /* width of scroll bar */
  31. #define sBarWidthM1        (sBarWidth-1)
  32. #define textMargin        4            /* left and right margins for text */
  33. #define minWindHeight    150        /* min window height */
  34. /*_____________________________________________________________________
  35.  
  36.     Types.
  37. _____________________________________________________________________*/
  38.  
  39. typedef struct HelpInfo {
  40.     ControlHandle        scrollBar;            /* handle to scroll bar control */
  41.     TEHandle                help;                    /* handle to help terec */
  42.     short                    windNum;                /* window number */
  43.     Str255                server;                /* help server */
  44. } HelpInfo;
  45.  
  46. /*_____________________________________________________________________
  47.  
  48.     Global Variables.
  49. _____________________________________________________________________*/
  50.  
  51. static Rect                SizeRect;                /* size rectangle */
  52.  
  53. static oop_Dispatch dispatch = {
  54.                                 help_DoPeriodic,
  55.                                 help_DoClick,
  56.                                 help_DoKey,
  57.                                 help_DoUpdate,
  58.                                 help_DoActivate,
  59.                                 help_DoDeactivate,
  60.                                 help_DoGrow,
  61.                                 help_DoZoom,
  62.                                 help_DoClose,
  63.                                 help_DoCommand
  64.                             };
  65.  
  66. /*_____________________________________________________________________
  67.  
  68.     GetHelpInfo - Get HelpInfo Handle from Window Pointer
  69.     
  70.     Entry:    w = pointer to window record
  71.     
  72.     Exit:        Function result = handle to HelpInfo record.
  73. _____________________________________________________________________*/
  74.  
  75. static HelpInfo **GetHelpInfo (WindowPtr w)
  76.  
  77. {
  78.     return (HelpInfo**)oop_GetWindInfo(w);
  79. }
  80.  
  81. /*_____________________________________________________________________
  82.  
  83.     GetViewRect - Get View Rectangle.
  84.     
  85.     Entry:    w = pointer to window record.
  86.     
  87.     Exit:        *viewRect = view rectangle.
  88. _____________________________________________________________________*/
  89.  
  90. static void GetViewRect (WindowPtr w, Rect *viewRect)
  91.  
  92. {
  93.     *viewRect = w->portRect;
  94.     viewRect->bottom -= sBarWidthM1;
  95.     viewRect->right -= sBarWidthM1;
  96. }
  97.  
  98. /*_____________________________________________________________________
  99.  
  100.     AdjustScrollMax - Adjust Scroll Bar Max Value.
  101.     
  102.     Entry:    w = pointer to window record.
  103. _____________________________________________________________________*/
  104.  
  105. static void AdjustScrollMax (WindowPtr w)
  106.  
  107. {
  108.     HelpInfo            **e;            /* handle to help info */
  109.     TEHandle            help;            /* handle to help terec */
  110.     Rect                viewRect;    /* view rect */
  111.     short                vHeight;        /* height of view rect */
  112.     short                tHeight;        /* height of reply text */
  113.     short                max;            /* new max control value */
  114.     
  115.     e = GetHelpInfo(w);
  116.     help = (**e).help;
  117.     GetViewRect(w, &viewRect);
  118.     vHeight = viewRect.bottom - viewRect.top;
  119.     tHeight = (**help).destRect.bottom - (**help).destRect.top;
  120.     max = tHeight - vHeight;
  121.     if (max < 0) max = 0;
  122.     SetCtlMax((**e).scrollBar, max);
  123. }
  124.  
  125. /*_____________________________________________________________________
  126.  
  127.     Scroll - Scroll the Window.
  128.     
  129.     Entry:    w = pointer to window record.
  130.                 dv = number of pixels to scroll.
  131. _____________________________________________________________________*/
  132.  
  133. static void Scroll (WindowPtr w, short dv)
  134.  
  135. {
  136.     HelpInfo        **e;            /* handle to help info */
  137.     
  138.     e = GetHelpInfo(w);
  139.     SetPort(w);
  140.     TEScroll(0, dv, (**e).help);
  141.     SetOrigin(0, 0);
  142. }
  143.  
  144. /*_____________________________________________________________________
  145.  
  146.     ChangeSize - Process Window Size Change.
  147.     
  148.     Entry:    w = pointer to window record.
  149.                 height = new window height
  150. _____________________________________________________________________*/
  151.  
  152. static void ChangeSize (WindowPtr w, short height)
  153.  
  154. {
  155.     HelpInfo        **e;                    /* handle to help info */
  156.     Rect            viewRect;            /* view rectangle */
  157.     TEHandle        help;                    /* handle to help terec */
  158.     short            offTop;                /* amount of text scrolled off top */
  159.     short            textBot;                /* bottom text coord */
  160.     short            viewBot;                /* bottom view coord */
  161.     short            dv;                    /* amount to scroll */
  162.  
  163.     e = GetHelpInfo(w);
  164.     SizeControl((**e).scrollBar, sBarWidth, height-13);
  165.     AdjustScrollMax(w);
  166.     GetViewRect(w, &viewRect);
  167.     help = (**e).help;
  168.     InsetRect(&viewRect, textMargin, 0);
  169.     (**help).viewRect = viewRect;
  170.     offTop = -(**help).destRect.top;
  171.     textBot = (**help).destRect.bottom;
  172.     viewBot = w->portRect.bottom - sBarWidthM1;
  173.     if (textBot < viewBot && offTop) {
  174.         dv = viewBot - textBot;
  175.         if (dv > offTop) dv = offTop;
  176.         Scroll(w, dv);
  177.     }
  178. }
  179.  
  180. /*_____________________________________________________________________
  181.  
  182.     ScrollAction - Scroll Bar Action Procedure
  183. _____________________________________________________________________*/
  184.  
  185. static pascal void ScrollAction (ControlHandle scrollBar, short partCode)
  186.  
  187. {
  188.     WindowPtr        w;                    /* pointer to window */
  189.     HelpInfo            **e;                /* handle to help info */
  190.     short                val;                /* scroll bar value */
  191.     short                min;                /* scroll bar minimum value */
  192.     short                max;                /* scroll bar maximum value */
  193.     short                viewHeight;        /* height of view rectangle */
  194.     short                lineHeight;        /* height of one line */
  195.     short                dv;                /* amount to scroll */
  196.     
  197.     w = FrontWindow();
  198.     e = GetHelpInfo(w);
  199.     val = (**scrollBar).contrlValue;
  200.     min = (**scrollBar).contrlMin;
  201.     max = (**scrollBar).contrlMax;
  202.     lineHeight = (**(**e).help).lineHeight;
  203.     viewHeight = w->portRect.bottom - sBarWidthM1 - lineHeight;
  204.     dv = 0;
  205.     switch (partCode) {
  206.         case inUpButton:
  207.             dv = (lineHeight < val-min) ? lineHeight : val-min;
  208.             break;
  209.         case inDownButton:
  210.             dv = (lineHeight < max-val) ? -lineHeight : val-max;
  211.             break;
  212.         case inPageUp:
  213.             dv = (viewHeight < val-min) ? viewHeight : val-min;
  214.             break;
  215.         case inPageDown:
  216.             dv = (viewHeight < max-val) ? -viewHeight : val-max;
  217.             break;
  218.     }
  219.     if (dv) {
  220.         SetCtlValue(scrollBar, val-dv);
  221.         Scroll(w, dv);
  222.     }
  223. }
  224.  
  225. /*_____________________________________________________________________
  226.  
  227.     DrawGrowBox - Draw Grow Box.
  228.     
  229.     Entry:    w = pointer to window record.
  230. _____________________________________________________________________*/
  231.  
  232. static void DrawGrowBox (WindowPtr w)
  233.  
  234. {
  235.     DrawGrowIcon(w);
  236. }
  237.  
  238. /*_____________________________________________________________________
  239.  
  240.     InvalScroll - Invalidate Scroll Bars.
  241.     
  242.     Entry:    w = pointer to window record.
  243. _____________________________________________________________________*/
  244.  
  245.  
  246. static void InvalScroll (WindowPtr w)
  247.  
  248. {
  249.     Rect                r;                    /* rectangle to invalidate */
  250.     
  251.     r = w->portRect;
  252.     r.left = r.right - sBarWidthM1;
  253.     InvalRect(&r);
  254.     r = w->portRect;
  255.     r.top = r.bottom - sBarWidthM1;
  256.     InvalRect(&r);
  257. }
  258.  
  259. /*_____________________________________________________________________
  260.  
  261.     CloseHelpWindow - Close Window.
  262.     
  263.     Entry:    w = pointer to window record.
  264. _____________________________________________________________________*/
  265.  
  266. static void CloseHelpWindow (WindowPtr w)
  267.  
  268. {
  269.     HelpInfo            **e;            /* handle to help info */
  270.     short                windNum;        /* window number */
  271.     
  272.     e = GetHelpInfo(w);
  273.     windNum = (**e).windNum;
  274.     if (windNum <= numPosSave) wstm_Save(w, &HelpStates[windNum]);
  275.     TEDispose((**e).help);
  276.     DisposHandle((Handle)e);
  277.     oop_DoClose(w);
  278. }
  279.  
  280. /*_____________________________________________________________________
  281.  
  282.     NewHelpWindow - Create New Help Window.
  283.     
  284.     Entry:    theItem = item number in Help menu.
  285. _____________________________________________________________________*/
  286.  
  287. static void NewHelpWindow (short theItem)
  288.     
  289. {
  290.     Str255                topic;                /* help topic */
  291.     WindowPtr            v;                        /* traverses window list */
  292.     HelpInfo                **g;                    /* handle to help info for window v */
  293.     Boolean                haveWindNum;        /* true when window number found */
  294.     short                    windNum;                /* window number */
  295.     WindState            windState;            /* window state record */
  296.     HelpInfo                **e;                    /* handle to help info */
  297.     WindowPtr            w;                        /* pointer to window */
  298.     Rect                    r;                        /* general purpose rect */
  299.     Str255                ttl;                    /* title of window v */
  300.     TEHandle                help;                    /* handle to help terec */
  301.     OSErr                    rCode;                /* result code */
  302.     char                    *p;                    /* pointer into help topic */
  303.     short                    i;                        /* loop index */
  304.     
  305.     /* Get the help topic. */
  306.     
  307.     GetItem(HelpMenu, theItem, topic);
  308.     
  309.     /* Check to see if this topic help window is already open. */
  310.     
  311.     v = FrontWindow();
  312.     while (v) {
  313.         if (oop_GetWindKind(v) == helpWind) {
  314.             g = GetHelpInfo(v);
  315.             GetWTitle(v, ttl);
  316.             if (EqualString(ttl, topic, true, true) &&
  317.                 EqualString(HelpServer, (**g).server, true, true)) {
  318.                 SelectWindow(v);
  319.                 return;
  320.             }
  321.         }
  322.         v = (WindowPtr)(((WindowPeek)v)->nextWindow);
  323.     }
  324.     
  325.     /* Create the new window record */
  326.  
  327.     windNum = 1;
  328.     haveWindNum = false;
  329.     while (true) {
  330.         v = FrontWindow();
  331.         if (!v) break;
  332.         while (v) {
  333.             if (oop_GetWindKind(v) == helpWind) {
  334.                 g = GetHelpInfo(v);
  335.                 if ((**g).windNum == windNum) break;
  336.             }
  337.             v = (WindowPtr)((WindowPeek)v)->nextWindow;
  338.             if (!v) haveWindNum = true;
  339.         }
  340.         if (haveWindNum) break;
  341.         windNum++;
  342.     }
  343.     windState.moved = false;
  344.     w = wstm_Restore(false, helpWindID, nil, 
  345.         windNum <= numPosSave ? &HelpStates[windNum] : &windState);
  346.     SetPort(w);
  347.     TextFont(FontNum);
  348.     TextSize(fontSize);
  349.     SetWTitle(w, topic);
  350.     
  351.     /* Create the new HelpInfo record. */
  352.     
  353.     e = (HelpInfo**)NewHandle(sizeof(HelpInfo));
  354.     (**e).scrollBar = GetNewControl(helpSBarID, w);
  355.     GetViewRect(w, &r);
  356.     InsetRect(&r, textMargin, 0);
  357.     (**e).help = help = TENew(&r, &r);
  358.     (**e).windNum = windNum;
  359.     utl_CopyPString((**e).server, HelpServer);
  360.     
  361.     /* Create the new window object. */
  362.     
  363.     oop_NewWindow(w, helpWind, (Handle)e, &dispatch);
  364.     
  365.     /* Fetch the help text. */
  366.     
  367.     HLock(HelpTopics);
  368.     p = *HelpTopics;
  369.     theItem -= HelpMenuLength;
  370.     while (--theItem) p += *p+1;
  371.     utl_CopyPString(topic, p);
  372.     for (i = 1; i <= *topic; i++) if (topic[i] == ' ') topic[i] = '_';
  373.     HUnlock(HelpTopics);
  374.     if (rCode = serv_GetHelp(HelpServer, topic, (**help).hText)) {
  375.         glob_ErrorCode(rCode);
  376.         SetPort(w);
  377.         help_DoClose(w);
  378.         return;
  379.     }
  380.     SetPort(w);
  381.     (**help).teLength = GetHandleSize((**help).hText);
  382.     TECalText(help);
  383.     (**help).destRect.top = 0;
  384.     (**help).destRect.bottom = (**help).nLines * (**help).lineHeight;
  385.     AdjustScrollMax(w);
  386.     
  387.     /* Show the window. */
  388.     
  389.     ChangeSize(w, w->portRect.bottom);
  390.     InvalRect(&w->portRect);
  391.     ShowWindow(w);    
  392.     
  393.     return;
  394. }
  395.  
  396. /*_____________________________________________________________________
  397.  
  398.     help_DoPeriodic - Do Periodic Tasks.
  399.     
  400.     Entry:    w = pointer to window record.
  401. _____________________________________________________________________*/
  402.  
  403. void help_DoPeriodic (WindowPtr w)
  404.  
  405. {
  406.     HelpInfo                **e;                /* handle to help info */
  407.     Point                    where;            /* current mouse loc in local coords */
  408.     Rect                    viewRect;        /* view rect */
  409.     ControlHandle        scrollBar;        /* handle to scroll bar control */
  410.     short                    newBalloon;        /* index in STR# of balloon help msg, or 0 if
  411.                                                     none */
  412.     Rect                    hotRect;            /* balloon help hot rectangle */
  413.     Point                    tip;                /* balloon help tip location */
  414.     HMMessageRecord    helpMsg;            /* help message record */
  415.     
  416.     static short        oldBalloon = 0;    /* index in STR# of previous balloon help msg,
  417.                                                         or 0 if none */
  418.  
  419.     e = GetHelpInfo(w);
  420.     SetPort(w);
  421.     TEIdle((**e).help);
  422.     GetViewRect(w, &viewRect);
  423.     GetMouse(&where);
  424.     SetCursor(PtInRect(where, &viewRect) ? *IBeamHandle : &qd.arrow);
  425.     if (HaveBalloons && HMGetBalloons()) {
  426.         scrollBar = (**e).scrollBar;
  427.         if (PtInRect(where, &viewRect)) {
  428.             newBalloon = hbHelpText;
  429.             hotRect = viewRect;
  430.         } else if (PtInRect(where, &(**scrollBar).contrlRect)) {
  431.             newBalloon = (**scrollBar).contrlMin < (**scrollBar).contrlMax ?
  432.                 hbScrollEnabled : hbScrollDisabled;
  433.                 hotRect = (**scrollBar).contrlRect;
  434.         } else {
  435.             hotRect = w->portRect;
  436.             hotRect.top = hotRect.bottom - sBarWidthM1;
  437.             hotRect.left = hotRect.right - sBarWidthM1;
  438.             if (PtInRect(where, &hotRect)) {
  439.                 newBalloon = hbGrow;
  440.             } else {
  441.                 newBalloon = 0;
  442.             }
  443.         }
  444.         if (!HMIsBalloon()) oldBalloon = 0;
  445.         if (newBalloon != oldBalloon) {
  446.             if (newBalloon) {
  447.                 LocalToGlobal((Point*)&hotRect);
  448.                 LocalToGlobal((Point*)&hotRect.bottom);
  449.                 tip.h = (hotRect.left + hotRect.right) >> 1;
  450.                 tip.v = (hotRect.top + hotRect.bottom) >> 1;
  451.                 helpMsg.hmmHelpType = khmmStringRes;
  452.                 helpMsg.u.hmmStringRes.hmmResID = hbStringsId;
  453.                 helpMsg.u.hmmStringRes.hmmIndex = newBalloon;
  454.                 if (!HMShowBalloon(&helpMsg, tip, &hotRect, 
  455.                     nil, 0, 0, kHMRegularWindow)) oldBalloon = newBalloon;
  456.             } else {
  457.                 oldBalloon = 0;
  458.             }
  459.         }
  460.     }
  461. }
  462.  
  463. /*_____________________________________________________________________
  464.  
  465.     help_DoClick - Process a Mouse Down Event.
  466.     
  467.     Entry:    w = pointer to window record.
  468.                 where = mouse click location in local coordinates.
  469.                 modifiers = modifiers from event record.
  470. _____________________________________________________________________*/
  471.  
  472. void help_DoClick (WindowPtr w, Point where, short modifiers)
  473.  
  474. {
  475.     HelpInfo            **e;                    /* handle to help info */
  476.     ControlHandle    whichControl;        /* control clicked in */
  477.     short                partCode;            /* control part code */
  478.     short                oldVal;                /* old scroll bar control value */
  479.     short                dv;                    /* amount to scroll */
  480.     Rect                viewRect;            /* view rect */
  481.     
  482.     e = GetHelpInfo(w);
  483.     GetViewRect(w, &viewRect);
  484.     if (PtInRect(where, &viewRect)) {
  485.         TEAutoView(true, (**e).help);
  486.         TEClick(where, modifiers & shiftKey ? true : false, (**e).help);
  487.         TEAutoView(false, (**e).help);
  488.         SetCtlValue((**e).scrollBar, -(**(**e).help).destRect.top);
  489.     } else {
  490.         partCode = FindControl(where, w, &whichControl);
  491.         if (whichControl == (**e).scrollBar) {
  492.             if (partCode == inThumb) {
  493.                 oldVal = GetCtlValue(whichControl);
  494.                 TrackControl(whichControl, where, nil);
  495.                 dv = GetCtlValue(whichControl) - oldVal;
  496.                 if (dv) Scroll(w, -dv);
  497.             } else {
  498.                 TrackControl(whichControl, where, (ProcPtr)ScrollAction);
  499.             }
  500.             AdjustScrollMax(w);
  501.         }
  502.     }
  503. }
  504.  
  505. /*_____________________________________________________________________
  506.  
  507.     help_DoKey - Process a Key Down Event.
  508.     
  509.     Entry:    w = pointer to window record.
  510.                 key = ascii code of key.
  511.                 modifiers = modifiers from event record.
  512. _____________________________________________________________________*/
  513.  
  514. void help_DoKey (WindowPtr w, char key, short modifiers)
  515.  
  516. {
  517. #pragma unused (modifiers)
  518.  
  519.     HelpInfo            **e;                /* handle to query info */
  520.     TEHandle            help;                /* handle to terec */
  521.     ControlHandle    scrollBar;        /* handle to scroll bar */
  522.     short                val;                /* scroll bar value */
  523.     short                min;                /* scroll bar minimum value */
  524.     short                max;                /* scroll bar maximum value */
  525.  
  526.     e = GetHelpInfo(w);
  527.     if (key == leftArrow || key == rightArrow ||
  528.         key == downArrow || key == upArrow) {
  529.         help = (**e).help;
  530.         TEAutoView(true, help);
  531.         TEKey(key, help);
  532.         TEAutoView(false, help);
  533.         SetCtlValue((**e).scrollBar, -(**help).destRect.top);
  534.     } else if (key == pageUpKey || key == pageDownKey ||
  535.         key == homeKey || key == endKey) {
  536.         scrollBar = (**e).scrollBar;
  537.         val = (**scrollBar).contrlValue;
  538.         min = (**scrollBar).contrlMin;
  539.         max = (**scrollBar).contrlMax;
  540.         if (key == pageUpKey) {
  541.             ScrollAction(scrollBar, inPageUp);
  542.         } else if (key == pageDownKey) {
  543.             ScrollAction(scrollBar, inPageDown);
  544.         } else if (key == homeKey) {
  545.             SetCtlValue(scrollBar, min);
  546.             Scroll(w, val-min);
  547.         } else {
  548.             SetCtlValue(scrollBar, max);
  549.             Scroll(w, val-max);
  550.         }
  551.     } else {
  552.         SysBeep(0);
  553.     }
  554. }
  555.  
  556. /*_____________________________________________________________________
  557.  
  558.     help_DoUpdate - Process an Update Event.
  559. _____________________________________________________________________*/
  560.  
  561. void help_DoUpdate (WindowPtr w)
  562.  
  563. {
  564.     HelpInfo        **e;                    /* handle to help info */
  565.     Rect            viewRect;            /* view rect */
  566.  
  567.     e = GetHelpInfo(w);
  568.     EraseRect(&w->portRect);
  569.     DrawControls(w);
  570.     GetViewRect(w, &viewRect);
  571.     TEUpdate(&viewRect, (**e).help);
  572.     DrawGrowBox(w);
  573. }
  574.  
  575. /*_____________________________________________________________________
  576.  
  577.     help_DoActivate - Process an Activate Event.    
  578.     
  579.     Entry:    w = pointer to window record.
  580. _____________________________________________________________________*/
  581.  
  582. void help_DoActivate (WindowPtr w)
  583.  
  584. {
  585.     HelpInfo        **e;            /* handle to help info */
  586.     
  587.     e = GetHelpInfo(w);
  588.     ShowControl((**e).scrollBar);
  589.     TEActivate((**e).help);
  590.     DrawGrowBox(w);
  591. }
  592.  
  593. /*_____________________________________________________________________
  594.  
  595.     help_DoDeactivate - Process a Deactivate Event.    
  596.     
  597.     Entry:    w = pointer to window record.
  598. _____________________________________________________________________*/
  599.  
  600. void help_DoDeactivate (WindowPtr w)
  601.  
  602. {
  603.     HelpInfo        **e;            /* handle to help info */
  604.     
  605.     e = GetHelpInfo(w);
  606.     HideControl((**e).scrollBar);
  607.     TEDeactivate((**e).help);
  608.     DrawGrowBox(w);
  609. }
  610.  
  611. /*_____________________________________________________________________
  612.  
  613.     help_DoGrow - Process Window Grow Operation.
  614.     
  615.     Entry:    w = pointer to window record.
  616.                 where = location of mouse click in global coordinates.
  617. _____________________________________________________________________*/
  618.  
  619. void help_DoGrow(WindowPtr w, Point where)
  620.  
  621. {
  622.     unsigned long            newSize;            /* new window size */
  623.     short                        height;            /* new window height */
  624.     short                        width;            /* new window width */
  625.  
  626.     SetPort(w);
  627.     newSize = GrowWindow(w, where, &SizeRect);
  628.     if (!newSize) return;
  629.     height = newSize >> 16;
  630.     if (!(height & 1)) height--;
  631.     width = newSize & 0xffff;
  632.     InvalScroll(w);
  633.     SizeWindow(w, width, height, true);
  634.     InvalScroll(w);
  635.     ChangeSize(w, height);
  636. }
  637.  
  638. /*_____________________________________________________________________
  639.  
  640.     help_DoZoom - Process Window Zoom Operation.
  641.     
  642.     Entry:    w = pointer to window record.
  643.                 where = location of mouse click in global coordinates.
  644.                 partCode = inZoomIn or inZoomOut
  645. _____________________________________________________________________*/
  646.  
  647. void help_DoZoom (WindowPtr w, Point where, short partCode)
  648.  
  649. {
  650.     if (!TrackBox(w, where, partCode)) return;
  651.     SetPort(w);
  652.     if (partCode == inZoomOut) wstm_ComputeStd(w);
  653.     EraseRect(&w->portRect);
  654.     ZoomWindow(w, partCode, false);
  655.     ChangeSize(w, w->portRect.bottom - w->portRect.top);
  656. }
  657.  
  658. /*_____________________________________________________________________
  659.  
  660.     help_DoClose - Close Window.
  661.     
  662.     Entry:    w = pointer to window record.
  663. _____________________________________________________________________*/
  664.  
  665. void help_DoClose (WindowPtr w)
  666.  
  667. {
  668.     CloseHelpWindow(w);
  669. }
  670.  
  671. /*_____________________________________________________________________
  672.  
  673.     help_DoCommand - Process a Command.
  674.     
  675.     Entry:    top = pointer to top window record.
  676.                 theMenu = menu number.
  677.                 theItem = menu item number.
  678. _____________________________________________________________________*/
  679.  
  680. #pragma segment command
  681.  
  682. Boolean help_DoCommand (WindowPtr top, short theMenu, short theItem)
  683.  
  684. {
  685.     HelpInfo            **e;            /* handle to help info */
  686.     TEHandle            help;            /* handle to help terec */
  687.     OSErr                rCode;        /* error code */
  688.     Str255            server;        /* help server domain name */
  689.     
  690.     switch (theMenu) {
  691.         case editID:
  692.             if (!top) break;
  693.             e = GetHelpInfo(top);
  694.             help = (**e).help;
  695.             switch (theItem) {
  696.                 case copyCmd:
  697.                     TECopy(help);
  698.                     ZeroScrap();
  699.                     TEToScrap();
  700.                     return true;
  701.                 case selectAllCmd:
  702.                     TESetSelect(0, 32767, help);
  703.                     return true;
  704.             }
  705.             break;
  706.         case helpID:
  707.         case kHMHelpMenuID:
  708.             HiliteMenu(0);
  709.             if (theItem > HelpMenuLength) {
  710.                 if (HelpTopics) {
  711.                     NewHelpWindow(theItem);
  712.                 } else {
  713.                     glob_Error(servErrors, msgNoHelp, nil);
  714.                 }
  715.             } else {
  716.                 utl_CopyPString(server, HelpServer);
  717.                 while (true) {
  718.                     if (site_DoDialog(server, helpLabelMsg1, helpLabelMsg2)) break;
  719.                     if (rCode = serv_GetHelpList(server)) {
  720.                         glob_ErrorCode(rCode);
  721.                         continue;
  722.                     }
  723.                     utl_CopyPString(HelpServer, server);
  724.                     break;
  725.                 }
  726.             }
  727.             return true;
  728.     }
  729.     return false;
  730. }
  731.  
  732. #pragma segment help
  733.  
  734. /*_____________________________________________________________________
  735.  
  736.     help_Init - Initialize
  737. _____________________________________________________________________*/
  738.  
  739. #pragma segment init
  740.  
  741. void help_Init (void)
  742.  
  743. {
  744.     WindowPtr    w;                    /* pointer to dummy window */
  745.     
  746.     w = GetNewWindow(helpWindID, nil, (WindowPtr)-1);
  747.     SetPort(w);
  748.     SetRect(&SizeRect, w->portRect.right+1, minWindHeight, 
  749.         w->portRect.right+1, 0x7fff);
  750.     DisposeWindow(w);
  751.     oop_RegisterCommandHandler(help_DoCommand);
  752. }
  753.  
  754. #pragma segment help
  755.  
  756. /*_____________________________________________________________________
  757.  
  758.     help_Terminate - Terminate
  759. _____________________________________________________________________*/
  760.  
  761. void help_Terminate (void)
  762.  
  763. {
  764.     WindowPtr        v;                /* traverses window list */
  765.     HelpInfo            **g;            /* handle to help info for window v */
  766.     short                windNum;        /* window number */
  767.     
  768.     v = FrontWindow();
  769.     while (v) {
  770.         if (oop_GetWindKind(v) == helpWind) {
  771.             g = GetHelpInfo(v);
  772.             windNum = (**g).windNum;
  773.             if (windNum <= numPosSave) wstm_Save(v, &HelpStates[windNum]);
  774.         }
  775.         v = (WindowPtr)((WindowPeek)v)->nextWindow;
  776.     }
  777. }
  778.  
  779. /*_____________________________________________________________________
  780.  
  781.     help_BuildHelpMenu - Build Help Menu.
  782.     
  783.     Entry:    HelpTopics = help topic list.
  784.     
  785.     Exit:        HelpMenu = rebuilt help menu.
  786.     
  787.     If a help topic contains the substring "..", only the part of the
  788.     help topic following the first occurence of the substring ".." is
  789.     displayed in the help menu. All occurences of '_' in help topics
  790.     are also replaced by ' '.
  791. _____________________________________________________________________*/
  792.  
  793. void help_BuildHelpMenu (void)
  794.  
  795. {
  796.     short                nItems;            /* number of menu items */
  797.     short                item;                /* menu item number */
  798.     Str255            ttl;                /* menu command */
  799.     short                len;                /* length of menu command */
  800.     char                *p;                /* pointer into help topic */
  801.     char                *pEnd;            /* pointer to end of help topic list */
  802.     char                 *q;                /* pointer into help topic */
  803.     short                i;                    /* loop index */
  804.  
  805.     nItems = CountMItems(HelpMenu);
  806.     for (item = nItems; item > HelpMenuLength; item--) DelMenuItem(HelpMenu, item);
  807.     if (HelpTopics) {
  808.         HLock(HelpTopics);
  809.         p = *HelpTopics;
  810.         pEnd = p + GetHandleSize(HelpTopics);
  811.         item = HelpMenuLength;
  812.         while (p < pEnd) {
  813.             len = *p;
  814.             q = p+1;
  815.             while (len > 2 && (*q != '.' || *(q+1) != '.')) {
  816.                 q++;
  817.                 len--;
  818.             }
  819.             if (len > 2) {
  820.                 q += 2;
  821.                 len -= 2;
  822.             } else {
  823.                 q = p+1;
  824.                 len = *p;
  825.             }
  826.             if (len) {
  827.                 item++;
  828.                 memcpy(ttl+1, q, len);
  829.                 *ttl = len;
  830.                 for (i = 1; i <= len; i++) if (ttl[i] == '_') ttl[i] = ' ';
  831.                 AppendMenu(HelpMenu, "\p ");
  832.                 SetItem(HelpMenu, item, ttl);
  833.             }
  834.             p += *p+1;
  835.         }
  836.         HUnlock(HelpTopics);
  837.     } else {
  838.         GetIndString(ttl, stringsID, whyCmd);
  839.         AppendMenu(HelpMenu, ttl);
  840.     }
  841.     CalcMenuSize(HelpMenu);
  842. }
  843.