home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Applications / Eudora 1.3.1 / source / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-16  |  29.0 KB  |  1,212 lines  |  [TEXT/MPS ]

  1. #define FILE_NUM 22
  2. /* Copyright (c) 1990-1992 by the University of Illinois Board of Trustees */
  3. #pragma load EUDORA_LOAD
  4. #pragma segment Main
  5. #ifdef    KERBEROS
  6. #include                <krb.h>
  7. #endif
  8.  
  9. #define TICKS2MINS 3600
  10.  
  11.     Boolean HandleEvent(EventRecord *event);
  12.     extern void UnloadSegments(void);
  13.     void HouseKeeping(long activeTicks);
  14.     void DoKeyDown(WindowPtr topWin,EventRecord *event);
  15.     void DoMouseDown(WindowPtr topWin,EventRecord *event);
  16.     Boolean DoUpdate(WindowPtr topWin,EventRecord *event);
  17.     Boolean DoActivate(WindowPtr topWin,EventRecord *event);
  18.     Boolean DoApp4(WindowPtr topWin,EventRecord *event);
  19.     Boolean DoApp1(MyWindowPtr topWin,EventRecord *event);
  20.     void DoContentClick(MyWindowPtr topWin,MyWindowPtr win,EventRecord *event);
  21.     void NotifyNewMail(void);
  22.     void NewMailSound(void);
  23.     Boolean DoDisk(long message);
  24.     void TendNotificationManager(Boolean isActive);
  25.     long CloseUnused(void);
  26.  
  27. #ifndef KERBEROS
  28. void main()
  29. #else
  30. void c_main()
  31. #endif
  32. {
  33.     EventRecord theEvent;
  34.     MyWindowPtr topWin;
  35.     Boolean active=True;
  36.     long houseTicks=0;
  37.     long activeTicks=TickCount();
  38.     
  39.     /*
  40.      * perform set-up, including initializing mac managers
  41.      */
  42.     UnloadSegments();
  43.     Initialize();
  44.     UnloadSegments();
  45.  
  46.     /*
  47.      * run the event loop
  48.      */
  49.     while (!EjectBuckaroo && !Done)
  50.     {
  51. #ifdef DEBUG
  52.     if (BUG3 && !FrontWindow())
  53.     {
  54.         Str63 s;
  55.         long grow, newFree;
  56.         static long oldFree=1L<<30;
  57.         (void) MaxMem(&grow);
  58.         newFree = FreeMem();
  59.         if (oldFree>newFree)
  60.         {
  61.             DebugStr(ComposeString(s,"\p#%d;ht;g",oldFree-newFree));
  62.             AlertStr(OK_ALRT,Stop,ComposeString(s,
  63.              "\pLeak? was %d, now %d (%d)",oldFree,newFree,oldFree-newFree));
  64.         }
  65.         oldFree = newFree;
  66.     }
  67. #endif
  68. #ifdef DEBUG
  69.         if (BUG6) DebugStr("\p;hc;g");
  70. #endif
  71.         CommandPeriod = False;
  72.         
  73.         /*
  74.          * allocate a window here, in case we need it later
  75.          */
  76.         if (!HandyWindow)
  77.         {
  78.             HandyWindow = New(MyWindow);
  79.             if (HandyWindow != nil) WriteZero(HandyWindow,sizeof(MyWindow));
  80.         }
  81.         
  82.         /*
  83.          * handle any events we might come across 
  84.          */
  85.         active = GrabEvent(&theEvent) ? HandleEvent(&theEvent) : False;
  86.         if (active)
  87.             activeTicks = TickCount();
  88.         
  89.         TendNotificationManager(active);
  90.         
  91.         if (TickCount()-houseTicks > 120)
  92.         {
  93.             HouseKeeping(TickCount()-activeTicks);
  94.             houseTicks = TickCount();
  95.         }
  96.  
  97. #ifndef SLOW_CLOSE
  98.         /*
  99.      * destroy defunct streams
  100.        */
  101.         TcpFastFlush(False);
  102. #endif
  103.             
  104.         /*
  105.          * blink caret, if need be
  106.          */
  107.         topWin = FrontWindow();
  108.         if (topWin && IsMyWindow(topWin) && !InBG)
  109.         {
  110.             if (topWin->txe) TEIdle(topWin->txe);
  111.             else if (topWin->ste) TEIdle((*(STEHandle)topWin->ste)->te);
  112.         }
  113.         
  114.         /*
  115.          * write dirty toc's
  116.          */
  117.         if (!PrefIsSet(PREF_CORVAIR)) FlushTOCs(False,True);
  118.         
  119.         /*
  120.          * cursor & help
  121.          */
  122.         if (SFWTC) SetCursorByLocation();
  123.         if (theEvent.what==nullEvent && HasHelp && !InBG && HMGetBalloons())
  124.             DoHelp(topWin);
  125.                     
  126.         /*
  127.          * here's an interesting little goodie
  128.          */
  129.         if (theEvent.what==nullEvent && !InBG && AliasWinIsOpen() &&
  130.                 FrontWindow() && IsMyWindow(FrontWindow()) &&
  131.                 ((MyWindowPtr)(FrontWindow()))->txe && PrefIsSet(PREF_NICK_FOLLOW))
  132.         {
  133.             switch (((MyWindowPtr)(FrontWindow()))->qWindow.windowKind)
  134.             {
  135.                 case COMP_WIN:
  136.                 case TEXT_WIN:
  137.                     FinishAlias(FrontWindow(),False,True);
  138.                     break;
  139.                 default: break;
  140.             }
  141.         }
  142.  
  143.         /*
  144.          * Unload all segments
  145.          */
  146.         UnloadSegments();
  147.         
  148.         /*
  149.          * debugging...
  150.          */
  151. #ifdef DEBUG
  152.         {
  153.             extern void **AliasGlobals;
  154.             ASSERT(!AliasGlobals || Notes && *Notes);
  155.         }
  156. #endif
  157.         
  158.         /*
  159.          * all windows are fair game
  160.          */
  161.         NotUsingAllWindows();
  162.         if (EjectBuckaroo) DoQuit();
  163.     }
  164.     if (PrefIsSet(PREF_AUTO_EMPTY)) EmptyTrash();
  165.     FlushTOCs(True,False);
  166.     Cleanup();
  167. }
  168. /************************************************************************
  169.  * HouseKeeping - periodic cleanup functions
  170.  ************************************************************************/
  171. void HouseKeeping(long activeTicks)
  172. {
  173.     static long flushTicks=0;
  174.  
  175.     if (activeTicks)
  176.     {
  177.         long ivalTicks = TICKS2MINS * GetRLong(PREF_STRN+PREF_INTERVAL);
  178.  
  179.         /*
  180.          * warn the user if we're growing low (get it) on memory
  181.          */
  182.         MonitorGrow();
  183.     
  184.         /*
  185.          * check mail?
  186.          */
  187.         if (activeTicks > 60*60)
  188.         {
  189.             if (ivalTicks && (!CheckTicks || TickCount()-CheckTicks > ivalTicks))
  190.             {
  191.                 if (!(CurrentModifiers()&optionKey))
  192.                 {
  193.                     CheckForMail(False);
  194.                 }
  195.             }
  196.             if (ForceSend <= GMTDateTime()) {SetSendQueue();DoSendQueue();}
  197.         }
  198.         
  199.         /*
  200.          * close unneeded TOC's
  201.          */
  202.         FlushTOCs(True,True);
  203.         
  204.         /*
  205.          * just for good measure
  206.          */
  207.         if (TickCount()-flushTicks > 60*GetRLong(FLUSH_SECS))
  208.         {
  209.             FlushVol(nil,MyVRef);
  210.             flushTicks = TickCount();
  211.         }
  212.         
  213.         /*
  214.          * The resolver may have left us little poodle bombs...
  215.          */
  216.         FlushHIQ();
  217.         
  218.         /*
  219.          * and logging...
  220.          */
  221.         if (!(LogLevel&LOG_EVENT)) CloseLog();
  222.         
  223.         /*
  224.          * and that pesky settings file
  225.          */
  226.         UpdateResFile(SettingsRefN);
  227.         
  228.         /*
  229.          * for debugging
  230.          */
  231. #ifdef DEBUG
  232.         if (BUG7)
  233.         {
  234.             long bytes;
  235.             MaxMem(&bytes);
  236.         }
  237. #endif
  238.     }
  239. }
  240.  
  241. /**********************************************************************
  242.  * HandleEvent - handle an event
  243.  **********************************************************************/
  244. Boolean HandleEvent(EventRecord *event)
  245. {
  246.     WindowPtr topWin = FrontWindow();     /* in case we need to know */
  247.     Boolean active=False;
  248.     
  249.     if (IsDialogEvent(event))
  250.     {
  251.       DoModelessEvent(event);
  252.         return(True);
  253.     }
  254.  
  255.     if (topWin)
  256.     {
  257.         SetPort(topWin);
  258.         UsingWindow(topWin);
  259.     }
  260.     else
  261.         SetPort(InsurancePort);
  262.     /*
  263.      * slog through all the events...
  264.      */
  265.     switch (event->what)
  266.     {
  267.         case keyDown:
  268.         case autoKey:
  269.             /*if (HasHelp && HMIsBalloon()) HMRemoveBalloon();*/
  270.             DoKeyDown(topWin,event);
  271.             active = True;
  272.             break;
  273.         
  274.         case mouseUp:
  275.         case mouseDown:
  276.             /*if (HasHelp && HMIsBalloon()) HMRemoveBalloon();*/
  277.             DoMouseDown(topWin,event);
  278.             active = True;
  279.             break;
  280.             
  281.         case updateEvt:
  282.             DoUpdate(topWin,event);
  283.             break;
  284.             
  285.         case activateEvt:
  286.             if (!InBG) DoActivate(topWin,event);
  287.             break;
  288.             
  289.         case app4Evt:
  290.             active = DoApp4(topWin,event);
  291.             break;
  292.             
  293.         case app1Evt:
  294.             active = DoApp1(topWin,event);
  295.             break;
  296.             
  297.         case diskEvt:
  298.             active = DoDisk(event->message);
  299.             break;
  300.     }
  301.     if (!ForceSend) SetSendQueue();    /* a message from beyond */
  302.     EnableMenus(FrontWindow());     /* enable the correct menu items */
  303.     return(active);
  304. }
  305.  
  306. /************************************************************************
  307.  *
  308.  ************************************************************************/
  309. Boolean DoDisk(long message)
  310. {
  311.     if ((message>>16)&0xffff)
  312.     {
  313.         Point pt;
  314.         pt.h = pt.v = 50;
  315.         DILoad();
  316.         (void) DIBadMount(pt,message);
  317.         DIUnload();
  318.     }
  319.     return(True);
  320. }
  321.  
  322. /**********************************************************************
  323.  * DoApp4 - handle an app4 event; suspend/resume/mouse
  324.  **********************************************************************/
  325. Boolean DoApp4(WindowPtr topWin,EventRecord *event)
  326. {
  327.     if (((event->message>>24)&0xff) == 0xfa)
  328.     {
  329.         SFWTC = True;
  330.         return(False);
  331.     }
  332.     else
  333.     {
  334.         if (((event->message)>>24)&1 == 1)
  335.         {
  336.             if (!InBG)
  337.             {
  338.                 EnableProgress();
  339.                 SFWTC = True;
  340.             }
  341.             else
  342.                 DisableProgress();
  343.             if (CnH) CMResume(CnH,!InBG);
  344.             if (topWin && ((WindowPeek)topWin)->windowKind >= userKind)
  345.                 ActivateMyWindow(topWin,!InBG);
  346.         }
  347.         return(!InBG);
  348.     }
  349. }
  350.  
  351. /**********************************************************************
  352.  * DoApp1 - handle an app1 event; scrolling by saratoga keys
  353.  **********************************************************************/
  354. Boolean DoApp1(MyWindowPtr topWin,EventRecord *event)
  355. {
  356.     if (topWin && IsMyWindow(topWin))
  357.     {
  358.         if (topWin->app1 && (*topWin->app1)(topWin,event))
  359.             ;
  360.       else if (topWin->ste) STEApp1(topWin->ste,event);
  361.         else if (topWin->vBar)
  362.             switch(event->message & charCodeMask)
  363.             {
  364.                 case homeChar:
  365.                     ScrollIt(topWin,INFINITY,INFINITY);
  366.                     break;
  367.                 case endChar:
  368.                     ScrollIt(topWin,0,-INFINITY);
  369.                     break;
  370.                 case pageUpChar:
  371.                     ScrollIt(topWin,0,
  372.                         RoundDiv(topWin->contR.bottom-topWin->contR.top,topWin->vPitch)-1);
  373.                     break;
  374.                 case pageDownChar:
  375.                     ScrollIt(topWin,0,
  376.                         RoundDiv(topWin->contR.top-topWin->contR.bottom,topWin->vPitch)+1);
  377.                     break;
  378.             }
  379.     }
  380.     return(True);
  381. }
  382.  
  383. /**********************************************************************
  384.  * DoKeyDown - handle a keystroke aimed at a window
  385.  **********************************************************************/
  386. void DoKeyDown(WindowPtr topWin,EventRecord *event)
  387. {
  388.     long select;
  389.     short c = UnadornMessage(event)&0xff;
  390.  
  391.     /*
  392.      * handle key equivalents
  393.      */
  394.     if (event->modifiers&cmdKey)
  395.     {
  396.         if (select=MyMenuKey(event))
  397.         {
  398.             DoMenu(topWin,select,event->modifiers);
  399.             return;
  400.         }
  401.     }
  402.     if (topWin && ((WindowPeek)topWin)->windowKind >= userKind)
  403.     {
  404.         MyWindowPtr mw = (MyWindowPtr) topWin;
  405.         TEHandle teh = WinTEH(mw);
  406.         
  407.         SetPort(mw);
  408.         if (mw->key)
  409.             (*mw->key)(mw,event);
  410.         else if (event->modifiers&cmdKey)
  411.             SysBeep(20L);
  412.         else if (!teh)
  413.             AlertStr(NOT_HOME_ALRT, Stop, nil);
  414.         else if (mw->ro && DirtyKey(event->message))
  415.             AlertStr(READ_ONLY_ALRT, Stop, nil);
  416.         else
  417.         {
  418.             TEActivate(teh);
  419.             if ((event->message&0xff)==tabKey)
  420.                 TEFakeTab(mw,GetRLong(TAB_DISTANCE));
  421.             else
  422.                 TESomething(mw,TEKEY,event->message&charCodeMask,event->modifiers);
  423.         }
  424.     }
  425.     else if (event->modifiers&cmdKey)
  426.         SysBeep(20L);
  427.     else
  428.         StopAlert(NOT_HOME_ALRT, nil);
  429. }
  430.  
  431. pascal void Hook(void)
  432. {
  433.     if (RunType != Production && CurrentModifiers()&controlKey)
  434.     {
  435.         Handle fkey3;
  436.         if (fkey3 = GetResource('FKEY',3))
  437.         {
  438.             (*(ProcPtr)LDRef(fkey3))();
  439.             UL(fkey3);
  440.         }
  441.         else SysBeep(10);
  442.     }
  443. }
  444.  
  445. /**********************************************************************
  446.  * DoMouseDown - handle a mouse-down event, goodness knows where
  447.  **********************************************************************/
  448. void DoMouseDown(WindowPtr topWin,EventRecord *event)
  449. {
  450.     static Point downSpot;    /* Point of previous mouseDown */
  451.     static long upTicks;        /* time of previous mouseUp */
  452.     long dblTime;                        /* double-click time from PRAM */
  453.     long wPart;                         /* window part where click occurred */
  454.     MyWindowPtr win;                /* window where click occurred */
  455.     short tolerance;
  456.     long mSelect;
  457.     
  458.     if (event->what==mouseUp)
  459.     {
  460.         upTicks = event->when-1;
  461.         return;
  462.     }
  463.     
  464.     dblTime = GetDblTime();
  465.     tolerance = GetRLong(DOUBLE_TOLERANCE);
  466.     
  467.     /*
  468.      * figure out whether this is a double or triple click,
  469.      * and update double and triple click times
  470.      */
  471.     if (event->when!=upTicks && event->when-upTicks<dblTime)
  472.     {
  473.         int dx = event->where.h - downSpot.h;
  474.         int dy = event->where.v - downSpot.v;
  475.         if (ABS(dx)<tolerance && ABS(dy)<tolerance && !(event->modifiers&cmdKey))
  476.         {
  477.             /* upgrade the click */
  478.             ClickType++;
  479.             if (ClickType > Triple) ClickType = Single;
  480.         }
  481.         else
  482.             ClickType = Single;
  483.     }
  484.     else
  485.         ClickType = Single;
  486.         
  487.     upTicks = event->when;            /* ignore two downs in a row as far as clicktype */
  488.     downSpot = event->where;
  489.     
  490.     /*
  491.      * where was the click?
  492.      */
  493.     wPart = FindWindow(event->where,&win);
  494.     if (CnH && win && (long)CnH==win->qWindow.refCon)
  495.         CMEvent(CnH,event);
  496.     else
  497.         switch (wPart)
  498.         {
  499.             case inMenuBar:
  500.                 EnableMenuItems();
  501.                 mSelect = MenuSelect(event->where);
  502.                 DoMenu(topWin,mSelect,CurrentModifiers());
  503.                 break;
  504.             case inSysWindow:
  505.                 SystemClick(event,win);
  506.                 break;
  507.             case inDrag:
  508.                 DragMyWindow(win,event->where);
  509.                 break;
  510.             case inZoomIn:
  511.             case inZoomOut:
  512.                 if (IsMyWindow(win)) win->saveSize = True;
  513.                 ZoomMyWindow(win,event->where,wPart);
  514.                 break;
  515.             case inGrow:
  516.                 if (!(win->qWindow.windowKind==dialogKind ||
  517.                         win->qWindow.windowKind>=userKind && win->isRunt))
  518.                 {
  519.                     GrowMyWindow(win,event->where);
  520.                     break;
  521.                 }
  522.                 /* fall-through is deliberate */
  523.             case inContent:
  524.                 Undo.didClick = True;
  525.                 DoContentClick(topWin,win,event);
  526.                 break;
  527.             case inGoAway:
  528.                 if (event->modifiers & optionKey)
  529.                     CloseAll();
  530.                 else
  531.                     GoAwayMyWindow(win,event->where);
  532.                 break;
  533.         }
  534. }
  535.  
  536. /**********************************************************************
  537.  * DoContentClick - handle a click in the content region of a window
  538.  **********************************************************************/
  539. void DoContentClick(MyWindowPtr topWin,MyWindowPtr win,EventRecord *event)
  540. {
  541.     Point pt;
  542.     Rect r;
  543.     
  544.     if (win != (MyWindowPtr)topWin)
  545.     {
  546.         SelectWindow(win);
  547.         if (IsMyWindow(win) && win->hot) HandleEvent(event); /* resubmit */
  548.     }
  549.     else
  550.     {
  551.         SetPort(win);
  552.         pt = event->where;
  553.         GlobalToLocal(&pt);
  554.         if (!win->dontControl && HandleControl(pt,win))
  555.             ;
  556.         else if (((WindowPeek)win)->windowKind > userKind)
  557.         {
  558.             if (win->click)
  559.                 (*win->click)(win,event);
  560.             else if (win->ste && ((r=(*(STEHandle)win->ste)->encloseR),PtInRect(pt,&r)))
  561.                 STEClick(win->ste,event);
  562.         }
  563.     }
  564. }
  565.  
  566.  
  567. /************************************************************************
  568.  * 
  569.  ************************************************************************/
  570. Boolean HandleControl(Point pt, MyWindowPtr win)
  571. {
  572.     int part;
  573.     int oldValue, difference;
  574.     ControlHandle cntl;
  575.  
  576.     if (part = FindControl(pt,win,&cntl))
  577.     {
  578.         if ((*cntl)->contrlRfCon!='GREY')
  579.         {
  580.             oldValue = GetCtlValue(cntl);
  581.             part = TrackControl(cntl,pt,part==inThumb ? nil : (UPtr)(-1));
  582.             if (part==inThumb)
  583.             {
  584.                 difference = oldValue - GetCtlValue(cntl);
  585.                 if (difference)
  586.                 {
  587.                     if (ScrollIsH(cntl))
  588.                         ScrollMyWindow(win,difference,0);
  589.                     else
  590.                         ScrollMyWindow(win,0,difference);
  591.                     UpdateMyWindow(win);
  592.                 }
  593.             }
  594.             else if (win->button)
  595.                 (*win->button)(win,cntl,CurrentModifiers(),part);
  596.         }
  597.       return(True);
  598.     }
  599.     return(False);
  600. }
  601.  
  602. /**********************************************************************
  603.  * DoUpdate - handle an update event
  604.  **********************************************************************/
  605. Boolean DoUpdate(WindowPtr topWin,EventRecord *event)
  606. {
  607. #pragma unused(topWin)
  608.     MyWindowPtr win;
  609.     
  610.     win = (MyWindowPtr)event->message;
  611.     if (CnH && win->qWindow.refCon==(long)CnH)
  612.     {
  613.         CMEvent(CnH,event);
  614.         return(False);
  615.     }
  616.     if (IsMyWindow(win))
  617.     {
  618.         UpdateMyWindow(win);
  619.         return(False);
  620.     }
  621.     return(True);    /* somebody else better do this one */
  622. }
  623.  
  624. /**********************************************************************
  625.  * DoActivate - handle an activate event (and a prior deactivate, to boot)
  626.  **********************************************************************/
  627. Boolean DoActivate(WindowPtr topWin,EventRecord *event)
  628. {
  629. #pragma unused(topWin)
  630.     MyWindowPtr win;
  631.     Boolean active = !InBG && (event->modifiers&activeFlag)!=0;
  632.     Boolean yours = False;
  633.     
  634.     win = (MyWindowPtr) event->message;
  635.     if (CnH && (long)CnH==win->qWindow.refCon)
  636.         CMActivate(CnH,active);
  637.     else if (IsMyWindow(win))
  638.     {
  639.         if (active != win->isActive)
  640.             ActivateMyWindow(win,(event->modifiers&activeFlag)!=0);
  641.     }
  642.     else
  643.         yours=True;
  644.     SFWTC=True;
  645.     return(yours);
  646. }
  647.  
  648. /**********************************************************************
  649.  * WarnUser - tell the user that something bad is happening
  650.  **********************************************************************/
  651. int WU(int errorStr,int errorNum,int file,int line)
  652. {
  653.     Str255 message;
  654.     
  655.     ComposeRString(message,WU_FMT,errorStr,errorNum,file,line);
  656.     (void) AlertStr(OK_ALRT,Caution,message);
  657.     return(errorNum);
  658. }
  659.  
  660. /**********************************************************************
  661.  * DieWithError - die with the given error message
  662.  **********************************************************************/
  663. void DWE(int errorStr,int errorNum,int file,int line)
  664. {
  665.     Str255 fatal;
  666.     Str255 message;
  667.     Str255 number;
  668.     Str255 debugStr;
  669.     
  670.     GetRString(fatal,FATAL);
  671.     GetRString(message,errorStr);
  672.     NumToString((long)errorNum,number);
  673.     ComposeRString(debugStr,FILE_LINE_FMT,file,line);
  674.     MyParamText(fatal,message,number,debugStr);
  675.     (void) ReallyDoAnAlert(ERR_ALRT,Stop);
  676.     Cleanup();
  677.     ExitToShell();
  678. }
  679.  
  680. /**********************************************************************
  681.  * DumpData - put up an alert that shows some data.
  682.  **********************************************************************/
  683. void DumpData(UPtr description, UPtr data,int length)
  684. {
  685.     Str255 asAscii;
  686.     Str255 asHex;
  687.     static char hex[]="0123456789abcdef";
  688.     char *ac, *hx;
  689.     char *from;
  690.     
  691.     if (length > 255/2) length = 255/2;
  692.     
  693.     /*
  694.      * prepare display strings
  695.      */
  696.     *asAscii = 2*length;
  697.     *asHex = 2*length;
  698.     ac=asAscii+1;
  699.     hx=asHex+1;
  700.     for (from=data; from<data+length;from++)
  701.     {
  702.         *ac++ = optSpace;
  703.         if (*from==' ')
  704.             *ac++ = optSpace;
  705.         else if (*from<' ')
  706.             *ac++='.';
  707.         else
  708.             *ac++ = *from;
  709.         *hx++ = hex[((*from)>>4)&0xf];
  710.         *hx++ = hex[(*from)&0xf];
  711.     }
  712.     
  713.     SetDAFont(monaco);
  714.     MyParamText(description,asAscii,asHex,"");
  715.     switch (Alert(DUMP_ALRT,nil))
  716.     {
  717.         case DEBUG_BUTTON: Debugger(); break;
  718.         case EXIT_BUTTON:  Cleanup(); ExitToShell(); break;
  719.     }
  720.     SetDAFont(applFont);
  721.  
  722. /**********************************************************************
  723.  * monitor the heap situation
  724.  **********************************************************************/
  725. void MonitorGrow(void)
  726. {
  727.     static long memLeft = SPARE_SIZE;
  728.     long roomLeft = GetHandleSize(SpareSpace);
  729.     long roomAvailable;
  730.     
  731.     if (roomLeft < memLeft)
  732.     {
  733.         UnloadUnneeded(1L<<29);
  734.         FlushTOCs(True,True);
  735.         UnloadUnneeded(1L<<29);
  736.         if (memLeft==SPARE_SIZE || roomLeft+10K<memLeft || roomLeft<MEM_CRITICAL)
  737.             MemoryWarning();
  738.     }
  739.     
  740.     if (roomLeft < memLeft || roomLeft<MEM_CRITICAL)
  741.     {
  742.         memLeft = roomLeft;
  743.         DisposHandle(SpareSpace);
  744.         roomAvailable = CompactMem(SPARE_SIZE);
  745.         if (roomAvailable < SPARE_SIZE)
  746.             roomAvailable = MaxMem(&roomLeft);
  747.         if (roomAvailable > SPARE_SIZE) roomAvailable = SPARE_SIZE;
  748.         MakeGrow(roomAvailable);
  749.     }
  750. }
  751.  
  752. /************************************************************************
  753.  * MemoryWarning - warn the user about how much memory is left.
  754.  ************************************************************************/
  755. MemoryWarning(void)
  756. {
  757.     Str255 partitionString,warningString;
  758.     long currentSize, estSize, spareSize;
  759.     
  760.     currentSize = CurrentSize();
  761.     estSize = EstimatePartitionSize();
  762.     spareSize = GetHandleSize(SpareSpace);
  763.     estSize = MAX(estSize,SPARE_SIZE-spareSize+currentSize);
  764.     (void) ComposeRString(partitionString,MEM_PARTITION,currentSize/(1K),
  765.                                                 estSize/(1K));
  766.     GetRString(warningString,MEM_LOW);
  767.     MyParamText(warningString,partitionString,"\p\n\n\n","");
  768.     if (ReallyDoAnAlert(MEMORY_ALRT,Caution)==MEMORY_QUIT) EjectBuckaroo=True;
  769. }
  770.  
  771. /************************************************************************
  772.  * CurrentSize - how big is our partition?
  773.  ************************************************************************/
  774. long CurrentSize(void)
  775. {
  776.     SizeHandle sizeH;
  777.     long size=0;
  778.     
  779.     if (sizeH = GetResource('SIZE',0))
  780.     {
  781.         size = (*sizeH)->prefSize;
  782.         ReleaseResource(sizeH);
  783.         return(size);
  784.     }
  785.     else return(DefaultSize());
  786. }
  787.  
  788. /************************************************************************
  789.  * DefaultSize - how big is Eudora's normal partition?
  790.  ************************************************************************/
  791. long DefaultSize(void)
  792. {
  793.     SizeHandle sizeH;
  794.     long size=0;
  795.     
  796.     if (sizeH = GetResource('SIZE',-1))
  797.     {
  798.         size = (*sizeH)->prefSize;
  799.         ReleaseResource(sizeH);
  800.     }
  801.     return(size);
  802. }
  803.  
  804. /************************************************************************
  805.  * EstimatePartitionSize - estimate the "right" size for Eudora
  806.  ************************************************************************/
  807. long EstimatePartitionSize(void)
  808. {
  809.     HFileInfo info;
  810.   Str63 scratch;
  811.     Str31 suffix;
  812.     uLong drain = 0;
  813.     static short strids[] = {IN,OUT,TRASH,ALIAS_FILE};
  814.     short id;
  815.     MyWindowPtr win;
  816.     
  817.     GetRString(suffix,TOC_SUFFIX);
  818.     
  819.     for (id=0;id<sizeof(strids)/sizeof(short);id++)
  820.     {
  821.         GetRString(scratch,strids[id]);
  822.         if (strids[id]!=ALIAS_FILE) PCat(scratch,suffix);
  823.         if (!HGetFileInfo(MyVRef,MyDirId,scratch,&info))
  824.             drain+=info.ioFlLgLen;
  825.     }
  826.     
  827.     for (win=FrontWindow();win;win=win->qWindow.nextWindow)
  828.     {
  829.         drain += sizeof(MyWindow);
  830.         switch (win->qWindow.windowKind)
  831.         {
  832.             case COMP_WIN:
  833.             case MESS_WIN:
  834.                 drain += (*BodyOf((MessHandle)win->qWindow.refCon))->teLength;
  835.                 break;
  836.             case TEXT_WIN:
  837.                 drain += (*(*(STEHandle)win->ste)->te)->teLength;
  838.                 break;
  839.             case MBOX_WIN:
  840.             case CBOX_WIN:
  841.                 if (!(*(TOCHandle)win->qWindow.refCon)->which)
  842.                     drain += GetHandleSize((TOCHandle)win->qWindow.refCon);
  843.                 break;
  844.             default:
  845.                 drain += 1K;
  846.         }
  847.     }
  848.      return(DefaultSize()+drain-24K);
  849. }
  850.  
  851. /**********************************************************************
  852.  * create some space for the grow zone function
  853.  **********************************************************************/
  854. void MakeGrow(long howMuch)
  855. {
  856.     if (SpareSpace = NuHandle(howMuch)) *(long *)*SpareSpace = 'SPAR';
  857. }
  858.  
  859. /**********************************************************************
  860.  * grow that zone...
  861.  **********************************************************************/
  862. pascal long GrowZone(unsigned long needed)
  863. {
  864.     long roomLeft;
  865.     long freed=0;
  866.     long theA5=SetCurrentA5();
  867.     Handle dontMove = GZSaveHnd();
  868.     PScrapStuff scrap;
  869.     
  870.     if (freed = UnloadUnneeded(needed))
  871.         ;
  872.     else if (scrap=InfoScrap(),scrap->scrapHandle&&dontMove!=scrap->scrapHandle&&GetHandleSize(scrap->scrapHandle))
  873.     {
  874.         freed = GetHandleSize(scrap->scrapHandle);
  875.         if (UnloadScrap()) ZeroScrap();                /* if we can't write it, kill it */
  876.         return(freed);
  877.     }
  878. #ifndef SLOW_CLOSE
  879.     else if (FastList)
  880.     {
  881.         TcpFastFlush(True);
  882.         return(1);
  883.     }
  884. #endif
  885.     else if (roomLeft = GetHandleSize(SpareSpace))
  886.     { 
  887.         freed = needed <= roomLeft ? needed : roomLeft;
  888.         SetHandleSize(SpareSpace,roomLeft - freed);
  889. #ifdef NEVER
  890.         if (RunType != Production) DebugStr("\pSPARE!");
  891. #endif
  892.     }
  893.     else if (Undo.text && Undo.text != dontMove)
  894.     {
  895.         freed = GetHandleSize(Undo.text);
  896.         ZapHandle(Undo.text);
  897.     }
  898.     else if (DamagedTOC && DamagedTOC != dontMove)
  899.     {
  900.         freed = GetHandleSize(DamagedTOC);
  901.         ZapHandle(DamagedTOC);
  902.     }
  903.     else
  904.     {
  905.         freed = CloseUnused();
  906.     }
  907.     (void) SetA5(theA5);
  908.     return(freed);
  909. }
  910.  
  911. /************************************************************************
  912.  * CloseUnused - close unused windows
  913.  ************************************************************************/
  914. long CloseUnused(void)
  915. {
  916.     static short kinds[] = {MB_WIN,PH_WIN,TEXT_WIN,ALIAS_WIN,MESS_WIN,COMP_WIN};
  917.     MyWindowPtr win,deadWin=nil;
  918.     short kind;
  919.     
  920.     for (kind=0;kind<sizeof(kinds)/sizeof(short);kind++)
  921.     {
  922.         for (win=FrontWindow();win;win=win->qWindow.nextWindow)
  923.         {
  924.             if (win->qWindow.windowKind==kinds[kind] && !win->isDirty && !win->inUse)
  925.                 if (kinds[kind]!=MESS_WIN || Win2Body(win)==WinTEH(win)) deadWin = win;
  926.         }
  927.         if (deadWin)
  928.         {
  929.             if (!CloseMyWindow(deadWin))
  930.             {
  931.                 UsingWindow(deadWin);        /* couldn't close it ??? */
  932.                 deadWin = nil;
  933.                 kind--;    /* try again with this kind */
  934.             }
  935.             else
  936.             {
  937.                 return(1);
  938.             }
  939.         }
  940.     }
  941.     return(0);
  942. }
  943.         
  944. /**********************************************************************
  945.  * FileSystemError - report an error regarding the file system
  946.  **********************************************************************/
  947. int FSE(int context, UPtr name, int err, int file,int line)
  948. {
  949.     Str255 text;
  950.     Str255 contextStr;
  951.     Str63 debugStr;
  952.     Str127 nameStr;
  953.     int offset = 0;
  954.     
  955.     PCopy(nameStr,name);
  956.     NumToString(err,text);
  957.     PCatC(text,' ');
  958.     if (err < wrPermErr) offset += wrPermErr-dirNFErr;
  959.     if (err < volGoneErr) offset += volGoneErr+127;
  960.     err += offset;
  961.     err = dirFulErr - err + 2;
  962.     if (err > 37) err = 37;
  963.     GetRString(contextStr,FILE_STRN+err);
  964.     PCat(text,contextStr);
  965.     GetRString(contextStr,context);
  966.     ComposeRString(debugStr,FILE_LINE_FMT,file,line);
  967.     MyParamText(contextStr,nameStr,text,debugStr);
  968.     (void) ReallyDoAnAlert(BIG_OK_ALRT,Stop);
  969.     return(err);
  970. }
  971.  
  972. /************************************************************************
  973.  * MiniMainLoop - handle only a limited set of events.    returns the event
  974.  * if someone else needs to handle it
  975.  ************************************************************************/
  976. Boolean MiniMainLoop(EventRecord *event)
  977. {
  978.     MyWindowPtr topWin=FrontWindow();
  979.     
  980. #ifdef DEBUG
  981.     if (BUG6) DebugStr("\p;hc;g");
  982.     if (BUG7)
  983.     {
  984.         long bytes;
  985.         MaxMem(&bytes);
  986.     }
  987. #endif
  988.     
  989.     TcpFastFlush(False);    /* give lingering connections a chance to die */
  990.  
  991.     switch (event->what)
  992.     {
  993.         case keyDown:
  994.             if (((event->message&charCodeMask)=='.') && (event->modifiers&cmdKey) ||
  995.                     ((event->message&charCodeMask)==escChar) &&
  996.                      (((event->message&keyCodeMask)>>8)==escKey))
  997.             {
  998.                 CommandPeriod = True;
  999.                 return(False);
  1000.             }
  1001.             break;
  1002.         case app4Evt:
  1003.             if (((event->message)>>24)&1 == 1)
  1004.                 DoApp4(topWin,event);
  1005.             return(False);
  1006.         case updateEvt:
  1007.             return(DoUpdate(topWin,event));
  1008.             break;
  1009.         case activateEvt:
  1010.             return(DoActivate(topWin,event));
  1011.             break;
  1012.         case mouseDown:
  1013.             if (IsSwitch(event) && Switch())
  1014.             {
  1015.                 event->what=nullEvent;
  1016.                 InBG = True;
  1017.                 return(False);
  1018.             }
  1019.             break;
  1020.     }
  1021.  
  1022.     if (CnH && topWin && topWin->qWindow.refCon==(long)CnH)
  1023.     {
  1024.         CMEvent(CnH,event);
  1025.         return(False);
  1026.     }
  1027.     
  1028.     return(True); 
  1029. }
  1030.  
  1031. /************************************************************************
  1032.  * CheckForMail - need I say more?
  1033.  ************************************************************************/
  1034. void CheckForMail(Boolean setTicks)
  1035. {
  1036.     short err=0;
  1037.     long interval=TICKS2MINS * GetRLong(PREF_STRN+PREF_INTERVAL);
  1038.     short gotSome=0;
  1039.     Boolean sendToo = SendQueue && PrefIsSet(PREF_SEND_CHECK);
  1040.     Str255 user;
  1041.     
  1042.     GetAlrtStage() = 0;
  1043.     SetSendQueue(); FlushTOCs(True,True);
  1044.     if (interval && (setTicks || !CheckTicks)) CheckTicks = TickCount();
  1045. #ifndef KERBEROS
  1046.     GetPref(user,PREF_POP);
  1047.     if (UUPCIn || *Password || !GetPassword(user,Password,sizeof(Password),ENTER))
  1048. #else
  1049.     if (UUPCIn || GetPassword())
  1050. #endif
  1051.     {
  1052.         AlertsTimeout = PrefIsSet(PREF_AUTO_DISMISS);
  1053.         OpenProgress();
  1054. #ifdef POPSECURE
  1055.         if (UseCTB && !UUPCIn) err=DialThePhone();
  1056. #else
  1057.         if (UseCTB && (!UUPCIn || (!UUPCOut&&sendToo))) err=DialThePhone();
  1058. #endif
  1059.         if (!err)
  1060.         {
  1061.             if (sendToo)
  1062.             {
  1063.                 err=SendTheQueue();
  1064.                 CommandPeriod = False;    /* clear condition, continue with POP */
  1065.                 if (!UUPCIn && !UUPCOut && UseCTB && !err) CTBNavigateSTRN(NAVMID);
  1066.             }
  1067.             if (!UseCTB || !err)
  1068.             {
  1069.                 Handle table;
  1070.                 if (!NewTables && !TransIn && (table=GetResource('taBL',TRANS_IN_TABL)))
  1071.                 {
  1072.                   HNoPurge(table);
  1073.                     if (TransIn=NuPtr(256)) BlockMove(*table,TransIn,256);
  1074.                     HPurge(table);
  1075.                 }
  1076.  
  1077.                 gotSome = UUPCIn ? GetUUPCMail(True) : GetMyMail(True);
  1078.             }
  1079.         }
  1080.         if (UseCTB) HangUpThePhone();
  1081.         CloseProgress();
  1082.         EnableProgress();
  1083.         if (gotSome>0) NotifyNewMail();
  1084.         AlertsTimeout = False;
  1085.         if (TransIn) {DisposPtr(TransIn); TransIn=nil;}
  1086.     }
  1087.     if (UseCTB) HangUpThePhone();    /* just making sure... */
  1088.     if (interval && CheckTicks+interval<TickCount()+45*60)
  1089.     {
  1090.         CheckTicks += interval*((TickCount()-CheckTicks+1)/interval);
  1091.         if (CheckTicks+interval<TickCount()+45*60) CheckTicks += interval;
  1092.     }
  1093. }
  1094.  
  1095. /************************************************************************
  1096.  * NotifyNewMail - notify the user that new mail has arrived, via the
  1097.  * notification manager.
  1098.  ************************************************************************/
  1099. void NotifyNewMail(void)
  1100. {
  1101.     TOCHandle tocH;
  1102.     if (PrefIsSet(PREF_NEW_SOUND)) NewMailSound();
  1103.     if (!PrefIsSet(PREF_NO_OPEN_IN) && (tocH=GetInTOC()))
  1104.     {
  1105.             short i=(*tocH)->count;
  1106.             while (i--) if ((*tocH)->sums[i].state!=UNREAD) break;
  1107.             i++;
  1108.             RedoTOC(tocH);
  1109.             ShowMyWindow((*tocH)->win);
  1110.             SelectBoxRange(tocH,i,i,False,-1,-1);
  1111.             ScrollIt((*tocH)->win,0,-INFINITY);
  1112.             SelectWindow((*tocH)->win);
  1113. #ifdef NEVER
  1114.         }
  1115.         else
  1116.         {
  1117.             UpdateMyWindow((*tocH)->win);
  1118.           ScrollIt((*tocH)->win,0,-INFINITY);
  1119.         }
  1120. #endif
  1121.     }
  1122.  
  1123.     if (InBG && PrefIsSet(PREF_NEW_ALERT) || !PrefIsSet(PREF_NO_APPLE_FLASH))
  1124.     {
  1125.         if (MyNMRec) return;                /* already done */
  1126.         MyNMRec = New(struct NMRec);
  1127.         if (!MyNMRec) return;             /* couldn't allocate memory (bad) */
  1128.         WriteZero(MyNMRec,sizeof(*MyNMRec));
  1129.         MyNMRec->qType = nmType;
  1130.         MyNMRec->nmMark = 1;
  1131.         MyNMRec->nmRefCon = TickCount();
  1132.         if (!PrefIsSet(PREF_NO_APPLE_FLASH))
  1133.             MyNMRec->nmIcon = GetResource('SICN',FLAG_SICN);
  1134.         if (InBG && PrefIsSet(PREF_NEW_ALERT))
  1135.         {
  1136.             Str255 scratch;
  1137.             GetRString(scratch,NEW_MAIL);
  1138.             MyNMRec->nmStr = NuPtr(*scratch+1);
  1139.             if (MyNMRec->nmStr) PCopy(MyNMRec->nmStr,scratch);
  1140.         }
  1141.         if (NMInstall(MyNMRec))
  1142.         {
  1143.             DisposPtr(MyNMRec->nmStr);
  1144.             DisposPtr(MyNMRec);
  1145.             MyNMRec = nil;
  1146.         }
  1147.     }
  1148.     if (!InBG && PrefIsSet(PREF_NEW_ALERT))
  1149.     {
  1150.         AlertTicks=GetRLong(ALERT_TIMEOUT)*60+TickCount();
  1151.         (void) ReallyDoAnAlert(NEW_MAIL_ALRT,Note);
  1152.         AlertTicks = 0;
  1153.     }
  1154. }
  1155.  
  1156. /************************************************************************
  1157.  * NewMailSound - play the sound for new mail
  1158.  ************************************************************************/
  1159. void NewMailSound(void)
  1160. {
  1161.     Handle sound=GetResource('snd ',NEW_MAIL_SND);
  1162.     if (sound)
  1163.     {
  1164.         HNoPurge(sound);
  1165.         (void) SndPlay(nil,sound,False);
  1166.         HPurge(sound);
  1167.     }
  1168.     else
  1169.         SysBeep(20);
  1170. }
  1171.  
  1172. /************************************************************************
  1173.  *
  1174.  ************************************************************************/
  1175. void FlushHIQ(void)
  1176. {
  1177.     HostInfoQHandle hiq, nextHIQ;
  1178.     for (hiq=HIQ;hiq;hiq=nextHIQ)
  1179.     {
  1180.         nextHIQ = (*hiq)->next;
  1181.         if ((*hiq)->hi.rtnCode!=inProgress && (*hiq)->hi.rtnCode!=cacheFault)
  1182.         {
  1183.             LL_Remove(HIQ,hiq,(HostInfoQHandle));
  1184.             DisposHandle(hiq);
  1185.         }
  1186.     }
  1187. #ifndef KERBEROS
  1188.     if (!HIQ) CloseResolver();
  1189. #endif
  1190. }
  1191.  
  1192. /************************************************************************
  1193.  * TendNotificationManager - see if an NM rec is active, and if it should
  1194.  * be taken down
  1195.  ************************************************************************/
  1196. void TendNotificationManager(Boolean isActive)
  1197. {
  1198.     if (MyNMRec)
  1199.     {
  1200.         long ticksSince = TickCount()-MyNMRec->nmRefCon;
  1201.         if (isActive && ticksSince>10 || AlertsTimeout &&
  1202.                 MyNMRec->nmRefCon && ticksSince>GetRLong(ALERT_TIMEOUT)*60)
  1203.         {
  1204.             NMRemove(MyNMRec);
  1205.             if (MyNMRec->nmStr) DisposPtr(MyNMRec->nmStr);
  1206.             DisposPtr(MyNMRec);
  1207.             MyNMRec = nil;
  1208.         }
  1209.     }
  1210. }
  1211.