home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / mac / util / comm / news102.sit / NewsWatcher / source / miscstuff.c < prev    next >
Text File  |  1991-04-03  |  13KB  |  587 lines

  1. /*----------------------------------------------------------
  2. #
  3. #    NewsWatcher    - Macintosh NNTP Client Application
  4. #
  5. #    Written by Steven Falkenburg
  6. #    ⌐1990 Apple Computer, Inc.
  7. #
  8. #-----------------------------------------------------------
  9. #
  10. #    miscstuff.c
  11. #
  12. #    This code module contains miscellaneous routines
  13. #    called by many of the other code segments.
  14. #    The memory management routines and status window
  15. #    routines are contained in this module.
  16. #
  17. #-----------------------------------------------------------*/
  18.  
  19. #include "compat.h"
  20. #include <stdlib.h>
  21. #include <CType.h>
  22. #include <string.h>
  23.  
  24. #ifdef PROTOS
  25. #include <Types.h>
  26. #include <Memory.h>
  27. #include <QuickDraw.h>
  28. #include <Controls.h>
  29. #include <Dialogs.h>
  30. #include <OSUtils.h>
  31. #include <CursorCtl.h>
  32. #include <Strings.h>
  33. #include <OSEvents.h>
  34. #include <Windows.h>
  35. #include <Lists.h>
  36. #include <Fonts.h>
  37. #include <Packages.h>
  38. #include <Errors.h>
  39. #include <ErrMgr.h>
  40. #include <Desk.h>
  41. #endif
  42.  
  43. #include "nntp.h"
  44. #include "miscstuff.h"
  45. #include "userint.h"
  46.  
  47. #define kButtonFrameSize    3    /* button frameUs pen size */
  48. #define kButtonFrameInset    4    /*inset rectangle adjustment around button */
  49.  
  50. static OSErr gMemError = noErr;
  51.  
  52.  
  53. #ifdef THINK_C
  54. void InitCursorCtl(long id)
  55. {
  56. }
  57.  
  58. void SpinCursor(short num)
  59. {
  60.     extern Cursor gWatchCurs;    
  61.     SetCursor(&gWatchCurs);
  62. }
  63. #endif
  64.  
  65.  
  66. /* OutlineOK: draws outline around ok button */
  67.  
  68. void OutlineOK(DialogPtr theDialog)
  69. {
  70.     short itemType;
  71.     ControlHandle theItem;
  72.     Rect itemRect;
  73.     GrafPtr savePort;
  74.     PenState thePen;
  75.     short buttonOval;
  76.     
  77.     GetDItem(theDialog,okButton,&itemType,(Handle *)&theItem,&itemRect);
  78.     GetPort(&savePort);
  79.     GetPenState(&thePen);
  80.     SetPort(theDialog);
  81.     PenNormal();
  82.     InsetRect(&itemRect,-kButtonFrameInset,-kButtonFrameInset);
  83.     buttonOval = (itemRect.bottom-itemRect.top)/2;
  84.     PenPat(QDBLACK);
  85.     PenSize(kButtonFrameSize,kButtonFrameSize);
  86.     FrameRoundRect(&itemRect,buttonOval,buttonOval);
  87.     SetPenState(&thePen);
  88.     SetPort(savePort);
  89. }
  90.  
  91.  
  92. /*    CmdKeyFilter is used as a universal dialog box filter.  It traps
  93.     command-key events and checks for items which have the same first
  94.     letter as the command key which was pressed.  If a match is found,
  95.     an event is generated for the appropriate item.
  96. */
  97.  
  98. pascal Boolean CmdKeyFilter(DialogPtr theDialog,EventRecord *theEvent,short *itemHit)
  99. {
  100.     char keyPressed;
  101.     short itemNumber;
  102.     short numItems;
  103.     short iType;
  104.     Handle iHndl;
  105.     Rect iRect;
  106.     Str255 btnTitle;
  107.     
  108.     /* totally convoluted and disgusting way to get the number of items in a dialog without
  109.        using assembly-language crap or blockmove -- probably could be cleaner */
  110.        
  111.     numItems = (short) 1 + ((((char *)(*(((DialogPeek)theDialog)->items)))[0] << 8) + ((char *)(*(((DialogPeek)theDialog)->items)))[1]);
  112.     keyPressed = theEvent->message & charCodeMask;
  113.     
  114.     if ((theEvent->what == keyDown)    || (theEvent->what == autoKey)) {
  115.         if ((keyPressed == CR) || (keyPressed == 03))    {
  116.             *itemHit = okButton;
  117.             return true;
  118.         }
  119.         if ((theEvent->modifiers & cmdKey) != 0) {
  120.             if (keyPressed == '.') {
  121.                 *itemHit = cancelButton;
  122.                 return true;
  123.             }
  124.             else {
  125.                 for (itemNumber = 1;itemNumber <= numItems;itemNumber++) {
  126.                     GetDItem(theDialog,itemNumber,&iType,&iHndl,&iRect);
  127.                     if (iType == (ctrlItem+btnCtrl) || iType == (ctrlItem+chkCtrl) || iType == (ctrlItem+radCtrl)) {
  128.                         GetCTitle((ControlHandle)iHndl,btnTitle);
  129.                         if (toupper(btnTitle[1]) == toupper(keyPressed)) {
  130.                             *itemHit = itemNumber;
  131.                             return true;
  132.                         }
  133.                     }
  134.                 }
  135.             }
  136.         }
  137.     }
  138.     return false;
  139. }
  140.  
  141.  
  142. /*    BlessedFolder returns the vRefNum of the currently active system folder.
  143. */
  144.  
  145. short BlessedFolder(void)
  146. {
  147.     SysEnvRec    sysEnv;
  148.     
  149.     if (SysEnvirons(1,&sysEnv) != noErr)
  150.         return 0;
  151.     return (sysEnv.sysVRefNum);
  152. }
  153.  
  154.  
  155. /*    GiveTime is called whenever the application is waiting for a slow
  156.     process to complete.  The routine calls SpinCursor and WaitNextEvent
  157.     to give time to currently running background applications.
  158.     
  159.     This procedure can be thought of as a secondary main event loop.
  160. */
  161.  
  162. Boolean GiveTime(unsigned long sleepTime)
  163. {
  164.     EventRecord ev;
  165.     static unsigned short count = 0;
  166.     extern Boolean gInBackground;
  167.     extern Boolean gCancel;
  168.     extern Boolean gHasWaitNextEvent;
  169.     
  170.     Boolean gotEvt;
  171.  
  172.     if (gInBackground)
  173.         sleepTime *= 5;
  174.     else if ((count%6) == 0)
  175.         SpinCursor(12);
  176.             
  177.     if ( (count%10) == 0 ) {
  178.                 
  179.         if (gHasWaitNextEvent)
  180.             gotEvt = WaitNextEvent(everyEvent,&ev,sleepTime,nil);
  181.         else {
  182.             gotEvt = GetNextEvent(everyEvent,&ev);
  183.             SystemTask();
  184.         }
  185.         
  186.         if ( gotEvt )
  187.             switch (ev.what) {
  188.                 case mouseDown:
  189.                     if (IsMovableModal(FrontWindow()))
  190.                         HandleMouseDowns(&ev);
  191.                     break;
  192.                 case activateEvt:
  193.                     HandleActivates(&ev);
  194.                     break;
  195.                 case updateEvt:
  196.                     HandleUpdates((WindowPtr)(ev.message));
  197.                     break;
  198.                 case app4Evt:
  199.                     HandleSREvt(ev.message);
  200.                     break;
  201.                 case keyDown:
  202.                 case autoKey:
  203.                     FlushEvents(keyDownMask+keyUpMask+autoKeyMask,0);
  204.                     if ((ev.modifiers & cmdKey) != 0 && (ev.message & charCodeMask) == '.') {
  205.                         gCancel = true;
  206.                     }
  207.                     break;
  208.             }
  209.     }
  210.     
  211.     count++;
  212.     
  213.     return !gCancel;
  214. }
  215.  
  216.  
  217. /*    StatusWindow displays a movable-modal status window indicating
  218.     the current state of the program.  An optional percent-complete
  219.     status bar may also be displayed.
  220. */
  221.  
  222. Boolean StatusWindow(char *text,short percent)
  223. {
  224.     WindowPtr statusWind;
  225.     Rect bounds = {0,0,60,230};
  226.     extern short gMoveModalProc;
  227.     TwindowInfo *info;
  228.     Rect tmpRect;
  229.     GrafPtr savePort;
  230.     extern TPrefRec gPrefs;
  231.     extern Rect desktopExtent;
  232.     
  233.     if (PtInRect(gPrefs.statusWindowLocn,&desktopExtent))
  234.         OffsetRect(&bounds,gPrefs.statusWindowLocn.h,gPrefs.statusWindowLocn.v);
  235.     
  236.     if (!IsMovableModal(statusWind = FrontWindow())) {
  237.         info = (TwindowInfo *) MyNewPtr(sizeof(TwindowInfo));
  238.         if (MyMemErr() != noErr)
  239.             return false;
  240.         info->data2 = (unsigned long) MyNewPtr(256);
  241.         if (MyMemErr() != noErr)
  242.             return false;
  243.         *((char *)info->data2) = 0;
  244.         info->kind = cMoveModal;
  245.         info->numGroups = -2;
  246.         statusWind = NewWindow(nil,&bounds,"\pStatus",true,gMoveModalProc,(WindowPtr)-1,
  247.                                 false,(unsigned long)info);
  248.     }
  249.     else info = (TwindowInfo *) GetWRefCon(statusWind);
  250.     
  251.     GetPort(&savePort);
  252.     SetPort(statusWind);
  253.     
  254.     if (strcmp(text,(char *)info->data2) != 0) {
  255.         strcpy((char *)info->data2,text);
  256.         SetRect(&tmpRect,0,0,230,44);
  257.         InvalRect(&tmpRect);
  258.     }
  259.     if (info->numGroups != percent) {
  260.         info->numGroups = percent;
  261.         SetRect(&tmpRect,0,45,230,60);
  262.         InvalRect(&tmpRect);
  263.     }
  264.  
  265.     if (info->numGroups <= 0)
  266.         UpdateStatus();
  267.  
  268.         
  269.     SetPort(savePort);
  270.     
  271.     return true;
  272. }
  273.  
  274.  
  275. /*    UpdateStatus is called in response to update events for the status
  276.     window.  This routine will redraw sections of the window as necessary.
  277. */
  278.  
  279. void UpdateStatus(void)
  280. {
  281.     GrafPtr savePort;
  282.     WindowPtr statusWind;
  283.     TwindowInfo *info;
  284.     short percent;
  285.     Rect percentRect,tmpRect;
  286.     short newRight;
  287.     
  288.     if (!FrontWindow()) {
  289.         SysBeep(1);
  290.         return;
  291.     }
  292.     
  293.     info = (TwindowInfo *) GetWRefCon(statusWind = FrontWindow());
  294.     percent = info->numGroups;
  295.     
  296.     if (!IsMovableModal(statusWind))
  297.         return;
  298.     
  299.     GetPort(&savePort);
  300.     SetPort(statusWind);
  301.     
  302.     tmpRect = statusWind->portRect;
  303.     if (percent > 0)
  304.         tmpRect.bottom = 35;
  305.     EraseRect(&tmpRect);
  306.     
  307.     TextFont(systemFont);
  308.     TextSize(12);
  309.     MoveTo(20,30);
  310.     DrawText((char *)info->data2,0,strlen((char *)info->data2));
  311.     if (percent >= 0) {
  312.         SetRect(&percentRect,20,45,210,55);
  313.         FrameRect(&percentRect);
  314.         InsetRect(&percentRect,1,1);
  315.         newRight = percentRect.left + (short) (((float)(percentRect.right-percentRect.left))*((float)percent/100.0));
  316.         if (newRight < percentRect.right)
  317.             percentRect.right = newRight;
  318.         FillRect(&percentRect,QDDKGRAY);
  319.     }
  320.     SetPort(savePort);
  321. }
  322.  
  323.  
  324. /*    CloseStatusWindow is called when the status window should be removed.
  325. */
  326.  
  327. void CloseStatusWindow(void)
  328. {
  329.     WindowPtr statusWind;
  330.     GrafPtr savePort;
  331.     extern TPrefRec gPrefs;
  332.     TwindowInfo *info;
  333.     
  334.     if (IsMovableModal(statusWind = FrontWindow())) {
  335.         SetPt(&gPrefs.statusWindowLocn,0,0);
  336.         GetPort(&savePort);
  337.         SetPort(statusWind);
  338.         LocalToGlobal(&gPrefs.statusWindowLocn);
  339.         
  340.         info = (TwindowInfo *)GetWRefCon(statusWind);
  341.         
  342.         SetPort(savePort);
  343.         MyDisposPtr( (Ptr) (info->data2) );
  344.         MyDisposPtr( (Ptr) info );
  345.         DisposeWindow(statusWind);
  346.     }
  347. }
  348.  
  349.  
  350. /*    MyIOCheck can be called to display the result of a routine returning
  351.     an OSErr.  If the value in err is zero, the routine simply terminates.
  352. */
  353.  
  354. OSErr MyIOCheck(OSErr err)
  355. {
  356.     Str255 errNoStr;
  357.     
  358.     if (err != noErr) {
  359.         NumToString(err,errNoStr);
  360.         ParamText("\pAn error has occurred",errNoStr,"\p","\p");
  361.         StopAlert(kErrDlg,nil);
  362.     }
  363.     return err;
  364. }
  365.  
  366.  
  367. /*    LowMemory is called when the program runs out of useable memory.
  368.     If this is the first time this has happened, the program de-allocates
  369.     lifeboat memory which was allocated when the program was launched.
  370.     Otherwise, the user had better quit.
  371. */
  372.  
  373. Boolean LowMemory(void)
  374. {
  375.     extern Handle gLifeBoat;
  376.     extern Boolean gSinking;
  377.     extern Boolean gOutOfMemory;
  378.     Boolean result;
  379.     
  380.     if (MyMemErr() != memFullErr) {
  381.         MyIOCheck(MyMemErr());
  382.         return false;
  383.     }
  384.         
  385.     if (gSinking) {
  386.         result = false;
  387.         gOutOfMemory = true;
  388.         ParamText("\pYou have run out of memory","\p","\p","\p");
  389.     }
  390.     else {
  391.         HUnlock(gLifeBoat);
  392.         DisposHandle(gLifeBoat);
  393.         gSinking = true;
  394.         result = true;
  395.         ParamText("\pMemory is getting low.  Some operations may fail.","\p","\p","\p");
  396.     }
  397.     StopAlert(kErrDlg,nil);
  398.     return result;
  399. }
  400.  
  401.  
  402. /*    This is a wrapper for the NewPtr routine which automatically checks
  403.     the result of the call and takes appropriate action.
  404. */
  405.  
  406. Ptr MyNewPtr(Size byteCount)
  407. {
  408.     Ptr thePtr;
  409.     
  410.     thePtr = NewPtr(byteCount);
  411.     if ((gMemError = MemError()) != noErr) {
  412.         if (LowMemory())
  413.             thePtr = MyNewPtr(byteCount);
  414.         else
  415.             thePtr = nil;
  416.     }
  417.     return thePtr;
  418. }
  419.  
  420.  
  421. /*    This is a wrapper for the NewHandle routine which automatically checks
  422.     the result of the call and takes appropriate action.
  423. */
  424.  
  425. Handle MyNewHandle(Size byteCount)
  426. {
  427.     Handle theHndl;
  428.     
  429.     theHndl = NewHandle(byteCount);
  430.     if ((gMemError = MemError()) != noErr) {
  431.         if (LowMemory())
  432.             theHndl = MyNewHandle(byteCount);
  433.         else
  434.             theHndl = nil;
  435.     }
  436.     return theHndl;
  437. }
  438.  
  439. /*    This is a wrapper for the SetHandleSize routine which automatically checks
  440.     the result of the call and takes appropriate action.
  441. */
  442.  
  443. void MySetHandleSize(Handle h,Size newSize)
  444. {
  445.     SetHandleSize(h,newSize);
  446.     if ((gMemError = MemError()) != noErr) {
  447.         if (LowMemory())
  448.             MySetHandleSize(h,newSize);
  449.     }
  450. }
  451.  
  452.  
  453. /*    This is a wrapper for the SetPtrSize routine which automatically checks
  454.     the result of the call and takes appropriate action.
  455.     
  456.     Note: don't call SetPtrSize to increase allocation for a pointer!
  457. */
  458.  
  459. void MySetPtrSize(Ptr p,Size newSize)
  460. {
  461.     SetPtrSize(p,newSize);
  462.     if ((gMemError = MemError()) != noErr) {
  463.         if (LowMemory())
  464.             MySetPtrSize(p,newSize);
  465.     }
  466. }
  467.  
  468.  
  469. /*    This is a wrapper for the HandToHand routine which automatically checks
  470.     the result of the call and takes appropriate action.
  471. */
  472.  
  473. OSErr MyHandToHand(Handle *theHndl)
  474. {
  475.     Handle oldHndl;
  476.     OSErr result;
  477.     
  478.     oldHndl = *theHndl;
  479.     result = gMemError = HandToHand(theHndl);
  480.     if (result != noErr) {
  481.         *theHndl = oldHndl;
  482.         if (LowMemory())
  483.             MyHandToHand(theHndl);
  484.     }
  485.     return result;
  486. }
  487.  
  488.  
  489. /*    This is a wrapper for the DisposPtr routine which automatically checks
  490.     the result of the call and takes appropriate action.
  491. */
  492.  
  493. OSErr MyDisposPtr(Ptr thePtr)
  494. {
  495.     DisposPtr(thePtr);
  496.     gMemError = MemError();
  497.     return MyIOCheck(MemError());
  498. }
  499.  
  500.  
  501. /*    This is a wrapper for the DisposHandle routine which automatically checks
  502.     the result of the call and takes appropriate action.
  503. */
  504.  
  505. OSErr MyDisposHandle(Handle theHndl)
  506. {
  507.     DisposHandle(theHndl);
  508.     gMemError = MemError();
  509.     return MyIOCheck(MemError());
  510. }
  511.  
  512.  
  513. /*    This is a wrapper for the MemError routine which automatically checks
  514.     the result of the call and takes appropriate action.
  515. */
  516.  
  517. OSErr MyMemErr(void)
  518. {
  519.     return gMemError;
  520. }
  521.  
  522.  
  523. /*    ReadPrefs reads the preferences file off of the disk file.
  524.     The preferences are stored in a global block of memory.
  525. */
  526.  
  527. OSErr ReadPrefs(TPrefPtr thePrefs)
  528. {
  529.     OSErr err;
  530.     short fRefNum;
  531.     long count;
  532.     
  533.     if ((err = FSOpen(kPrefName,BlessedFolder(),&fRefNum))==noErr) {
  534.         count=sizeof(TPrefRec);
  535.         err = FSRead(fRefNum,&count,(Ptr)thePrefs);
  536.         FSClose(fRefNum);
  537.     }
  538.     else {
  539.         thePrefs->newsServerName[0] = '\0';
  540.         thePrefs->mailServerName[0] = '\0';
  541.         thePrefs->name[0] = '\0';
  542.         thePrefs->host[0] = '\0';
  543.         thePrefs->fullName[0] = '\0';
  544.         thePrefs->organization[0] = '\0';
  545.         thePrefs->signature[0] = '\0';
  546.         thePrefs->address[0] = '\0';
  547.         
  548.         BlockMove("\pGeneva",thePrefs->listFont,7L);
  549.         BlockMove("\pMonaco",thePrefs->textFont,7L);
  550.         thePrefs->listSize = kListFontSize;
  551.         thePrefs->textSize = kTextFontSize;
  552.         SetRect(&thePrefs->groupWindowSize,4,40,300,340);
  553.         SetPt(&thePrefs->windowOffset,10,30);
  554.         SetPt(&thePrefs->statusWindowLocn,100,100);
  555.         thePrefs->groupWindowVisible = true;
  556.         thePrefs->openWindowsZoomed = false;
  557.         thePrefs->parentWindows = true;
  558.         thePrefs->mostRecentFirst = false;
  559.         thePrefs->maxFetch = 400;
  560.     }
  561.     return noErr;
  562. }
  563.  
  564.  
  565. /*    WritePrefs writes the NewsWatcher preferences back to the News Prefs
  566.     file.  This is called when the program terminates.
  567. */
  568.  
  569. OSErr WritePrefs(TPrefPtr thePrefs)
  570. {
  571.     OSErr err;
  572.     short fRefNum;
  573.     long count;
  574.     
  575.     if ((err = FSOpen(kPrefName,BlessedFolder(),&fRefNum))==fnfErr) {
  576.         Create(kPrefName,BlessedFolder(),kFCreator,kPrefType);
  577.         err = FSOpen(kPrefName,BlessedFolder(),&fRefNum);
  578.     }
  579.     if (err != noErr)
  580.         return err;
  581.     
  582.     count=sizeof(TPrefRec);
  583.     err = FSWrite(fRefNum,&count,(Ptr)thePrefs);
  584.     FSClose(fRefNum);
  585.     return err;
  586. }
  587.