home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Utilities / Ph 1.1.1 / PhClient / query.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-11-04  |  34.2 KB  |  1,194 lines  |  [TEXT/MPS ]

  1. /*_____________________________________________________________________
  2.  
  3.       query.c - Query 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 "query.h"
  19. #include "oop.h"
  20. #include "wstm.h"
  21.  
  22. #pragma segment query
  23.  
  24. /*_____________________________________________________________________
  25.  
  26.     Defines.
  27. _____________________________________________________________________*/
  28.  
  29. #define headerRule        73            /* v coord of top line of header double rule */
  30. #define headerHeight        (headerRule+4)        
  31.                                             /* total height of window header area */
  32. #define sBarWidth            16            /* width of scroll bar */
  33. #define sBarWidthM1        (sBarWidth-1)
  34. #define textMargin        4            /* left and right margins for text */
  35. #define minWindHeight    250        /* min window height */
  36. #define teSlop                3            /* extra pixels around textedit boxes */
  37. #define teHeight            12            /* height of textedit boxes */
  38. #define popupTop            11            /* top coord popup menu */
  39. #define popupBot            (popupTop+16)            
  40.                                             /* bot coord popup menu */
  41. #define popupLeft            13            /* left coord popup menu */
  42. #define popupRight        314        /* right coord popup menu */
  43. #define domainTop            14            /* top coord domain name te box */
  44. #define domainBot            (domainTop+11) 
  45.                                             /* bot coord domain name te box */
  46. #define domainLeft        (popupRight+15)
  47.                                             /* left coord domain name te box */
  48. #define domainRight        490        /* right coord domain name te box */
  49. #define queryTop            46            /* top coord query te box */
  50. #define queryBot            (queryTop+11)
  51.                                             /* bot coord query te box */
  52. #define queryLeft            (popupLeft+teSlop)
  53.                                             /* left coord query te box */
  54. #define queryRight        410        /* right coord query te box */
  55.  
  56. /*_____________________________________________________________________
  57.  
  58.     Types.
  59. _____________________________________________________________________*/
  60.  
  61. typedef struct QueryInfo {
  62.     ControlHandle        scrollBar;                /* handle to scroll bar control */
  63.     ControlHandle        doitBtn;                    /* handle to doit button */
  64.     short                    serverInx;                /* index of currently selected server */
  65.     short                    windNum;                    /* window number */
  66.     TEHandle                domain;                    /* handle to domain name terec */
  67.     TEHandle                query;                    /* handle to query terec */
  68.     TEHandle                reply;                    /* handle to reply terec */
  69.     TEHandle                curEdit;                    /* handle to current active terec */
  70. } QueryInfo;
  71.  
  72. /*_____________________________________________________________________
  73.  
  74.     Global Variables.
  75. _____________________________________________________________________*/
  76.  
  77. static Rect                SizeRect;                /* size rectangle */
  78. static Rect                PopupRect = {popupTop, popupLeft, popupBot, popupRight};
  79.                                                         /* popup menu rect */
  80. static Rect                DomainRect = {domainTop-teSlop, domainLeft-teSlop, 
  81.                                 domainBot+teSlop, domainRight+teSlop};
  82.                                                         /* domain name te box */
  83. static Rect                DomainClickRect = {domainTop, domainLeft-teSlop,
  84.                                 domainBot, domainRight+teSlop};
  85.                                                         /* domain name clickable box */
  86. static Rect                QueryRect = {queryTop-teSlop, queryLeft-teSlop, 
  87.                                 queryBot+teSlop, queryRight+teSlop};                
  88.                                                         /* query te box */
  89. static Rect                QueryClickRect = {queryTop, queryLeft-teSlop,
  90.                                 queryBot, queryRight+teSlop};
  91.                                                         /* query clickable box */
  92.  
  93. static oop_Dispatch dispatch = {
  94.                                 query_DoPeriodic,
  95.                                 query_DoClick,
  96.                                 query_DoKey,
  97.                                 query_DoUpdate,
  98.                                 query_DoActivate,
  99.                                 query_DoDeactivate,
  100.                                 query_DoGrow,
  101.                                 query_DoZoom,
  102.                                 query_DoClose,
  103.                                 query_DoCommand
  104.                             };
  105.  
  106. /*_____________________________________________________________________
  107.  
  108.     GetQueryInfo - Get QueryInfo Handle from Window Pointer
  109.     
  110.     Entry:    w = pointer to window record
  111.     
  112.     Exit:        Function result = handle to QueryInfo record.
  113. _____________________________________________________________________*/
  114.  
  115. static QueryInfo **GetQueryInfo (WindowPtr w)
  116.  
  117. {
  118.     return (QueryInfo**)oop_GetWindInfo(w);
  119. }
  120.  
  121. /*_____________________________________________________________________
  122.  
  123.     GetViewRect - Get View Rectangle.
  124.     
  125.     Entry:    w = pointer to window record.
  126.     
  127.     Exit:        *viewRect = view rectangle.
  128. _____________________________________________________________________*/
  129.  
  130. static void GetViewRect (WindowPtr w, Rect *viewRect)
  131.  
  132. {
  133.     *viewRect = w->portRect;
  134.     viewRect->top += headerHeight;
  135.     viewRect->bottom -= sBarWidthM1;
  136.     viewRect->right -= sBarWidthM1;
  137. }
  138.  
  139. /*_____________________________________________________________________
  140.  
  141.     AdjustScrollMax - Adjust Scroll Bar Max Value.
  142.     
  143.     Entry:    w = pointer to window record.
  144. _____________________________________________________________________*/
  145.  
  146. static void AdjustScrollMax (WindowPtr w)
  147.  
  148. {
  149.     QueryInfo        **e;            /* handle to query info */
  150.     TEHandle            reply;        /* handle to reply terec */
  151.     Rect                viewRect;    /* view rect */
  152.     short                vHeight;        /* height of view rect */
  153.     short                tHeight;        /* height of reply text */
  154.     short                max;            /* new max control value */
  155.     
  156.     e = GetQueryInfo(w);
  157.     reply = (**e).reply;
  158.     GetViewRect(w, &viewRect);
  159.     vHeight = viewRect.bottom - viewRect.top;
  160.     tHeight = (**reply).destRect.bottom - (**reply).destRect.top;
  161.     max = tHeight - vHeight;
  162.     if (max < 0) max = 0;
  163.     SetCtlMax((**e).scrollBar, max);
  164. }
  165.  
  166. /*_____________________________________________________________________
  167.  
  168.     Scroll - Scroll the Window.
  169.     
  170.     Entry:    w = pointer to window record.
  171.                 dv = number of pixels to scroll.
  172. _____________________________________________________________________*/
  173.  
  174. static void Scroll (WindowPtr w, short dv)
  175.  
  176. {
  177.     QueryInfo        **e;            /* handle to query info */
  178.     
  179.     e = GetQueryInfo(w);
  180.     SetPort(w);
  181.     TEScroll(0, dv, (**e).reply);
  182.     SetOrigin(0, 0);
  183. }
  184.  
  185. /*_____________________________________________________________________
  186.  
  187.     ChangeSize - Process Window Size Change.
  188.     
  189.     Entry:    w = pointer to window record.
  190.                 height = new window height
  191. _____________________________________________________________________*/
  192.  
  193. static void ChangeSize (WindowPtr w, short height)
  194.  
  195. {
  196.     QueryInfo    **e;                    /* handle to query info */
  197.     Rect            viewRect;            /* view rectangle */
  198.     TEHandle        reply;                /* handle to reply terec */
  199.     short            offTop;                /* amount of text scrolled off top */
  200.     short            textBot;                /* bottom text coord */
  201.     short            viewBot;                /* bottom view coord */
  202.     short            dv;                    /* amount to scroll */
  203.  
  204.     e = GetQueryInfo(w);
  205.     SizeControl((**e).scrollBar, sBarWidth, height-12-headerHeight);
  206.     AdjustScrollMax(w);
  207.     GetViewRect(w, &viewRect);
  208.     reply = (**e).reply;
  209.     InsetRect(&viewRect, textMargin, 0);
  210.     (**reply).viewRect = viewRect;
  211.     offTop = headerHeight - (**reply).destRect.top;
  212.     textBot = (**reply).destRect.bottom;
  213.     viewBot = w->portRect.bottom - sBarWidthM1;
  214.     if (textBot < viewBot && offTop) {
  215.         dv = viewBot - textBot;
  216.         if (dv > offTop) dv = offTop;
  217.         Scroll(w, dv);
  218.     }
  219. }
  220.  
  221. /*_____________________________________________________________________
  222.  
  223.     ScrollAction - Scroll Bar Action Procedure
  224. _____________________________________________________________________*/
  225.  
  226. static pascal void ScrollAction (ControlHandle scrollBar, short partCode)
  227.  
  228. {
  229.     WindowPtr        w;                    /* pointer to window */
  230.     QueryInfo        **e;                /* handle to query info */
  231.     short                val;                /* scroll bar value */
  232.     short                min;                /* scroll bar minimum value */
  233.     short                max;                /* scroll bar maximum value */
  234.     short                viewHeight;        /* height of view rectangle */
  235.     short                lineHeight;        /* height of one line */
  236.     short                dv;                /* amount to scroll */
  237.     
  238.     w = FrontWindow();
  239.     e = GetQueryInfo(w);
  240.     val = (**scrollBar).contrlValue;
  241.     min = (**scrollBar).contrlMin;
  242.     max = (**scrollBar).contrlMax;
  243.     lineHeight = (**(**e).reply).lineHeight;
  244.     viewHeight = w->portRect.bottom - sBarWidthM1 - headerHeight - lineHeight;
  245.     dv = 0;
  246.     switch (partCode) {
  247.         case inUpButton:
  248.             dv = (lineHeight < val-min) ? lineHeight : val-min;
  249.             break;
  250.         case inDownButton:
  251.             dv = (lineHeight < max-val) ? -lineHeight : val-max;
  252.             break;
  253.         case inPageUp:
  254.             dv = (viewHeight < val-min) ? viewHeight : val-min;
  255.             break;
  256.         case inPageDown:
  257.             dv = (viewHeight < max-val) ? -viewHeight : val-max;
  258.             break;
  259.     }
  260.     if (dv) {
  261.         SetCtlValue(scrollBar, val-dv);
  262.         Scroll(w, dv);
  263.     }
  264. }
  265.  
  266. /*_____________________________________________________________________
  267.  
  268.     DrawGrowBox - Draw Grow Box.
  269.     
  270.     Entry:    w = pointer to window record.
  271. _____________________________________________________________________*/
  272.  
  273. static void DrawGrowBox (WindowPtr w)
  274.  
  275. {
  276.     Rect            r;                /* clip rect */
  277.     
  278.     r = w->portRect;
  279.     r.top += headerHeight-1;
  280.     ClipRect(&r);
  281.     DrawGrowIcon(w);
  282.     SetClip(BigClipRgn);
  283. }
  284.  
  285. /*_____________________________________________________________________
  286.  
  287.     InvalScroll - Invalidate Scroll Bars.
  288.     
  289.     Entry:    w = pointer to window record.
  290. _____________________________________________________________________*/
  291.  
  292.  
  293. static void InvalScroll (WindowPtr w)
  294.  
  295. {
  296.     Rect                r;                    /* rectangle to invalidate */
  297.     
  298.     r = w->portRect;
  299.     r.left = r.right - sBarWidthM1;
  300.     InvalRect(&r);
  301.     r = w->portRect;
  302.     r.top = r.bottom - sBarWidthM1;
  303.     InvalRect(&r);
  304. }
  305.  
  306. /*_____________________________________________________________________
  307.  
  308.     CloseQueryWindow - Close Window.
  309.     
  310.     Entry:    w = pointer to window record.
  311. _____________________________________________________________________*/
  312.  
  313. static void CloseQueryWindow (WindowPtr w)
  314.  
  315. {
  316.     QueryInfo            **e;            /* handle to query info */
  317.     short                    windNum;        /* window number */
  318.     
  319.     e = GetQueryInfo(w);
  320.     windNum = (**e).windNum;
  321.     if (windNum <= numPosSave) wstm_Save(w, &QueryStates[windNum]);
  322.     TEDispose((**e).domain);
  323.     TEDispose((**e).query);
  324.     TEDispose((**e).reply);
  325.     DisposHandle((Handle)e);
  326.     oop_DoClose(w);
  327. }
  328.  
  329. /*_____________________________________________________________________
  330.  
  331.     NewQueryWindow - Create New Query Window.
  332. _____________________________________________________________________*/
  333.  
  334. static void NewQueryWindow (void)
  335.     
  336. {
  337.     WindowPtr            v;                        /* traverses window list */
  338.     QueryInfo            **g;                    /* handle to query info for window v */
  339.     Boolean                haveWindNum;        /* true when window number found */
  340.     WindState            windState;            /* window state record */
  341.     QueryInfo            **e;                    /* handle to query info */
  342.     WindowPtr            w;                        /* pointer to window */
  343.     Str255                tmpl;                    /* window title template */
  344.     Str255                ttl;                    /* window title */
  345.     short                    windNum;                /* window number */
  346.     Str255                windNumStr;            /* window number string */
  347.     Rect                    r;                        /* general purpose rect */
  348.     Rect                    d;                        /* textedit dest rect */
  349.     
  350.     /* Create the new window record */
  351.  
  352.     windNum = 1;
  353.     haveWindNum = false;
  354.     while (true) {
  355.         v = FrontWindow();
  356.         if (!v) break;
  357.         while (v) {
  358.             if (oop_GetWindKind(v) == queryWind) {
  359.                 g = GetQueryInfo(v);
  360.                 if ((**g).windNum == windNum) break;
  361.             }
  362.             v = (WindowPtr)((WindowPeek)v)->nextWindow;
  363.             if (!v) haveWindNum = true;
  364.         }
  365.         if (haveWindNum) break;
  366.         windNum++;
  367.     }
  368.     windState.moved = false;
  369.     w = wstm_Restore(false, queryWindID, nil, 
  370.         windNum <= numPosSave ? &QueryStates[windNum] : &windState);
  371.     SetPort(w);
  372.     TextFont(FontNum);
  373.     TextSize(fontSize);
  374.     NumToString(windNum, windNumStr);
  375.     GetIndString(tmpl, stringsID, queryWindTtl);
  376.     utl_PlugParams(tmpl, ttl, windNumStr, nil, nil, nil);
  377.     SetWTitle(w, ttl);
  378.     
  379.     /* Create the new QueryInfo record. */
  380.     
  381.     e = (QueryInfo**)NewHandle(sizeof(QueryInfo));
  382.     (**e).scrollBar = GetNewControl(querySBarID, w);
  383.     (**e).doitBtn = GetNewControl(queryDoitID, w);
  384.     HiliteControl((**e).doitBtn, 255);
  385.     r = DomainRect;
  386.     InsetRect(&r, teSlop, teSlop);
  387.     (**e).domain = TENew(&r, &r);
  388.     TESetText(DefaultServer+1, *DefaultServer, (**e).domain);
  389.     r = QueryRect;
  390.     InsetRect(&r, teSlop, teSlop);
  391.     (**e).query = TENew(&r, &r);
  392.     (**e).curEdit = (**e).query;
  393.     GetViewRect(w, &r);
  394.     InsetRect(&r, textMargin, 0);
  395.     d = r;
  396.     d.top = d.bottom = headerHeight;
  397.     (**e).reply = TENew(&d, &r);
  398.     (**e).serverInx = glob_GetSiteIndex(DefaultServer);
  399.     (**e).windNum = windNum;
  400.     
  401.     /* Create the new window object. */
  402.     
  403.     oop_NewWindow(w, queryWind, (Handle)e, &dispatch);
  404.     
  405.     /* Finish initializing and show the window. */
  406.     
  407.     ChangeSize(w, w->portRect.bottom);
  408.     InvalRect(&w->portRect);
  409.     ShowWindow(w);    
  410.     
  411.     return;
  412. }
  413.  
  414. /*_____________________________________________________________________
  415.  
  416.     AutoScroll - Make Sure Selection Range is Visible.
  417.     
  418.     Entry:    w = pointer to window record.
  419. _____________________________________________________________________*/
  420.  
  421. static void AutoScroll (WindowPtr w)
  422.  
  423. {
  424.     QueryInfo        **e;                /* handle to query info */
  425.     TEHandle            reply;            /* handle to reply terec */
  426.     
  427.     e = GetQueryInfo(w);
  428.     reply = (**e).reply;
  429.     TEAutoView(true, (**e).reply);
  430.     TESelView(reply);
  431.     TEAutoView(false, (**e).reply);
  432.     SetCtlValue((**e).scrollBar, headerHeight - (**reply).destRect.top);
  433. }
  434.  
  435. /*_____________________________________________________________________
  436.  
  437.     SelectEmailAddress - Select Next Email Address.
  438.     
  439.     Entry:    w = pointer to window record.
  440.                 autoScroll = true to scoll selection range into view.
  441.                 backup = true to select previous email address.
  442.     
  443.     Exit:        function result = true if email address selected, else false.
  444. _____________________________________________________________________*/
  445.  
  446. static Boolean SelectEmailAddress (WindowPtr w, Boolean autoScroll, Boolean backup)
  447.  
  448. {
  449.     QueryInfo        **e;                /* handle to query info */
  450.     TEHandle            reply;            /* handle to reply terec */
  451.     Handle            hText;            /* handle to reply text */
  452.     short                teLength;        /* length of reply text */
  453.     Str255            emailStr;        /* "email: " search string */
  454.     short                emailStrLen;    /* length of search string */
  455.     char                *p;                /* pointer into reply text */
  456.     char                *pEnd;            /* pointer to last search anchor pos */
  457.     char                *q;                /* pointer into reply text */
  458.     char                *qEnd;            /* pointer to end of reply text */
  459.     short                selStart;        /* selection start pos */
  460.     short                selEnd;            /* selection end pos */
  461.     
  462.     e = GetQueryInfo(w);
  463.     reply = (**e).reply;
  464.     hText = (**reply).hText;
  465.     teLength = (**reply).teLength;
  466.     GetIndString(emailStr, fieldNames, emailFieldName);
  467.     emailStrLen = *emailStr + 1;
  468.     emailStr[emailStrLen++] = ':';
  469.     emailStr[emailStrLen] = ' ';
  470.     p = *hText + (backup ? (**reply).selStart-emailStrLen-1 : (**reply).selEnd);
  471.     pEnd = *hText + teLength - emailStrLen;
  472.     if (backup) {
  473.         if (p < *hText) p = pEnd;
  474.         while (p >= *hText) {
  475.             if (!strncmp(p, emailStr+1, emailStrLen)) break;
  476.             p--;
  477.         }
  478.         if (p < *hText) return false;
  479.     } else {
  480.         while (p < pEnd) {
  481.             if (!strncmp(p, emailStr+1, emailStrLen)) break;
  482.             p++;
  483.         }
  484.         if (p >= pEnd) return false;
  485.     }
  486.     p += emailStrLen;
  487.     q = p;
  488.     qEnd = *hText + teLength;
  489.     while (q < qEnd && *q != ' ' && *q != '\n') q++;
  490.     if (p == q) return false;
  491.     selStart = p - *hText;
  492.     selEnd = q - *hText;
  493.     TESetSelect(selStart, selEnd, reply);
  494.     if ((**e).curEdit != (**e).reply) {
  495.         TEDeactivate((**e).curEdit);
  496.         TEActivate((**e).reply);
  497.         (**e).curEdit = (**e).reply;
  498.     }
  499.     if (autoScroll) AutoScroll(w);
  500.     return true;
  501. }
  502.  
  503. /*_____________________________________________________________________
  504.  
  505.     Doit - Do A Query.
  506.     
  507.     Entry:    w = pointer to window record.
  508. _____________________________________________________________________*/
  509.  
  510. void Doit (WindowPtr w)
  511.  
  512. {
  513.     QueryInfo        **e;                /* handle to query info */
  514.     TEHandle            domain;            /* handle to domain terec */
  515.     TEHandle            query;            /* handle to query terec */
  516.     TEHandle            reply;            /* handle to reply terec */
  517.     short                domainLen;        /* length of domain name */
  518.     Str255            server;            /* server */
  519.     OSErr                rCode;            /* result code */
  520.     Rect                viewRect;        /* view rect */
  521.     short                i;                    /* loop index */
  522.     Str255            emailDomain;    /* email domain name */
  523.     char                *p;                /* pointer to server domain name */
  524.     char                *q;                /* pointer to email domain name */
  525.     
  526.     e = GetQueryInfo(w);
  527.     domain = (**e).domain;
  528.     query = (**e).query;
  529.     reply = (**e).reply;
  530.     TESetSelect(0, 0xffff, reply);
  531.     TEDelete(reply);
  532.     SetCtlValue((**e).scrollBar, 0);
  533.     domainLen = (**domain).teLength;
  534.     if (domainLen > 255) domainLen = 255;
  535.     *server = domainLen;
  536.     memcpy(server+1, *(**domain).hText, domainLen);
  537.     p = *Servers;
  538.     for (i = 1; i <= NumSites; i++) {
  539.         if (EqualString(server, p, true, true)) break;
  540.         p += *p+1;
  541.     }
  542.     if (i > NumSites) {
  543.         *emailDomain = 0;
  544.     } else {
  545.         q = *Domains;
  546.         while (--i) q += *q+1;
  547.         utl_CopyPString(emailDomain, q);
  548.     }
  549.     if (rCode = serv_DoQuery(server, (**query).hText, (**query).teLength,
  550.         emailDomain, (**reply).hText)) {
  551.         if (GetHandleSize((**reply).hText) == 0) glob_ErrorCode(rCode);
  552.     }
  553.     SetPort(w);
  554.     (**reply).teLength = GetHandleSize((**reply).hText);
  555.     TECalText(reply);
  556.     (**reply).destRect.top = headerHeight;
  557.     (**reply).destRect.bottom = headerHeight + 
  558.         (**reply).nLines * (**reply).lineHeight;
  559.     AdjustScrollMax(w);
  560.     GetViewRect(w, &viewRect);
  561.     InvalRect(&viewRect);
  562.     oop_UpdateAll();
  563.     TESetSelect(0, 0, reply);
  564.     if (!SelectEmailAddress(w, false, false)) {
  565.         if ((**e).curEdit != query) {
  566.             TEDeactivate((**e).curEdit);
  567.             TEActivate(query);
  568.             (**e).curEdit = query;
  569.         }
  570.         TESetSelect(0, 0xffff, query);
  571.     }
  572. }
  573.  
  574. /*_____________________________________________________________________
  575.  
  576.     query_DoPeriodic - Do Periodic Tasks.
  577.     
  578.     Entry:    w = pointer to window record.
  579. _____________________________________________________________________*/
  580.  
  581. void query_DoPeriodic (WindowPtr w)
  582.  
  583. {
  584.     QueryInfo            **e;                /* handle to query info */
  585.     Point                    where;            /* current mouse loc in local coords */
  586.     Rect                    viewRect;        /* view rect */
  587.     Boolean                okToDoit;        /* true if Doit button should be hilited */
  588.     ControlHandle        doitBtn;            /* handle to Doit button */
  589.     ControlHandle        scrollBar;        /* handle to scroll bar control */
  590.     short                    newBalloon;        /* index in STR# of balloon help msg, or 0 if
  591.                                                     none */
  592.     Rect                    hotRect;            /* balloon help hot rectangle */
  593.     Point                    tip;                /* balloon help tip location */
  594.     HMMessageRecord    helpMsg;            /* help message record */
  595.     
  596.     static short        oldBalloon = 0;    /* index in STR# of previous balloon help msg,
  597.                                                         or 0 if none */
  598.  
  599.     e = GetQueryInfo(w);
  600.     SetPort(w);
  601.     TEIdle((**e).curEdit);
  602.     GetViewRect(w, &viewRect);
  603.     GetMouse(&where);
  604.     SetCursor(PtInRect(where, &DomainClickRect) || PtInRect(where, &QueryClickRect)
  605.         || PtInRect(where, &viewRect) ? *IBeamHandle : &qd.arrow);
  606.     okToDoit = (**(**e).domain).teLength && (**(**e).query).teLength;
  607.     doitBtn = (**e).doitBtn;
  608.     HiliteControl(doitBtn, okToDoit ? 0 : 255);
  609.     if (HaveBalloons && HMGetBalloons()) {
  610.         scrollBar = (**e).scrollBar;
  611.         if (PtInRect(where, &DomainClickRect)) {
  612.             newBalloon = hbQueryDomainName;
  613.             hotRect = DomainClickRect;
  614.         } else if (PtInRect(where, &QueryClickRect)) {
  615.             newBalloon = hbQueryQuery;
  616.             hotRect = QueryClickRect;
  617.         } else if (PtInRect(where, &viewRect)) {
  618.             newBalloon = hbQueryResult;
  619.             hotRect = viewRect;
  620.         } else if (SiteMenu && PtInRect(where, &PopupRect)) {
  621.             newBalloon = hbQueryPopup;
  622.             hotRect = PopupRect;
  623.         } else if (PtInRect(where, &(**doitBtn).contrlRect)) {
  624.             newBalloon = okToDoit ? 
  625.                 hbQueryDoitEnabled : hbQueryDoitDisabled;
  626.                 hotRect = (**doitBtn).contrlRect;
  627.         } else if (PtInRect(where, &(**scrollBar).contrlRect)) {
  628.             newBalloon = (**scrollBar).contrlMin < (**scrollBar).contrlMax ?
  629.                 hbScrollEnabled : hbScrollDisabled;
  630.                 hotRect = (**scrollBar).contrlRect;
  631.         } else {
  632.             hotRect = w->portRect;
  633.             hotRect.top = hotRect.bottom - sBarWidthM1;
  634.             hotRect.left = hotRect.right - sBarWidthM1;
  635.             if (PtInRect(where, &hotRect)) {
  636.                 newBalloon = hbGrow;
  637.             } else {
  638.                 newBalloon = 0;
  639.             }
  640.         }
  641.         if (!HMIsBalloon()) oldBalloon = 0;
  642.         if (newBalloon != oldBalloon) {
  643.             if (newBalloon) {
  644.                 LocalToGlobal((Point*)&hotRect);
  645.                 LocalToGlobal((Point*)&hotRect.bottom);
  646.                 tip.h = (hotRect.left + hotRect.right) >> 1;
  647.                 tip.v = (hotRect.top + hotRect.bottom) >> 1;
  648.                 helpMsg.hmmHelpType = khmmStringRes;
  649.                 helpMsg.u.hmmStringRes.hmmResID = hbStringsId;
  650.                 helpMsg.u.hmmStringRes.hmmIndex = newBalloon;
  651.                 if (!HMShowBalloon(&helpMsg, tip, &hotRect, 
  652.                     nil, 0, 0, kHMRegularWindow)) oldBalloon = newBalloon;
  653.             } else {
  654.                 oldBalloon = 0;
  655.             }
  656.         }
  657.     }
  658. }
  659.  
  660. /*_____________________________________________________________________
  661.  
  662.     query_DoClick - Process a Mouse Down Event.
  663.     
  664.     Entry:    w = pointer to window record.
  665.                 where = mouse click location in local coordinates.
  666.                 modifiers = modifiers from event record.
  667. _____________________________________________________________________*/
  668.  
  669. void query_DoClick (WindowPtr w, Point where, short modifiers)
  670.  
  671. {
  672.     QueryInfo        **e;                    /* handle to query info */
  673.     short                oldInx;                /* old index of server in menu */
  674.     short                newInx;                /* new index of server in menu */
  675.     Str255            newDomain;            /* new server domain name */
  676.     TEHandle            teHandle;            /* handle to TextEdit record */
  677.     ControlHandle    whichControl;        /* control clicked in */
  678.     short                partCode;            /* control part code */
  679.     short                oldVal;                /* old scroll bar control value */
  680.     short                dv;                    /* amount to scroll */
  681.     Rect                viewRect;            /* view rect */
  682.     
  683.     e = GetQueryInfo(w);
  684.     GetViewRect(w, &viewRect);
  685.     if (SiteMenu && PtInRect(where, &PopupRect)) {
  686.         oldInx = (**e).serverInx;
  687.         glob_PopupSiteMenu(&PopupRect, oldInx, &newInx, newDomain); 
  688.         if (newInx != -1) {
  689.             (**e).serverInx = newInx;
  690.             teHandle = (**e).domain;
  691.             TESetText(newDomain+1, *newDomain, teHandle);
  692.             InvalRect(&DomainRect);
  693.         }
  694.     } else if (PtInRect(where, &DomainClickRect)) {
  695.         if ((**e).curEdit != (**e).domain) {
  696.             TEDeactivate((**e).curEdit);
  697.             (**e).curEdit = (**e).domain;
  698.             TEActivate((**e).domain);
  699.         }
  700.         TEClick(where, modifiers & shiftKey ? true : false, (**e).domain);
  701.     } else if (PtInRect(where, &QueryClickRect)) {
  702.         if ((**e).curEdit != (**e).query) {
  703.             TEDeactivate((**e).curEdit);
  704.             (**e).curEdit = (**e).query;
  705.             TEActivate((**e).query);
  706.         }
  707.         TEClick(where, modifiers & shiftKey ? true : false, (**e).query);
  708.     } else if (PtInRect(where, &viewRect)) {
  709.         if ((**e).curEdit != (**e).reply) {
  710.             TEDeactivate((**e).curEdit);
  711.             (**e).curEdit = (**e).reply;
  712.             TEActivate((**e).reply);
  713.         }
  714.         TEAutoView(true, (**e).reply);
  715.         TEClick(where, modifiers & shiftKey ? true : false, (**e).reply);
  716.         TEAutoView(false, (**e).reply);
  717.         SetCtlValue((**e).scrollBar, headerHeight - (**(**e).reply).destRect.top);
  718.     } else {
  719.         partCode = FindControl(where, w, &whichControl);
  720.         if (whichControl == (**e).doitBtn) {
  721.             if (TrackControl(whichControl, where, nil)) {
  722.                 Doit(w);
  723.             }
  724.         } else if (whichControl == (**e).scrollBar) {
  725.             if (partCode == inThumb) {
  726.                 oldVal = GetCtlValue(whichControl);
  727.                 TrackControl(whichControl, where, nil);
  728.                 dv = GetCtlValue(whichControl) - oldVal;
  729.                 if (dv) Scroll(w, -dv);
  730.             } else {
  731.                 TrackControl(whichControl, where, (ProcPtr)ScrollAction);
  732.             }
  733.             AdjustScrollMax(w);
  734.         }
  735.     }
  736. }
  737.  
  738. /*_____________________________________________________________________
  739.  
  740.     query_DoKey - Process a Key Down Event.
  741.     
  742.     Entry:    w = pointer to window record.
  743.                 key = ascii code of key.
  744.                 modifiers = modifiers from event record.
  745. _____________________________________________________________________*/
  746.  
  747. void query_DoKey (WindowPtr w, char key, short modifiers)
  748.  
  749. {
  750. #pragma unused (modifiers)
  751.  
  752.     QueryInfo        **e;                /* handle to query info */
  753.     ControlHandle    scrollBar;        /* handle to scroll bar */
  754.     short                val;                /* scroll bar value */
  755.     short                min;                /* scroll bar minimum value */
  756.     short                max;                /* scroll bar maximum value */
  757.  
  758.     e = GetQueryInfo(w);
  759.     if (key == returnKey || key == enterKey) {
  760.         if ((**(**e).doitBtn).contrlHilite) {
  761.             SysBeep(0);
  762.         } else {
  763.             utl_FlashButton((**e).doitBtn);
  764.             Doit(w);
  765.         }
  766.     } else if (key == tabKey) {
  767.         if (modifiers & shiftKey) {
  768.             if ((**e).curEdit == (**e).query) {
  769.                 TEDeactivate((**e).query);
  770.                 TESetSelect(0, 0xffff, (**e).domain);
  771.                 TEActivate((**e).domain);
  772.                 (**e).curEdit = (**e).domain;
  773.             } else if ((**e).curEdit == (**e).domain) {
  774.                 TEDeactivate((**e).domain);
  775.                 (**e).curEdit = (**e).reply;
  776.                 TESetSelect(0, 0, (**e).reply);
  777.                 if (!SelectEmailAddress(w, true, true)) TESetSelect(0, 0xffff, (**e).reply);
  778.                 TEActivate((**e).reply);
  779.             } else if ((**e).curEdit == (**e).reply) {
  780.                 if (!SelectEmailAddress(w, true, true)) {
  781.                     TEDeactivate((**e).reply);
  782.                     TESetSelect(0, 0xffff, (**e).query);
  783.                     TEActivate((**e).query);
  784.                     (**e).curEdit = (**e).query;
  785.                 }
  786.             }
  787.         } else {
  788.             if ((**e).curEdit == (**e).domain) {
  789.                 TEDeactivate((**e).domain);
  790.                 TESetSelect(0, 0xffff, (**e).query);
  791.                 TEActivate((**e).query);
  792.                 (**e).curEdit = (**e).query;
  793.             } else if ((**e).curEdit == (**e).query) {
  794.                 TEDeactivate((**e).query);
  795.                 (**e).curEdit = (**e).reply;
  796.                 TESetSelect(0, 0, (**e).reply);
  797.                 if (!SelectEmailAddress(w, true, false)) TESetSelect(0, 0xffff, (**e).reply);
  798.                 TEActivate((**e).reply);
  799.             } else if ((**e).curEdit == (**e).reply) {
  800.                 if (!SelectEmailAddress(w, true, false)) {
  801.                     TEDeactivate((**e).reply);
  802.                     TESetSelect(0, 0xffff, (**e).domain);
  803.                     TEActivate((**e).domain);
  804.                     (**e).curEdit = (**e).domain;
  805.                 }
  806.             }
  807.         }
  808.     } else if (utl_StandardAsciiChar(key) || key == deleteKey) {
  809.         if ((**e).curEdit == (**e).reply) {
  810.             TEDeactivate((**e).reply);
  811.             TESetSelect(0, 0xfffff, (**e).query);
  812.             TEActivate((**e).query);
  813.             (**e).curEdit = (**e).query;
  814.         }
  815.         TEKey(key, (**e).curEdit);
  816.     } else if (key == leftArrow || key == rightArrow ||
  817.         (key == downArrow || key == upArrow) && (**e).curEdit == (**e).reply) {
  818.         TEAutoView(true, (**e).curEdit);
  819.         TEKey(key, (**e).curEdit);
  820.         TEAutoView(false, (**e).curEdit);
  821.         SetCtlValue((**e).scrollBar, headerHeight - (**(**e).reply).destRect.top);
  822.     } else if (key == pageUpKey || key == pageDownKey ||
  823.         key == homeKey || key == endKey) {
  824.         scrollBar = (**e).scrollBar;
  825.         val = (**scrollBar).contrlValue;
  826.         min = (**scrollBar).contrlMin;
  827.         max = (**scrollBar).contrlMax;
  828.         if (key == pageUpKey) {
  829.             ScrollAction(scrollBar, inPageUp);
  830.         } else if (key == pageDownKey) {
  831.             ScrollAction(scrollBar, inPageDown);
  832.         } else if (key == homeKey) {
  833.             SetCtlValue(scrollBar, min);
  834.             Scroll(w, val-min);
  835.         } else {
  836.             SetCtlValue(scrollBar, max);
  837.             Scroll(w, val-max);
  838.         }
  839.     } else {
  840.         SysBeep(0);
  841.     }
  842. }
  843.  
  844. /*_____________________________________________________________________
  845.  
  846.     query_DoUpdate - Process an Update Event.
  847. _____________________________________________________________________*/
  848.  
  849. void query_DoUpdate (WindowPtr w)
  850.  
  851. {
  852.     QueryInfo    **e;                    /* handle to query info */
  853.     short            right;                /* right coord window portrect */
  854.     Rect            frameRect;            /* framing rect */
  855.     Rect            viewRect;            /* view rect */
  856.  
  857.     e = GetQueryInfo(w);
  858.     EraseRect(&w->portRect);
  859.     DrawControls(w);
  860.     frameRect = (**(**e).doitBtn).contrlRect;
  861.     InsetRect(&frameRect, -4, -4);
  862.     PenSize(3, 3);
  863.     FrameRoundRect(&frameRect, 16, 16);
  864.     PenSize(1, 1);
  865.     if (SiteMenu) glob_DrawSitePopup(&PopupRect, (**e).serverInx);
  866.     FrameRect(&DomainRect);
  867.     TEUpdate(&DomainRect, (**e).domain);
  868.     FrameRect(&QueryRect);
  869.     TEUpdate(&QueryRect, (**e).query);
  870.     MoveTo(0, headerRule);
  871.     right = w->portRect.right;
  872.     Line(right, 0);
  873.     MoveTo(0, headerRule+2);
  874.     Line(right, 0);
  875.     GetViewRect(w, &viewRect);
  876.     TEUpdate(&viewRect, (**e).reply);
  877.     DrawGrowBox(w);
  878. }
  879.  
  880. /*_____________________________________________________________________
  881.  
  882.     query_DoActivate - Process an Activate Event.    
  883.     
  884.     Entry:    w = pointer to window record.
  885. _____________________________________________________________________*/
  886.  
  887. void query_DoActivate (WindowPtr w)
  888.  
  889. {
  890.     QueryInfo        **e;            /* handle to query info */
  891.     
  892.     e = GetQueryInfo(w);
  893.     ShowControl((**e).scrollBar);
  894.     TEActivate((**e).curEdit);
  895.     DrawGrowBox(w);
  896. }
  897.  
  898. /*_____________________________________________________________________
  899.  
  900.     query_DoDeactivate - Process a Deactivate Event.    
  901.     
  902.     Entry:    w = pointer to window record.
  903. _____________________________________________________________________*/
  904.  
  905. void query_DoDeactivate (WindowPtr w)
  906.  
  907. {
  908.     QueryInfo        **e;            /* handle to query info */
  909.     
  910.     e = GetQueryInfo(w);
  911.     HideControl((**e).scrollBar);
  912.     TEDeactivate((**e).curEdit);
  913.     DrawGrowBox(w);
  914. }
  915.  
  916. /*_____________________________________________________________________
  917.  
  918.     query_DoGrow - Process Window Grow Operation.
  919.     
  920.     Entry:    w = pointer to window record.
  921.                 where = location of mouse click in global coordinates.
  922. _____________________________________________________________________*/
  923.  
  924. void query_DoGrow(WindowPtr w, Point where)
  925.  
  926. {
  927.     unsigned long            newSize;            /* new window size */
  928.     short                        height;            /* new window height */
  929.     short                        width;            /* new window width */
  930.  
  931.     SetPort(w);
  932.     newSize = GrowWindow(w, where, &SizeRect);
  933.     if (!newSize) return;
  934.     height = newSize >> 16;
  935.     if (!(height & 1)) height--;
  936.     width = newSize & 0xffff;
  937.     InvalScroll(w);
  938.     SizeWindow(w, width, height, true);
  939.     InvalScroll(w);
  940.     ChangeSize(w, height);
  941. }
  942.  
  943. /*_____________________________________________________________________
  944.  
  945.     query_DoZoom - Process Window Zoom Operation.
  946.     
  947.     Entry:    w = pointer to window record.
  948.                 where = location of mouse click in global coordinates.
  949.                 partCode = inZoomIn or inZoomOut
  950. _____________________________________________________________________*/
  951.  
  952. void query_DoZoom (WindowPtr w, Point where, short partCode)
  953.  
  954. {
  955.     if (!TrackBox(w, where, partCode)) return;
  956.     SetPort(w);
  957.     if (partCode == inZoomOut) wstm_ComputeStd(w);
  958.     EraseRect(&w->portRect);
  959.     ZoomWindow(w, partCode, false);
  960.     ChangeSize(w, w->portRect.bottom - w->portRect.top);
  961. }
  962.  
  963. /*_____________________________________________________________________
  964.  
  965.     query_DoClose - Close Window.
  966.     
  967.     Entry:    w = pointer to window record.
  968. _____________________________________________________________________*/
  969.  
  970. void query_DoClose (WindowPtr w)
  971.  
  972. {
  973.     CloseQueryWindow(w);
  974. }
  975.  
  976. /*_____________________________________________________________________
  977.  
  978.     query_DoCommand - Process a Command.
  979.     
  980.     Entry:    top = pointer to top window record.
  981.                 theMenu = menu number.
  982.                 theItem = menu item number.
  983. _____________________________________________________________________*/
  984.  
  985. #pragma segment command
  986.  
  987. Boolean query_DoCommand (WindowPtr top, short theMenu, short theItem)
  988.  
  989. {
  990.     QueryInfo        **e;            /* handle to query info */
  991.     TEHandle            textH;        /* handle to active TextEdit record */
  992.     Handle            scrap;        /* handle to scrap to be pasted */
  993.     short                scrapLen;    /* length of scrap to be pasted */
  994.     char                *p;            /* pointer to scrap char */
  995.     
  996.     if (top) e = GetQueryInfo(top);
  997.     switch (theMenu) {
  998.         case fileID:
  999.             switch (theItem) {
  1000.                 case newQueryCmd:
  1001.                     NewQueryWindow();
  1002.                     return true;
  1003.             }
  1004.             break;
  1005.         case editID:
  1006.             if (!top) break;
  1007.             textH = (**e).curEdit;
  1008.             switch (theItem) {
  1009.                 case cutCmd:
  1010.                 case copyCmd:
  1011.                     if (theItem == cutCmd) {
  1012.                         TECut(textH);
  1013.                     } else {
  1014.                         TECopy(textH);
  1015.                     }
  1016.                     ZeroScrap();
  1017.                     TEToScrap();
  1018.                     return true;
  1019.                 case pasteCmd:
  1020.                     TEFromScrap();
  1021.                     scrap = TEScrapHandle();
  1022.                     scrapLen = GetHandleSize(scrap);
  1023.                     if (scrapLen > 255) {
  1024.                         SysBeep(0);
  1025.                         return true;
  1026.                     }
  1027.                     p = *scrap;
  1028.                     while (scrapLen--) {
  1029.                         if (!utl_StandardAsciiChar(*p)) {
  1030.                             SysBeep(0);
  1031.                             return true;
  1032.                         };
  1033.                         p++;
  1034.                     }
  1035.                     TEPaste(textH);
  1036.                     return true;
  1037.                 case clearCmd:
  1038.                     TEDelete(textH);
  1039.                     return true;
  1040.                 case selectAllCmd:
  1041.                     TESetSelect(0, 32767, textH);
  1042.                     return true;
  1043.             }
  1044.             break;
  1045.     }
  1046.     return false;
  1047. }
  1048.  
  1049. #pragma segment query
  1050.  
  1051. /*_____________________________________________________________________
  1052.  
  1053.     query_Init - Initialize
  1054. _____________________________________________________________________*/
  1055.  
  1056. #pragma segment init
  1057.  
  1058. void query_Init (void)
  1059.  
  1060. {
  1061.     WindowPtr    w;                    /* pointer to dummy window */
  1062.     
  1063.     w = GetNewWindow(queryWindID, nil, (WindowPtr)-1);
  1064.     SetPort(w);
  1065.     SetRect(&SizeRect, w->portRect.right+1, minWindHeight, 
  1066.         w->portRect.right+1, 0x7fff);
  1067.     DisposeWindow(w);
  1068.     oop_RegisterCommandHandler(query_DoCommand);
  1069.     if (SiteMenu) {
  1070.         CalcMenuSize(SiteMenu);
  1071.         PopupRect.left = PopupRect.right - (**SiteMenu).menuWidth;
  1072.         if (PopupRect.left < popupLeft) PopupRect.left = popupLeft;
  1073.     }
  1074.     NewQueryWindow();
  1075. }
  1076.  
  1077. #pragma segment query
  1078.  
  1079. /*_____________________________________________________________________
  1080.  
  1081.     query_CanEditField - Check to See if Current Field Can be Edited.
  1082.     
  1083.     Entry:    w = pointer to window record.
  1084.     
  1085.     Exit:        function result = true if current field can be edited.
  1086. _____________________________________________________________________*/
  1087.  
  1088. Boolean query_CanEditField (WindowPtr w)
  1089.  
  1090. {
  1091.     QueryInfo        **e;                /* handle to query info */
  1092.     
  1093.     e = GetQueryInfo(w);
  1094.     return (**e).curEdit != (**e).reply;
  1095. }
  1096.  
  1097. /*_____________________________________________________________________
  1098.  
  1099.     query_NewSiteList - Process New Site List.
  1100. _____________________________________________________________________*/
  1101.  
  1102. void query_NewSiteList (void)
  1103.  
  1104. {
  1105.     WindowPtr        v;                /* traverses window list */
  1106.     QueryInfo        **g;            /* handle to query info for window v */
  1107.     Rect                r;                /* rect to invalidate */
  1108.     TEHandle            domain;        /* handle to domain terec */
  1109.     short                domainLen;    /* length of domain name */
  1110.     Str255            server;        /* server */
  1111.     short                i;                /* loop index */
  1112.     char                *p;            /* pointer to server domain name */
  1113.     
  1114.     r = PopupRect;
  1115.     InsetRect(&r, -2, -2);
  1116.     r.left = 0;
  1117.     v = FrontWindow();
  1118.     while (v) {
  1119.         if (oop_GetWindKind(v) == queryWind) {
  1120.             g = GetQueryInfo(v);
  1121.             SetPort(v);
  1122.             if (SiteMenu) {
  1123.                 domain = (**g).domain;
  1124.                 domainLen = (**domain).teLength;
  1125.                 if (domainLen > 255) domainLen = 255;
  1126.                 *server = domainLen;
  1127.                 memcpy(server+1, *(**domain).hText, domainLen);
  1128.                 p = *Servers;
  1129.                 for (i = 1; i <= NumSites; i++) {
  1130.                     if (EqualString(server, p, true, true)) break;
  1131.                     p += *p+1;
  1132.                 }
  1133.                 if (i > NumSites) i = 1;
  1134.                 (**g).serverInx = i;
  1135.             }
  1136.             InvalRect(&r);
  1137.         }
  1138.         v = (WindowPtr)((WindowPeek)v)->nextWindow;
  1139.     }
  1140.     if (SiteMenu) {
  1141.         CalcMenuSize(SiteMenu);
  1142.         PopupRect.left = PopupRect.right - (**SiteMenu).menuWidth;
  1143.         if (PopupRect.left < popupLeft) PopupRect.left = popupLeft;
  1144.     }
  1145. }
  1146.  
  1147. /*_____________________________________________________________________
  1148.  
  1149.     query_NewDefaultSite - Process New Default Site.
  1150. _____________________________________________________________________*/
  1151.  
  1152. void query_NewDefaultSite (void)
  1153.  
  1154. {
  1155.     WindowPtr            v;                /* traverses window list */
  1156.     QueryInfo            **g;            /* handle to query info for window v */
  1157.     
  1158.     v = FrontWindow();
  1159.     while (v) {
  1160.         if (oop_GetWindKind(v) == queryWind) {
  1161.             g = GetQueryInfo(v);
  1162.             SetPort(v);
  1163.             TESetText(DefaultServer+1, *DefaultServer, (**g).domain);
  1164.             (**g).serverInx = glob_GetSiteIndex(DefaultServer);
  1165.             InvalRect(&PopupRect);
  1166.             InvalRect(&DomainRect);
  1167.         }
  1168.         v = (WindowPtr)((WindowPeek)v)->nextWindow;
  1169.     }
  1170. }
  1171.  
  1172. /*_____________________________________________________________________
  1173.  
  1174.     query_Terminate - Terminate.
  1175. _____________________________________________________________________*/
  1176.  
  1177. void query_Terminate (void)
  1178.  
  1179. {
  1180.     WindowPtr        v;                /* traverses window list */
  1181.     QueryInfo        **g;            /* handle to query info for window v */
  1182.     short                windNum;        /* window number */
  1183.     
  1184.     v = FrontWindow();
  1185.     while (v) {
  1186.         if (oop_GetWindKind(v) == queryWind) {
  1187.             g = GetQueryInfo(v);
  1188.             windNum = (**g).windNum;
  1189.             if (windNum <= numPosSave) wstm_Save(v, &QueryStates[windNum]);
  1190.         }
  1191.         v = (WindowPtr)((WindowPeek)v)->nextWindow;
  1192.     }
  1193. }
  1194.