home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************************
-
- mac_undo.c: Copyright (c) Kevin Hammond 1993. All rights reserved.
-
- Utility Functions.
-
- *****************************************************************************/
-
-
- #include "mac.h"
-
- #pragma segment Utils
-
- extern pascal Boolean AutoScroll();
-
- extern jmp_buf catch_error;
- extern CursHandle watchcurs, gccurs; /* Watch and GC cursors */
- extern CCrsrHandle gccursc; /* Colour version of GC cursor */
- extern Boolean CCAvailable; /* Are colour cursors available */
- extern Boolean inForeground; /* Are we in the background? */
-
- /*
- See if a trap is available.
- Non-available traps all have the same unique address.
- */
-
- #define Unimplemented 0xA89F /* Unimplemented trap */
-
-
- Boolean TrapAvailable (trap,type)
- short trap, type;
- {
- return(NGetTrapAddress(trap, type) != GetTrapAddress(Unimplemented));
- }
-
- /*
- NB: A Macintosh TN says TextEdit may fail if the size of the
- viewrect (?destrect?) is greater than 32767 pixels in area.
- BEWARE: I do not check this!
- */
-
- /* Defined to make TE handling a little cleaner -- HSL */
- #define TE_RECT_INSET 4
- #define TE_RECT_WIDTH 1024
-
- void CalculateTERects(Rect *theViewR, Rect *theDestR, short theLineHeight,int fittovr)
- /* Calculates the view and destination rectangles for a TE */
- /* Assumes that the current port is set to the TE's port */
- {
- Rect pr = qd.thePort->portRect;
- short roundedViewHeight;
- short te_rect_width = qd.screenBits.bounds.right > TE_RECT_WIDTH?
- qd.screenBits.bounds.right: TE_RECT_WIDTH;
-
- // if((pr.right - (SCROLLBARWIDTH - 1))*(pr.bottom - (SCROLLBARWIDTH - 1)) > 32767)
- // AbortError("Internal","View Rectangle too large for TextEdit to handle");
-
- SetRect(theViewR, 0, 0, pr.right - (SCROLLBARWIDTH - 1), pr.bottom - (SCROLLBARWIDTH - 1));
- InsetRect(theViewR, TE_RECT_INSET, TE_RECT_INSET);
- roundedViewHeight = ((theViewR->bottom - theViewR->top) / theLineHeight) * theLineHeight;
- theViewR->bottom = theViewR->top + roundedViewHeight;
-
- if(fittovr)
- {
- *theDestR = *theViewR;
- theDestR->right -= 16;
- }
- else
- {
- SetRect(theDestR, 0, 0, TE_RECT_WIDTH+TE_RECT_INSET, 16384);
- InsetRect(theDestR, TE_RECT_INSET, TE_RECT_INSET);
- }
- }
-
-
- /*
- Create a new TE record.
- */
-
- NewTERec(windex,fittoviewrect)
- int windex;
- int fittoviewrect;
- {
- TEHandle teh;
- Rect vr, dr;
- FontInfo textFontInfo;
-
- TEHANDLE(windex) = NIL;
-
- GetFontInfo(&textFontInfo);
- CalculateTERects(&vr, &dr, textFontInfo.ascent + textFontInfo.descent + textFontInfo.leading, fittoviewrect);
-
- teh = TENew(&dr, &vr);
-
- if(teh == NIL)
- AbortError("Memory ","Out of Memory -- Closing windows may help");
-
- SetClikLoop((ClikLoopProcPtr)AutoScroll,teh); /* Install auto-scroll function */
-
- /* Deactivate the existing TE area */
- if (thefrontwindow != ILLEGAL_WINDOW && TEHANDLE(thefrontwindow) != NIL)
- TEDeactivate(TEHANDLE(thefrontwindow));
-
- /* (*teh)->crOnly = -1; /* Don't wrap lines. */
-
- TEHANDLE(windex) = teh;
- }
-
-
- /*
- Update windows for which there is an outstanding update event.
- This is used to clear up after dialogs when we intend to perform a
- non-trivial action before returning to the main event loop.
- */
-
- void updatewindows()
- {
- extern EventRecord myEvent;
-
- while(EventAvail(updateMask|activMask,&myEvent))
- {
- GetNextEvent(updateMask|activMask,&myEvent);
- if(myEvent.what == activateEvt)
- DoActivate();
- else
- DoUpdate();
- }
- }
-
-
-
- /*
- Lock a window's TE Handle, using a semaphore.
- We use these routines rather than simply HLock,
- to avoid unlocking a handle during recursive calls.
- */
-
-
- TEHLock(w)
- int w;
- {
- if( TELOCK(w)++ == 0)
- if(TEHANDLE(w) != NIL)
- HLock((Handle) TEHANDLE(w));
- }
-
-
- /*
- Unlock a window's TE Handle, using a semaphore.
- */
-
-
- TEHUnlock(w)
- int w;
- {
- if( TELOCK(w) > 0)
- if(--TELOCK(w)==0)
- if(TEHANDLE(w) != NIL)
- HUnlock((Handle) TEHANDLE(w));
- }
-
- /*
- A safe version of malloc(), which aborts back to the main event loop.
- */
-
- char *safemalloc(n)
- unsigned n;
- {
- extern char *malloc();
- char *temp = malloc(n);
-
- if(temp == NIL)
- {
- Error("Memory ","Out of Memory -- Closing windows may help");
- longjmp(catch_error,26);
- }
- return(temp);
- }
-
-
- char *safecalloc(n,s)
- unsigned n,s;
- {
- extern char *calloc();
- char *temp = calloc(n,s);
-
- if(temp == NIL)
- {
- mprintf("Failed to allocate %u bytes of memory\n",n*s);
- // Error("Memory ","Out of Memory -- Closing windows may help");
- longjmp(catch_error,27);
- }
- return(temp);
- }
-
-
- SetGCCursor(set)
- Boolean set;
- {
- if(inForeground)
- {
- if(set)
- if(CCAvailable)
- SetCCursor(gccursc);
- else
- SetCursor(*gccurs);
- else
- SpinCursor(0);
- }
- }
-
- /*
- Handle the multitasking event loop.
- In utils.c rather than machine.c so that variables
- etc. are in scope.
- */
-
- multitaskeventloop()
- {
- do {
- eventloop(everyEvent);
- } while (myEvent.what != nullEvent);
-
- if(thefrontwindow == worksheet)
- SpinCursor(4);
- }
-
-
- #define LOW_MEM_LIMIT 50000
-
- CheckMemory(kind,amount)
- char *kind;
- unsigned amount;
- {
- static Boolean memerr = FALSE, lowmemerr = FALSE;
- unsigned long maxblock = MaxBlock();
-
- /*
- Allow enough room to complete the largest operation.
- */
- if(maxblock < amount)
- {
- if(!lowmemerr)
- {
- char s[256];
- sprintf(s,"Aborting '%s' Operation -- Only %ld Bytes Left",kind,maxblock);
- Error("",s);
- }
- else
- SysBeep(1);
- memerr = lowmemerr = TRUE;
- longjmp(catch_error,33);
- }
-
- else if(maxblock < LOW_MEM_LIMIT)
- {
- if(!memerr)
- {
- char s[256];
- sprintf(s,"Memory Low in %s operation (%ld Bytes Left) -- Try Closing Windows?",kind,maxblock);
- Error("Warning ",s);
- }
- memerr = TRUE;
- lowmemerr = FALSE;
- }
-
- else
- lowmemerr = memerr = FALSE;
- }
-
-
- ResetCursor()
- {
- if(inForeground)
- {
- getnextevent(nullEvent);
- drawcursor(myEvent,FALSE);
- }
- }
-