home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Otherware
/
Otherware_1_SB_Development.iso
/
mac
/
util
/
comm
/
news102.sit
/
NewsWatcher
/
source
/
miscstuff.c
< prev
next >
Wrap
Text File
|
1991-04-03
|
13KB
|
587 lines
/*----------------------------------------------------------
#
# NewsWatcher - Macintosh NNTP Client Application
#
# Written by Steven Falkenburg
# ⌐1990 Apple Computer, Inc.
#
#-----------------------------------------------------------
#
# miscstuff.c
#
# This code module contains miscellaneous routines
# called by many of the other code segments.
# The memory management routines and status window
# routines are contained in this module.
#
#-----------------------------------------------------------*/
#include "compat.h"
#include <stdlib.h>
#include <CType.h>
#include <string.h>
#ifdef PROTOS
#include <Types.h>
#include <Memory.h>
#include <QuickDraw.h>
#include <Controls.h>
#include <Dialogs.h>
#include <OSUtils.h>
#include <CursorCtl.h>
#include <Strings.h>
#include <OSEvents.h>
#include <Windows.h>
#include <Lists.h>
#include <Fonts.h>
#include <Packages.h>
#include <Errors.h>
#include <ErrMgr.h>
#include <Desk.h>
#endif
#include "nntp.h"
#include "miscstuff.h"
#include "userint.h"
#define kButtonFrameSize 3 /* button frameUs pen size */
#define kButtonFrameInset 4 /*inset rectangle adjustment around button */
static OSErr gMemError = noErr;
#ifdef THINK_C
void InitCursorCtl(long id)
{
}
void SpinCursor(short num)
{
extern Cursor gWatchCurs;
SetCursor(&gWatchCurs);
}
#endif
/* OutlineOK: draws outline around ok button */
void OutlineOK(DialogPtr theDialog)
{
short itemType;
ControlHandle theItem;
Rect itemRect;
GrafPtr savePort;
PenState thePen;
short buttonOval;
GetDItem(theDialog,okButton,&itemType,(Handle *)&theItem,&itemRect);
GetPort(&savePort);
GetPenState(&thePen);
SetPort(theDialog);
PenNormal();
InsetRect(&itemRect,-kButtonFrameInset,-kButtonFrameInset);
buttonOval = (itemRect.bottom-itemRect.top)/2;
PenPat(QDBLACK);
PenSize(kButtonFrameSize,kButtonFrameSize);
FrameRoundRect(&itemRect,buttonOval,buttonOval);
SetPenState(&thePen);
SetPort(savePort);
}
/* CmdKeyFilter is used as a universal dialog box filter. It traps
command-key events and checks for items which have the same first
letter as the command key which was pressed. If a match is found,
an event is generated for the appropriate item.
*/
pascal Boolean CmdKeyFilter(DialogPtr theDialog,EventRecord *theEvent,short *itemHit)
{
char keyPressed;
short itemNumber;
short numItems;
short iType;
Handle iHndl;
Rect iRect;
Str255 btnTitle;
/* totally convoluted and disgusting way to get the number of items in a dialog without
using assembly-language crap or blockmove -- probably could be cleaner */
numItems = (short) 1 + ((((char *)(*(((DialogPeek)theDialog)->items)))[0] << 8) + ((char *)(*(((DialogPeek)theDialog)->items)))[1]);
keyPressed = theEvent->message & charCodeMask;
if ((theEvent->what == keyDown) || (theEvent->what == autoKey)) {
if ((keyPressed == CR) || (keyPressed == 03)) {
*itemHit = okButton;
return true;
}
if ((theEvent->modifiers & cmdKey) != 0) {
if (keyPressed == '.') {
*itemHit = cancelButton;
return true;
}
else {
for (itemNumber = 1;itemNumber <= numItems;itemNumber++) {
GetDItem(theDialog,itemNumber,&iType,&iHndl,&iRect);
if (iType == (ctrlItem+btnCtrl) || iType == (ctrlItem+chkCtrl) || iType == (ctrlItem+radCtrl)) {
GetCTitle((ControlHandle)iHndl,btnTitle);
if (toupper(btnTitle[1]) == toupper(keyPressed)) {
*itemHit = itemNumber;
return true;
}
}
}
}
}
}
return false;
}
/* BlessedFolder returns the vRefNum of the currently active system folder.
*/
short BlessedFolder(void)
{
SysEnvRec sysEnv;
if (SysEnvirons(1,&sysEnv) != noErr)
return 0;
return (sysEnv.sysVRefNum);
}
/* GiveTime is called whenever the application is waiting for a slow
process to complete. The routine calls SpinCursor and WaitNextEvent
to give time to currently running background applications.
This procedure can be thought of as a secondary main event loop.
*/
Boolean GiveTime(unsigned long sleepTime)
{
EventRecord ev;
static unsigned short count = 0;
extern Boolean gInBackground;
extern Boolean gCancel;
extern Boolean gHasWaitNextEvent;
Boolean gotEvt;
if (gInBackground)
sleepTime *= 5;
else if ((count%6) == 0)
SpinCursor(12);
if ( (count%10) == 0 ) {
if (gHasWaitNextEvent)
gotEvt = WaitNextEvent(everyEvent,&ev,sleepTime,nil);
else {
gotEvt = GetNextEvent(everyEvent,&ev);
SystemTask();
}
if ( gotEvt )
switch (ev.what) {
case mouseDown:
if (IsMovableModal(FrontWindow()))
HandleMouseDowns(&ev);
break;
case activateEvt:
HandleActivates(&ev);
break;
case updateEvt:
HandleUpdates((WindowPtr)(ev.message));
break;
case app4Evt:
HandleSREvt(ev.message);
break;
case keyDown:
case autoKey:
FlushEvents(keyDownMask+keyUpMask+autoKeyMask,0);
if ((ev.modifiers & cmdKey) != 0 && (ev.message & charCodeMask) == '.') {
gCancel = true;
}
break;
}
}
count++;
return !gCancel;
}
/* StatusWindow displays a movable-modal status window indicating
the current state of the program. An optional percent-complete
status bar may also be displayed.
*/
Boolean StatusWindow(char *text,short percent)
{
WindowPtr statusWind;
Rect bounds = {0,0,60,230};
extern short gMoveModalProc;
TwindowInfo *info;
Rect tmpRect;
GrafPtr savePort;
extern TPrefRec gPrefs;
extern Rect desktopExtent;
if (PtInRect(gPrefs.statusWindowLocn,&desktopExtent))
OffsetRect(&bounds,gPrefs.statusWindowLocn.h,gPrefs.statusWindowLocn.v);
if (!IsMovableModal(statusWind = FrontWindow())) {
info = (TwindowInfo *) MyNewPtr(sizeof(TwindowInfo));
if (MyMemErr() != noErr)
return false;
info->data2 = (unsigned long) MyNewPtr(256);
if (MyMemErr() != noErr)
return false;
*((char *)info->data2) = 0;
info->kind = cMoveModal;
info->numGroups = -2;
statusWind = NewWindow(nil,&bounds,"\pStatus",true,gMoveModalProc,(WindowPtr)-1,
false,(unsigned long)info);
}
else info = (TwindowInfo *) GetWRefCon(statusWind);
GetPort(&savePort);
SetPort(statusWind);
if (strcmp(text,(char *)info->data2) != 0) {
strcpy((char *)info->data2,text);
SetRect(&tmpRect,0,0,230,44);
InvalRect(&tmpRect);
}
if (info->numGroups != percent) {
info->numGroups = percent;
SetRect(&tmpRect,0,45,230,60);
InvalRect(&tmpRect);
}
if (info->numGroups <= 0)
UpdateStatus();
SetPort(savePort);
return true;
}
/* UpdateStatus is called in response to update events for the status
window. This routine will redraw sections of the window as necessary.
*/
void UpdateStatus(void)
{
GrafPtr savePort;
WindowPtr statusWind;
TwindowInfo *info;
short percent;
Rect percentRect,tmpRect;
short newRight;
if (!FrontWindow()) {
SysBeep(1);
return;
}
info = (TwindowInfo *) GetWRefCon(statusWind = FrontWindow());
percent = info->numGroups;
if (!IsMovableModal(statusWind))
return;
GetPort(&savePort);
SetPort(statusWind);
tmpRect = statusWind->portRect;
if (percent > 0)
tmpRect.bottom = 35;
EraseRect(&tmpRect);
TextFont(systemFont);
TextSize(12);
MoveTo(20,30);
DrawText((char *)info->data2,0,strlen((char *)info->data2));
if (percent >= 0) {
SetRect(&percentRect,20,45,210,55);
FrameRect(&percentRect);
InsetRect(&percentRect,1,1);
newRight = percentRect.left + (short) (((float)(percentRect.right-percentRect.left))*((float)percent/100.0));
if (newRight < percentRect.right)
percentRect.right = newRight;
FillRect(&percentRect,QDDKGRAY);
}
SetPort(savePort);
}
/* CloseStatusWindow is called when the status window should be removed.
*/
void CloseStatusWindow(void)
{
WindowPtr statusWind;
GrafPtr savePort;
extern TPrefRec gPrefs;
TwindowInfo *info;
if (IsMovableModal(statusWind = FrontWindow())) {
SetPt(&gPrefs.statusWindowLocn,0,0);
GetPort(&savePort);
SetPort(statusWind);
LocalToGlobal(&gPrefs.statusWindowLocn);
info = (TwindowInfo *)GetWRefCon(statusWind);
SetPort(savePort);
MyDisposPtr( (Ptr) (info->data2) );
MyDisposPtr( (Ptr) info );
DisposeWindow(statusWind);
}
}
/* MyIOCheck can be called to display the result of a routine returning
an OSErr. If the value in err is zero, the routine simply terminates.
*/
OSErr MyIOCheck(OSErr err)
{
Str255 errNoStr;
if (err != noErr) {
NumToString(err,errNoStr);
ParamText("\pAn error has occurred",errNoStr,"\p","\p");
StopAlert(kErrDlg,nil);
}
return err;
}
/* LowMemory is called when the program runs out of useable memory.
If this is the first time this has happened, the program de-allocates
lifeboat memory which was allocated when the program was launched.
Otherwise, the user had better quit.
*/
Boolean LowMemory(void)
{
extern Handle gLifeBoat;
extern Boolean gSinking;
extern Boolean gOutOfMemory;
Boolean result;
if (MyMemErr() != memFullErr) {
MyIOCheck(MyMemErr());
return false;
}
if (gSinking) {
result = false;
gOutOfMemory = true;
ParamText("\pYou have run out of memory","\p","\p","\p");
}
else {
HUnlock(gLifeBoat);
DisposHandle(gLifeBoat);
gSinking = true;
result = true;
ParamText("\pMemory is getting low. Some operations may fail.","\p","\p","\p");
}
StopAlert(kErrDlg,nil);
return result;
}
/* This is a wrapper for the NewPtr routine which automatically checks
the result of the call and takes appropriate action.
*/
Ptr MyNewPtr(Size byteCount)
{
Ptr thePtr;
thePtr = NewPtr(byteCount);
if ((gMemError = MemError()) != noErr) {
if (LowMemory())
thePtr = MyNewPtr(byteCount);
else
thePtr = nil;
}
return thePtr;
}
/* This is a wrapper for the NewHandle routine which automatically checks
the result of the call and takes appropriate action.
*/
Handle MyNewHandle(Size byteCount)
{
Handle theHndl;
theHndl = NewHandle(byteCount);
if ((gMemError = MemError()) != noErr) {
if (LowMemory())
theHndl = MyNewHandle(byteCount);
else
theHndl = nil;
}
return theHndl;
}
/* This is a wrapper for the SetHandleSize routine which automatically checks
the result of the call and takes appropriate action.
*/
void MySetHandleSize(Handle h,Size newSize)
{
SetHandleSize(h,newSize);
if ((gMemError = MemError()) != noErr) {
if (LowMemory())
MySetHandleSize(h,newSize);
}
}
/* This is a wrapper for the SetPtrSize routine which automatically checks
the result of the call and takes appropriate action.
Note: don't call SetPtrSize to increase allocation for a pointer!
*/
void MySetPtrSize(Ptr p,Size newSize)
{
SetPtrSize(p,newSize);
if ((gMemError = MemError()) != noErr) {
if (LowMemory())
MySetPtrSize(p,newSize);
}
}
/* This is a wrapper for the HandToHand routine which automatically checks
the result of the call and takes appropriate action.
*/
OSErr MyHandToHand(Handle *theHndl)
{
Handle oldHndl;
OSErr result;
oldHndl = *theHndl;
result = gMemError = HandToHand(theHndl);
if (result != noErr) {
*theHndl = oldHndl;
if (LowMemory())
MyHandToHand(theHndl);
}
return result;
}
/* This is a wrapper for the DisposPtr routine which automatically checks
the result of the call and takes appropriate action.
*/
OSErr MyDisposPtr(Ptr thePtr)
{
DisposPtr(thePtr);
gMemError = MemError();
return MyIOCheck(MemError());
}
/* This is a wrapper for the DisposHandle routine which automatically checks
the result of the call and takes appropriate action.
*/
OSErr MyDisposHandle(Handle theHndl)
{
DisposHandle(theHndl);
gMemError = MemError();
return MyIOCheck(MemError());
}
/* This is a wrapper for the MemError routine which automatically checks
the result of the call and takes appropriate action.
*/
OSErr MyMemErr(void)
{
return gMemError;
}
/* ReadPrefs reads the preferences file off of the disk file.
The preferences are stored in a global block of memory.
*/
OSErr ReadPrefs(TPrefPtr thePrefs)
{
OSErr err;
short fRefNum;
long count;
if ((err = FSOpen(kPrefName,BlessedFolder(),&fRefNum))==noErr) {
count=sizeof(TPrefRec);
err = FSRead(fRefNum,&count,(Ptr)thePrefs);
FSClose(fRefNum);
}
else {
thePrefs->newsServerName[0] = '\0';
thePrefs->mailServerName[0] = '\0';
thePrefs->name[0] = '\0';
thePrefs->host[0] = '\0';
thePrefs->fullName[0] = '\0';
thePrefs->organization[0] = '\0';
thePrefs->signature[0] = '\0';
thePrefs->address[0] = '\0';
BlockMove("\pGeneva",thePrefs->listFont,7L);
BlockMove("\pMonaco",thePrefs->textFont,7L);
thePrefs->listSize = kListFontSize;
thePrefs->textSize = kTextFontSize;
SetRect(&thePrefs->groupWindowSize,4,40,300,340);
SetPt(&thePrefs->windowOffset,10,30);
SetPt(&thePrefs->statusWindowLocn,100,100);
thePrefs->groupWindowVisible = true;
thePrefs->openWindowsZoomed = false;
thePrefs->parentWindows = true;
thePrefs->mostRecentFirst = false;
thePrefs->maxFetch = 400;
}
return noErr;
}
/* WritePrefs writes the NewsWatcher preferences back to the News Prefs
file. This is called when the program terminates.
*/
OSErr WritePrefs(TPrefPtr thePrefs)
{
OSErr err;
short fRefNum;
long count;
if ((err = FSOpen(kPrefName,BlessedFolder(),&fRefNum))==fnfErr) {
Create(kPrefName,BlessedFolder(),kFCreator,kPrefType);
err = FSOpen(kPrefName,BlessedFolder(),&fRefNum);
}
if (err != noErr)
return err;
count=sizeof(TPrefRec);
err = FSWrite(fRefNum,&count,(Ptr)thePrefs);
FSClose(fRefNum);
return err;
}