Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
BigEasy/BigEasy2.c
/* |
File: BigEasy2.c |
Copyright: © 1990-1992, 1994 by Apple Computer, Inc., all rights reserved. |
This file is used in these builds: Warhol |
Change History (most recent first): |
<41+> 22-9-94 dvb universal headers |
<41> 22-9-94 dvb |
<40+> 17-8-94 dvb allocate gx job when pagesetup, no sooner, coz its slow. |
<40> 17-8-94 dvb GX Printing |
<39> 9-8-94 dvb |
<38> 27-7-94 dvb installquititem |
<37+> 5/27/94 dvb InstallQuitItem |
<37> 5/27/94 dvb . |
<35> 1/7/93 dvb Compile under mpw. |
<34> 1/6/93 dvb Built in window-copy command. |
<33> 4/23/92 dvb Test checkout from new project |
<32> 4/13/92 dvb Pass activate/deactivates to back windows. |
<31> 3/22/92 dvb QuitApp message. |
<30> 1/20/92 dvb Cool new features. Much easier appleevents. |
<29> 12/19/91 JB removing think 4.0 code |
<28> 10/14/91 JB added #ifdef to create old window ports for debugging |
<27> 9/18/91 PH support silly disk inserted events |
<26> 8/12/91 MD support for timing profiler nastiness |
<25> 7/3/91 PH qd. is bad under old think |
<24> 6/28/91 dvb Make it work with/without MacHeaders in LSC5. |
<23> 6/4/91 PH compilin' |
<22> 6/3/91 dvb Just hackin. |
<21> 5/28/91 JB Added prototypes for BigEasy Proc Ptrs |
<20> 5/27/91 PH to compile again... |
<19> 5/25/91 JB OLD_THINK_C && TOOLBOX_LINKED |
<18> 5/23/91 PH changes for THINK 5 |
<17> 5/22/91 PH new style prototypes |
<16> 5/6/91 PH nifty line after about... |
<15> 5/5/91 dvb Latest features, and App-Events for document open. |
<14> 4/25/91 JB Changing to new THINK C interface files |
<13> 4/19/91 PH i like content clicks |
<12> 4/19/91 dvb Add WindowEventProc |
<11> 3/29/91 PH minor activate fix |
<10> 3/29/91 dvb Repair deactivate vs closewindow conflict, roll in latest cool |
features. |
<9> 3/9/91 dvb Adjust to work with or without (LSC) mac headers |
<8> 3/7/91 JB Adjusting for using MacHeaders |
<7> 3/1/91 dvb Trivial new functions |
<6> 2/24/91 dvb Various cool new calls |
<5> 2/18/91 dvb Miscellaneous Updates |
<4> 1/9/91 JB Increasing ItemsPerMenu & #Menus |
<3> 11/21/90 JB Changes for INIT & mpw compatability |
<2> 11/17/90 dvb Pass on unused command-keys to document windows |
<1> 11/17/90 dvb New again after 1st CD pressing! Yay! |
To Do: |
*/ |
/* file: BigEasy2.c |
* |
* Started 30 June 1988, more or less. |
* |
* A set of routines to allow the quick development |
* of simple Macintosh applications. |
* :) |
*/ |
#define BigEasy2 |
#include <QuickDraw.h> |
#include <Gestalt.h> |
#include <Events.h> |
#include <AppleEvents.h> |
#include <Resources.h> |
#include <Menus.h> |
#include <ToolUtils.h> |
#include <Menus.h> |
#include <Windows.h> |
#include <Dialogs.h> |
#include <Memory.h> |
#include <devices.h> |
#include <Fonts.h> |
#include <Scrap.h> |
#include <SegLoad.h> |
//#undef BigEasyGXPrinting |
#ifdef BigEasyGXPrinting |
#include <PrintingManager.h> |
#include <Graphics Toolbox.h> |
#include <Graphics Routines.h> |
#endif |
/* #define THINK_C_PROFILE /* */ |
#if defined(TIMING_PROFILE) || defined(STACK_KILLER) |
#include "stack killer.h" |
#endif |
#include "BigEasy2.h" |
#ifdef BigEasyGXPrinting |
#define WantsGX 1 |
#else |
#define WantsGX 0 |
#endif |
/*---------------- |
Limits |
----------------*/ |
#define kMMax 10 /* Number of menus in menubar */ |
#define kMIMax 50 /* Number of items per menu */ |
#define kMenuNameMax 32 /* Length of a menu title */ |
#define kStagLimX 97 |
#define kStagLimY 37 |
/*---------------- |
Constants |
----------------*/ |
#define kOSEvent app4Evt /* event used by MultiFinder */ |
#define kSuspendResumeMessage 1 /* high byte of suspend/resume event message */ |
#define kResumeMask 1 /* bit of message field for resume vs. suspend */ |
#define kWinPosType 'bewP' |
#define trapExitToShell 0xA9F4 |
/*---------------- |
Major BigEasy2 Structures |
----------------*/ |
typedef struct TEasyWindow |
{ |
Boolean wUsed; |
long iNum; |
long flags; |
Boolean wGrowable; |
beUpdateProcPtr wUpdateProc; |
beClickProcPtr wClickProc; |
beKeyProcPtr wKeyProc; |
beGoAwayProcPtr wGoAwayProc; |
beWNumCallProcPtr wZoomProc; |
beActivateProcPtr wActivateProc; |
beDeactivateProcPtr wDeactivateProc; |
beIdleProcPtr wIdleProc; |
beResizeProcPtr wResizeProc; |
beGrowWindowProcPtr wGrowWindowProc; |
beMoveWindowProcPtr wMoveWindowProc; |
beEventProcPtr wEventProc; |
WindowPtr wWindow; |
#ifdef BigEasyGXPrinting |
gxJob job; |
#endif |
} TEasyWindow; |
typedef struct |
{ |
short ref; |
char mark; |
char enable; |
char cmdEquiv; |
beMenuProcPtr proc; |
} TEasyMenuItem; |
/*---------------- |
Globals |
----------------*/ |
static short gIdleSeed; |
static Rect gResizeLim = {50,50,1000,1000}; |
static TEasyWindow **gEasyWindowListH; /* Handle to array of window objects */ |
static TEasyWindow *gEasyWindowList; /* Pointer to array of window objects */ |
static short gEasyWindowListSize; /* Number of window objects allocated */ |
/*** Menus ***/ |
static MenuHandle gMenuHandleList[kMMax]; /* MenuHandles indexed by MenuID's */ |
static short gMenuLength[kMMax]; |
static char gMenuName[kMMax][kMenuNameMax]; |
static TEasyMenuItem gMenu[kMMax][kMIMax]; |
static short gMenuCount; /* How many menus defined */ |
static short gCurrentMenu; /* the one to add to */ |
static MenuHandle gMenuEdit; /* Which one is the edit menu? */ |
/*** Phantom Menu ***/ |
static MenuHandle phantomMenuH = 0; |
/*** About ***/ |
static beAboutProcPtr gAboutProc; |
static char gAboutS0[256]; |
/*** Application Edit Commands ***/ |
static beWNumCallProcPtr gAppUndoProc,gAppCutProc,gAppCopyProc,gAppPasteProc,gAppClearProc; |
static beMenuProcPtr gAppPageSetupProc=0,gAppPrintProc=0; |
/*** Global Status ***/ |
static beOpenAppProcPtr gMasterOpenAppProc; |
static beOpenDocProcPtr gMasterOpenDocProc; |
static beQuitAppProcPtr gMasterQuitAppProc; |
static beAboutProcPtr gMasterIdleProc; |
static short gStagX,gStagY; |
static WindowPtr gLastFrontIdle; |
static short gLastFrontWindowNumber; |
static short gSleep; |
static short gCoolDragState; |
static Point gCoolDragPoint; |
static short gCoolDragWindowNumber; |
static TEasyWindow *gCoolDragEW; |
static Boolean gInvalidMenuBar; |
static void *gOldExitToShell; |
PicHandle GetWindowPICT(TEasyWindow *thisEasyWindow); |
/*---------------- |
Prototypes |
----------------*/ |
static void InitToolbox(void); |
static void CheckMenubar(void); |
static void EventLoop(void); |
static void InitBigEasy(void); |
static void ExitBigEasy(void); |
static void InstallMyExitToShell(void); |
static pascal void MyExitToShell(void); |
static void GetGrowRect(WindowPtr,Rect*); |
static void EnoughEasyWindows(short); |
static void FrontDAEdits(void); |
static TEasyWindow *GoodWNum(short); |
static Boolean CoolBigEasyCmdKeys(short key); |
static void DoMyAbout(void); |
static void BEUndo(short); |
static void BECopy(short); |
static void BECut(short); |
static void BEPaste(short); |
static void BEClear(short); |
static void BENull(void); |
void BEPageSetup(short n, short menuItem, short menuRef); |
void BEPrint(short n, short menuItem, short menuRef); |
static void MenuClick(Point p); |
static void DeleteIndexedMenuItem(short menu,short item); |
static Boolean DoKeyPress(long k); |
static void MenuPoint(long theclick); |
static void StartMenus(void); |
static short ScanWindowList(WindowPtr w); |
static void DoMouseClick(EventRecord *event); |
static void MyDrawGrowIcon(WindowPtr w); |
static pascal OSErr BigEasyOpenAppThang(AppleEvent *theEvent, AppleEvent *reply,long refCon); |
static pascal OSErr BigEasyOpenDocThang(AppleEvent *theEvent, AppleEvent *reply,long refCon); |
static pascal OSErr BigEasyQuitAppThang(AppleEvent *theEvent, AppleEvent *reply,long refCon); |
static OSErr MissedAEParameters (AppleEvent *message); |
Boolean ActivateWindow(WindowPtr w, Boolean activate); |
#ifdef BigEasyGXPrinting |
void MakeSureWeHaveJob(TEasyWindow *thisWindow); |
#endif |
void main(void); |
/*---------------- |
Some useful routines |
----------------*/ |
void InitToolbox(void) |
{ |
InitGraf(&qd.thePort); |
InitFonts(); |
FlushEvents(0xffff,0); |
InitWindows(); |
InitMenus(); |
InitDialogs(0); |
TEInit(); |
InitCursor(); |
} |
void GetGrowRect(WindowPtr w,Rect *r) |
{ |
register Rect *gr; |
gr = r; |
*gr = w->portRect; |
gr->left = gr->right - 15; |
gr->top = gr->bottom - 15; |
} |
void GoWatch(void) |
{ |
SetCursor(*(Cursor**)GetCursor(4)); |
} |
void GoArrow(void) |
{ |
SetCursor(&qd.arrow); |
} |
void GoCursor(short c) |
/* |
* Attempt to set to cursor ID c, |
* but skip it if not there. |
*/ |
{ |
register Cursor **cur; |
cur = (Cursor **)GetCursor(c); |
if(cur) |
SetCursor(*cur); |
} |
static void EnoughEasyWindows(short n) |
/* |
* If there are less than n window objects in the list, |
* grow the handle appropriately. |
*/ |
{ |
short i; |
n++; |
if(gEasyWindowListSize < n) |
{ |
HUnlock((Handle)gEasyWindowListH); |
SetHandleSize((Handle)gEasyWindowListH,sizeof(TEasyWindow) * (long)n); |
HLock((Handle)gEasyWindowListH); |
gEasyWindowList = *gEasyWindowListH; |
for(i = gEasyWindowListSize; i < n; i++) |
gEasyWindowList[i].wUsed = 0; |
gEasyWindowListSize = n; |
} |
} |
static TEasyWindow *GoodWNum(short n) |
/* |
* return true if n is the number of an |
* existing, used window. |
*/ |
{ |
register TEasyWindow *thisWindow; |
if(n<0 || n>=gEasyWindowListSize) |
return 0; |
thisWindow = &gEasyWindowList[n]; |
if(thisWindow->wUsed) |
return thisWindow; |
else |
return 0; |
} |
static void FrontDAEdits(void) |
/* |
* Check the front window. If it's a DA, |
* enable all edit menu options. |
*/ |
{ |
WindowRecord *w; |
w = (WindowRecord*)FrontWindow(); |
if(w->windowKind < 0) /* Any click in a DA window: */ |
EnDisEdits(1,1,1,1,1); /* enable edit menu. */ |
} |
void DoMyAbout(void) |
{ |
DialogPtr d; |
Handle h; |
short hit; |
if(gAboutProc) |
(*gAboutProc)(); |
else |
{ |
h = GetResource('DLOG',1962); /* does it exist? */ |
if( (ResError()==0) && (h!=nil) ) |
{ |
ParamText((StringPtr)gAboutS0,0,0,0); |
d = GetNewDialog(1962,0,(WindowPtr)-1); |
ModalDialog(nil,&hit); |
DisposDialog(d); |
} |
} |
} |
void SetMasterIdle(r) |
beAboutProcPtr r; |
{ |
gMasterIdleProc = r; |
} |
void SetWindowResizeProc(short n,beResizeProcPtr resizeProc) |
/* |
* Sets the procedure which gets called when the window is resized |
*/ |
{ |
TEasyWindow *thisWindow; |
thisWindow = GoodWNum(n); |
if(thisWindow) |
thisWindow->wResizeProc = resizeProc; |
} |
void SetWindowGrowWindowProc(short n,beGrowWindowProcPtr growWindowProc) |
/* |
* Sets the procedure which gets called when the window grows. |
* Allows alternate to GrowWindow. |
*/ |
{ |
TEasyWindow *thisWindow; |
thisWindow = GoodWNum(n); |
if(thisWindow) |
thisWindow->wGrowWindowProc = growWindowProc; |
} |
void SetWindowMoveProc(short n,beMoveWindowProcPtr moveWindowProc) |
{ |
TEasyWindow *thisWindow; |
thisWindow = GoodWNum(n); |
if(thisWindow) |
thisWindow->wMoveWindowProc = moveWindowProc; |
} |
void SetWindowZoomProc(short n,beWNumCallProcPtr zoomProc) |
{ |
register TEasyWindow *thisWindow; |
thisWindow = GoodWNum(n); |
if(thisWindow) |
thisWindow->wZoomProc = zoomProc; |
} |
void SetWindowEventProc(short n,beEventProcPtr eventProc) |
{ |
register TEasyWindow *thisWindow; |
thisWindow = GoodWNum(n); |
if(thisWindow) |
thisWindow->wEventProc = eventProc; |
} |
long GetWindowFlags(short n) |
{ |
TEasyWindow *thisWindow; |
if(!(thisWindow = GoodWNum(n))) |
return 0; |
return thisWindow->flags; |
} |
void SetWindowFlags(short n,long flags) |
{ |
TEasyWindow *thisWindow; |
if(!(thisWindow = GoodWNum(n))) |
return; |
thisWindow->flags = flags; |
} |
void SetAbout(StringPtr progName,StringPtr s0,beAboutProcPtr aboutProc) |
/* |
* Sets the program's name in the about box, and |
* sets the second string as ParamText 0 (^0) |
* for the about dialog, 1962. |
*/ |
{ |
short i; |
SetItem(gMenuHandleList[1],1,(StringPtr)progName); |
for(i=0; i<256; i++) |
gAboutS0[i] = *s0++; |
gAboutProc = aboutProc; |
} |
/*---------------- |
Error Handling |
----------------*/ |
void InstallMyExitToShell(void) |
/* |
* Add my HatStrap call to |
* the classic routine, "ExitToShell" |
*/ |
{ |
gOldExitToShell = (void *) NGetTrapAddress(trapExitToShell, ToolTrap); |
NSetTrapAddress((UniversalProcPtr) MyExitToShell, trapExitToShell, ToolTrap); |
} |
pascal void MyExitToShell(void) |
/* |
* My exit routine, which does |
* all the good cleanup. |
*/ |
{ |
Hatstrap(); |
NSetTrapAddress((UniversalProcPtr) gOldExitToShell, trapExitToShell, ToolTrap); |
ExitToShell(); |
} |
void FailNil(long x) |
/* |
* If x is zero, post an error |
* alert and quit the program. |
*/ |
{ |
if(!x) |
{ |
Alert(200,nil); |
Debugger(); |
ExitToShell(); |
} |
} |
void FailOSErr(long x) |
/* |
* If x isn't zero, post an error |
* alert and quit the program. |
*/ |
{ |
if(x) |
{ |
Debugger(); |
Alert(200,nil); |
ExitToShell(); |
} |
} |
/*---------------- |
Some inherent methods |
----------------*/ |
void BEUndo(short n) |
{ |
if(!SystemEdit(0) && gAppUndoProc) |
(*gAppUndoProc)(n); |
} |
void BECut(short n) |
{ |
if(!SystemEdit(2) && gAppCutProc) |
(*gAppCutProc)(n); |
} |
PicHandle GetWindowPICT(TEasyWindow *tew) |
{ |
Rect visBounds; |
beUpdateProcPtr fp; |
PicHandle picH; |
SetPort(tew->wWindow); /* Set port to window */ |
visBounds = qd.thePort->portRect; |
InsetRect(&visBounds,-1,-1); |
ForeColor(blackColor); |
BackColor(whiteColor); |
PenSize(1,1); |
picH = OpenPicture(&visBounds); |
ClipRect(&visBounds); |
FrameRect(&visBounds); |
fp = tew->wUpdateProc; |
if(fp) |
(*fp)(tew->iNum); /* Call drawing proc */ |
SetOrigin(0,0); |
ClosePicture(); |
ClipRect(&gBigRect); |
return picH; |
} |
void BECopy(short n) |
{ |
TEasyWindow *thisEasyWindow; |
if(!SystemEdit(3)) |
{ |
thisEasyWindow = GoodWNum(n); |
if(thisEasyWindow->flags & wCopyDraw) |
/* |
* |
*/ |
{ |
PicHandle picH; |
picH = GetWindowPICT(thisEasyWindow); |
HLock((Handle)picH); |
ZeroScrap(); |
PutScrap(GetHandleSize((Handle)picH),'PICT',(Ptr)*picH); |
KillPicture(picH); |
} |
else if(gAppCopyProc) |
(*gAppCopyProc)(n); |
} |
} |
void BEPaste(short n) |
{ |
if(!SystemEdit(4) && gAppPasteProc) |
(*gAppPasteProc)(n); |
} |
void BEClear(short n) |
{ |
if(!SystemEdit(5) && gAppClearProc) |
(*gAppClearProc)(n); |
} |
void BENull(void){} |
void BEPageSetup(short n, short menuItem, short menuRef) |
{ |
OSErr err; |
long oldMenus; |
#ifdef BigEasyGXPrinting |
TEasyWindow *tew; |
gxDialogResult result; |
gxEditMenuRecord editMenuRec; |
tew = GoodWNum(n); |
if(tew->flags & wPrintDraw) |
{ |
oldMenus = DisableAllMenus(); |
editMenuRec.editMenuID = 0; |
editMenuRec.cutItem = 0; |
editMenuRec.copyItem = 0; |
editMenuRec.pasteItem = 0; |
editMenuRec.clearItem = 0; |
editMenuRec.undoItem = 0; |
MakeSureWeHaveJob(tew); |
result = GXJobDefaultFormatDialog(tew->job,&editMenuRec); |
err = GXGetJobError(tew->job); |
EnableAllMenus(oldMenus); |
} |
else |
#endif |
{ |
if(gAppPageSetupProc) |
(*gAppPageSetupProc)(n,menuItem,menuRef); |
} |
} |
void BEPrint(short n, short menuItem, short menuRef) |
{ |
OSErr err; |
PicHandle picH; |
Rect pictR,centeredR,pageR; |
Point p; |
Str255 s; |
long oldMenus; |
#ifdef BigEasyGXPrinting |
TEasyWindow *tew; |
gxFormat format; |
gxTranslationStatistic stats; |
gxRectangle pageSize,paperSize; |
gxDialogResult result; |
gxEditMenuRecord editMenuRec; |
gxShape sh; |
tew = GoodWNum(n); |
if(tew->flags & wPrintDraw) |
{ |
oldMenus = DisableAllMenus(); |
editMenuRec.editMenuID = 0; |
editMenuRec.cutItem = 0; |
editMenuRec.copyItem = 0; |
editMenuRec.pasteItem = 0; |
editMenuRec.clearItem = 0; |
editMenuRec.undoItem = 0; |
MakeSureWeHaveJob(tew); |
result = GXJobPrintDialog(tew->job,&editMenuRec); |
err = GXGetJobError(tew->job); |
picH = GetWindowPICT(tew); |
pictR = (**picH).picFrame; |
p.h = p.v = 0; |
/* |
* Center the image in the page rectangle |
*/ |
format = GXGetJobFormat(tew->job,1); |
GXGetFormatDimensions(format,&pageSize,&paperSize); |
pageR.top = pageSize.top >> 16; |
pageR.bottom = pageSize.bottom >> 16; |
pageR.left = pageSize.left >> 16; |
pageR.right = pageSize.right >> 16; |
centeredR = pictR; |
OffsetRect(¢eredR, |
(pageR.left + pageR.right - pictR.left - pictR.right + 1) >> 1, |
(pageR.top + pageR.bottom - pictR.top - pictR.bottom + 1) >> 1); |
sh = GXConvertPICTToShape(picH, gxDefaultOptionsTranslation, &pictR, ¢eredR, p, nil, &stats); |
GetWTitle(tew->wWindow,s); |
GXStartJob(tew->job,s,0); |
err = GXGetJobError(tew->job); |
GXPrintPage(tew->job,1,nil,sh); |
err = GXGetJobError(tew->job); |
GXFinishJob(tew->job); |
err = GXGetJobError(tew->job); |
GXDisposeShape(sh); |
EnableAllMenus(oldMenus); |
} |
#endif |
{ |
if(gAppPageSetupProc) |
(*gAppPageSetupProc)(n,menuItem,menuRef); |
} |
} |
/*---------------- |
Menu Action Routines |
----------------*/ |
Boolean DoKeyPress(long k) |
{ |
register long thePoint; |
register Boolean didIt; |
thePoint = MenuKey((char)k); |
didIt = (thePoint>>16) != 0; |
if(didIt) |
MenuPoint(thePoint); |
return didIt; |
} |
void MenuClick(Point p) |
{ |
KeyMap theKeys; |
Boolean putBack = false; |
short oldID; |
if (phantomMenuH) { |
GetKeys(theKeys); |
if ((theKeys[1]&4) == 0) { |
putBack = true; |
oldID = (**phantomMenuH).menuID; |
DeleteMenu( oldID ); |
} |
} |
MenuPoint(MenuSelect(p)); |
if (putBack) |
{ |
InsertMenu(phantomMenuH,oldID); |
} |
} |
void MenuPoint(long theclick) |
{ |
register short mID,mItem; |
char DAname[30]; |
short wNum; |
TEasyWindow *thisWindow; |
register beMenuProcPtr aProc; |
register TEasyMenuItem *emi; |
mID = theclick>>16; |
mItem = theclick & 0xffff; |
if(mID == 0) return; |
if(mID == 1) /* Apple menu */ |
{ |
if(mItem == 1) /* Its either the about box */ |
DoMyAbout(); |
else |
{ /* Or a DA */ |
GetItem(gMenuHandleList[1],mItem,(StringPtr)DAname); |
OpenDeskAcc((StringPtr)DAname); |
} |
} |
else |
{ |
wNum = gLastFrontWindowNumber; |
thisWindow = GoodWNum(wNum); |
if(thisWindow) /* if one of our window in front, setport */ |
SetPort(thisWindow->wWindow); |
emi = &gMenu[mID][0]; |
aProc = emi->proc; |
if(aProc) /* call the menu's routine, if any */ |
(*aProc)(wNum,mItem,gMenu[mID][mItem].ref); |
emi = &gMenu[mID][mItem]; |
aProc = emi->proc; |
if(aProc) /* call the item's routine, if any */ |
(*aProc)(wNum,mItem,emi->ref); |
} |
HiliteMenu(0); |
} |
char dAbout[] = "\pAbout "; |
void StartMenus(void) |
/* |
* Start with just an About box, and some DA's. |
*/ |
{ |
char aboutS[255]; |
MenuHandle applemenu; |
BlockMove(&dAbout[0],aboutS,dAbout[0]+1); /* "About" */ |
BlockMove((StringPtr )0x910 + 1,aboutS + aboutS[0] + 1, *(StringPtr )0x910); /* ProgName */ |
aboutS[0] += *((StringPtr )0x910); |
aboutS[aboutS[0] + 1] = 'É'; |
aboutS[0]++; |
applemenu = NewMenu(1,(StringPtr)"\p"); /* Apple menu: ID 1 */ |
AppendMenu(applemenu,(StringPtr)aboutS); |
AppendMenu(applemenu,(StringPtr)"\p(-"); |
AddResMenu(applemenu,'DRVR'); |
InsertMenu(applemenu,0); |
DrawMenuBar(); |
gMenuHandleList[1] = applemenu; |
gMenu[1][0].enable = true; |
gMenuCount = 1; /* Next menu added will be ID 2 */ |
gCurrentMenu = 1; |
gMenuLength[1] = 0; /* No items, really, in Apple menu */ |
} |
MenuHandle InstallMenu(StringPtr s,beMenuProcPtr action,short ref) |
/* |
* Start a new menu with name s |
*/ |
{ |
register TEasyMenuItem *emi; |
register MenuHandle mh; |
gMenuCount++; /* new menu */ |
gCurrentMenu = gMenuCount; |
if(*s > kMenuNameMax-1) |
*s = kMenuNameMax-1; |
gMenuLength[gCurrentMenu] = 0; |
mh = NewMenu(gCurrentMenu,(StringPtr)s); |
gMenuHandleList[gCurrentMenu] = mh; |
InsertMenu(mh,0); |
emi = &gMenu[gCurrentMenu][0]; |
emi->enable = ref >= 0; |
if(!emi->enable) |
{ |
DisableItem(mh,0); |
ref =- ref; |
} |
emi->proc = action; |
emi->ref = ref; |
gInvalidMenuBar = true; /* redraw soon */ |
BlockMove(s,gMenuName[gCurrentMenu],*s+1); |
return mh; |
} |
static Str255 dQuitString = "\pQuit "; |
#define kQuitLength 5 |
static Str15 dQuitCmdKey = "\p/Q"; |
void InstallQuitItem(beMenuProcPtr action,short ref) |
{ |
short i,j; |
StringPtr w; |
i = kQuitLength; |
w = (StringPtr)0x910; |
j = *w++; |
while(j--) |
dQuitString[++i] = *w++; |
w = dQuitCmdKey; |
j = *w++; |
while(j--) |
dQuitString[++i] = *w++; |
dQuitString[0] = i; |
InstallMenuItem(dQuitString,action,ref); |
} |
void InstallMenuItem(StringPtr s,beMenuProcPtr action,short ref) |
/* |
* Add an item to the last menu, and associate a routine with it. |
*/ |
{ |
register MenuHandle mh; |
register TEasyMenuItem *emi; |
register short item; |
mh = gMenuHandleList[gCurrentMenu]; |
gMenuLength[gCurrentMenu]++; |
item = gMenuLength[gCurrentMenu]; |
emi = &gMenu[gCurrentMenu][item]; |
if (ref < 0) |
{ |
DisableItem(mh,item); |
ref =- ref; |
emi->enable = 0; |
} |
else |
emi->enable = 1; |
AppendMenu(mh,(StringPtr)s); |
emi->proc = action; |
emi->ref = ref; |
emi->mark = 0; |
if(*(s+*s-1) == '/') |
emi->cmdEquiv = *(s+*s); |
else |
emi->cmdEquiv = 0; |
} |
void RemoveMenuItem(short ref) |
/* |
* Remove all menu items with |
* refcon ref. |
*/ |
{ |
short menu; |
short item; |
for(menu = 1; menu <= gMenuCount; menu++) |
for(item = gMenuLength[menu]; item > 0; item--) |
{ |
if(gMenu[menu][item].ref == ref) |
DeleteIndexedMenuItem(menu,item); |
} |
} |
void DeleteIndexedMenuItem(short menu,short item) |
{ |
StringPtr oldStrings; |
MenuHandle mh; |
short i; |
short itemCount; |
register TEasyMenuItem *emi; |
register StringPtr w; |
itemCount = gMenuLength[menu]; |
mh = gMenuHandleList[menu]; |
oldStrings = (StringPtr)NewPtrClear(256 * (itemCount)); |
FailNil((long)oldStrings); |
for(i = 1; i<=itemCount; i++) |
GetItem(mh,i,(StringPtr)&oldStrings[(i-1)*256]); |
DeleteMenu(menu); |
DisposeMenu(mh); |
mh = NewMenu(menu,(StringPtr)gMenuName[menu]); |
emi = &gMenu[menu][1]; |
w = oldStrings; |
for(i = 1; i<=itemCount; i++) |
{ |
if(i != item) |
{ |
if(emi->cmdEquiv) |
{ |
*(w+*w+1) = '/'; |
*(w+*w+2) = emi->cmdEquiv; |
*w = *w + 2; |
} |
AppendMenu(mh,(StringPtr)w); |
} |
emi++; |
w += 256; |
} |
emi = &gMenu[menu][item]; |
for(i = item; i<itemCount; i++) |
{ |
*emi = *(emi+1); |
emi++; |
} |
gMenuLength[menu]--; |
itemCount--; |
emi = &gMenu[menu][1]; |
for(i = 1; i<=itemCount; i++) |
{ |
if(!emi->enable) |
DisableItem(mh,i); |
if(emi->mark) |
SetItemMark(mh,i,emi->mark); |
emi++; |
} |
InsertMenu(mh,menu+1); |
DisposPtr((Ptr)oldStrings); |
} |
void InstallEditMenu(beWNumCallProcPtr Xundo, |
beWNumCallProcPtr Xcut, |
beWNumCallProcPtr Xcopy, |
beWNumCallProcPtr Xpaste, |
beWNumCallProcPtr Xclear) |
/* |
* Start an edit menu, and put the first six things in. |
*/ |
{ |
gAppUndoProc = Xundo; |
gAppCutProc = Xcut; |
gAppCopyProc = Xcopy; |
gAppPasteProc = Xpaste; |
gAppClearProc = Xclear; |
InstallMenu("\pEdit",nil,0); |
InstallMenuItem("\px/Z",(beMenuProcPtr)BEUndo,-mUndo); /* barfs because it is static */ |
InstallMenuItem("\p(-",(beMenuProcPtr)BENull,0); |
InstallMenuItem("\px/X",(beMenuProcPtr)BECut,-mCut); |
InstallMenuItem("\px/C",(beMenuProcPtr)BECopy,-mCopy); |
InstallMenuItem("\px/V",(beMenuProcPtr)BEPaste,-mPaste); |
InstallMenuItem("\px/B",(beMenuProcPtr)BEClear,-mClear); |
gMenuEdit = gMenuHandleList[gCurrentMenu]; |
EnDisEdits(-1,-1,-1,-1,-1); |
} |
void InstallPrintItems(beMenuProcPtr pageSetup,beMenuProcPtr print) |
{ |
gAppPageSetupProc = pageSetup; |
gAppPrintProc = print; |
InstallMenuItem("\pPage SetupÉ/¹",(beMenuProcPtr)BEPageSetup,-mPageSetup); |
InstallMenuItem("\pPrintÉ/P",(beMenuProcPtr)BEPrint,-mPrint); |
} |
void SetMenuItem(short ref,char enable,char isMarked,char mark,StringPtr s) |
/* |
* Set all items with the reference number to the |
* enable/disable state, with mark, and name s. |
* pass enable + to enable, - to disable, and |
* zero to leave alone. |
*/ |
{ |
short m,i; |
MenuHandle mh; |
register TEasyMenuItem *emi; |
for(m=1; m<=gMenuCount; m++) |
{ |
mh = gMenuHandleList[m]; |
for(i=gMenuLength[m]; i>=0; i--) |
{ |
emi = &gMenu[m][i]; |
if(emi->ref == ref) |
{ |
if(enable) |
{ |
if(!i) |
gInvalidMenuBar = true; |
if(enable > 0) |
{ |
emi->enable = 1; |
EnableItem(mh,i); |
} |
else |
{ |
emi->enable = 0; |
DisableItem(mh,i); |
} |
} |
if(i > 0) /* these only apply to items */ |
{ |
if(isMarked) |
if(isMarked > 0) |
{ |
emi->mark = mark; |
SetItemMark(mh,i,mark); |
//CheckItem(mh,i,true); |
} |
else |
{ |
emi->mark = 0; |
SetItemMark(mh,i,0); |
} |
if(s) |
SetItem(mh,i,(StringPtr)s); |
} |
} |
} |
} |
} |
void EnDisEdits(short Eundo,short Ecut,short Ecopy,short Epaste,short Eclear) |
/* |
* For each edit menu entry, |
* -1=disable, 1=enable, 0=leave alone. |
*/ |
{ |
SetMenuItem(mUndo,Eundo,false,0,"\pUndo"); |
SetMenuItem(mCut,Ecut,false,0,"\pCut"); |
SetMenuItem(mCopy,Ecopy,false,0,"\pCopy"); |
SetMenuItem(mPaste,Epaste,false,0,"\pPaste"); |
SetMenuItem(mClear,Eclear,false,0,"\pClear"); |
} |
MenuHandle SetCurrentMenu(short ref) |
/* |
* Set which menu will take |
* future "InstallMenuItem"s. |
*/ |
{ |
register short i; |
for(i = 0; i<gMenuCount; i++) |
{ |
if(gMenu[i][0].ref == ref) |
{ |
gCurrentMenu = i; |
return gMenuHandleList[i]; |
} |
} |
return 0; |
} |
long DisableAllMenus(void) |
/* |
* Disable all menus, as for a modal dialog, |
* and return a long with the masks of which should get reenabled. |
*/ |
{ |
long result; |
long mask; |
TEasyMenuItem *emi; |
short i; |
result = 0; |
mask = 1; |
for(i = 0; i<kMMax; i++) |
{ |
emi = &gMenu[i][0]; |
if(emi->enable) |
{ |
DisableItem(gMenuHandleList[i],0); |
result |= mask; |
} |
mask <<= 1; |
} |
DrawMenuBar(); |
return result; |
} |
void EnableAllMenus(long saveMenus) |
/* |
* Enable menus according to the mask returned by DisableAllMenus(). |
*/ |
{ |
long mask; |
short i; |
mask = 1; |
for(i = 0; i<kMMax; i++) |
{ |
if(saveMenus & mask) |
EnableItem(gMenuHandleList[i],0); |
mask <<= 1; |
} |
DrawMenuBar(); |
} |
short ScanWindowList(WindowPtr w) |
/* |
* return a window number from a WindowPeek, |
* or -1 if no known window. |
*/ |
{ |
short i; |
TEasyWindow *wo; |
wo= &gEasyWindowList[0]; |
for(i=0; i<gEasyWindowListSize; i++) |
{ |
if (wo->wUsed && (wo->wWindow==w)) |
return i; |
wo++; |
} |
return -1; |
} |
/*---------------- |
Mouse Action Routines |
----------------*/ |
void DoMouseClick(EventRecord *event) |
{ |
WindowPtr w; |
short part; |
register short wNum; |
register TEasyWindow *thisEasyWindow; |
Point p; |
Rect r; |
Boolean tookEvent; |
p = event->where; |
part = FindWindow (p, &w); |
wNum = ScanWindowList(w); |
thisEasyWindow = GoodWNum(wNum); |
switch (part) |
{ |
case inDesk: |
break; |
case inMenuBar: |
MenuClick(p); |
break; |
case inSysWindow: |
SystemClick(event,w); |
break; |
case inContent: |
contentClick: |
if (w != FrontWindow()) /* If clicked on a non-front window, */ |
SelectWindow(w); /* bring it to the front. */ |
else if(thisEasyWindow) /* Click on front window: give click */ |
{ /* to window's click routine. */ |
SetPort(w); |
GlobalToLocal(&p); |
ClipRect(&gBigRect); |
SetOrigin(0,0); |
if(thisEasyWindow && thisEasyWindow->wEventProc) |
(*thisEasyWindow->wEventProc)(wNum,event,&tookEvent); |
else |
tookEvent = false; |
if(!tookEvent) |
{ |
register beClickProcPtr fp; |
fp = thisEasyWindow->wClickProc; |
if(fp) |
(*fp)(wNum,p, |
event->modifiers); |
} |
} |
break; |
case inDrag: |
if(((thisEasyWindow->flags & wCoolDrag)!=0) |
^ ((event->modifiers & optionKey)!=0)) |
{ |
gCoolDragPoint = event->where; |
gCoolDragState = 1; |
gCoolDragEW = thisEasyWindow; |
gCoolDragWindowNumber = wNum; |
if(!(event->modifiers & 256)) |
SelectWindow(w); |
} |
else |
if(Button()) /* for quick title-bar clicks */ |
{ |
beMoveWindowProcPtr fp; |
DragWindow(w,event->where,&gBigRect); |
fp = thisEasyWindow->wMoveWindowProc; |
if(fp) |
(fp)(wNum); |
} |
else |
SelectWindow(w); |
break; |
case inGrow: |
if(thisEasyWindow && (thisEasyWindow->flags & wGrowable)) |
{ |
long oldSize,newSize; |
beGrowWindowProcPtr fp; |
beResizeProcPtr rsfp; |
SetPort(w); |
GetGrowRect(w,&r); |
InvalRect(&r); |
fp = thisEasyWindow->wGrowWindowProc; |
if(fp) |
(*fp)(&newSize,wNum,w,event->where,&gResizeLim); |
else |
newSize = GrowWindow(w,event->where,&gResizeLim); |
if(newSize) |
{ |
rsfp = thisEasyWindow->wResizeProc; |
if(rsfp) |
{ |
oldSize = ((long)(w->portRect.bottom-w->portRect.top)<<16) | |
(w->portRect.right-w->portRect.left); |
(*rsfp)(wNum,(Point *)&oldSize,(Point *)&newSize,event->modifiers); |
} |
else |
SizeWindow(w,newSize&0xffff,newSize>>16,1); |
GetGrowRect(w,&r); |
InvalRect(&r); |
} |
} |
else |
goto contentClick; |
break; |
case inGoAway: |
if(thisEasyWindow) |
if (TrackGoAway(w,event->where)) |
{ |
beGoAwayProcPtr fp; |
fp = thisEasyWindow->wGoAwayProc; |
if(fp) |
(*fp)(wNum); |
} |
break; |
/* |
* The following way to handle zoom only |
* applies to zooming to 1 state. This does |
* not handle zooming in and out between 2 |
* states. Check IM IV. |
*/ |
case inZoomIn: /* zoomBox */ |
case inZoomOut: |
if(thisEasyWindow) |
{ |
if (TrackBox(w,event->where,part)) |
{ |
beWNumCallProcPtr fp; |
fp = thisEasyWindow->wZoomProc; |
if(fp) |
(*fp)(wNum); |
} |
} |
break; |
} |
} |
/*---------------- |
Window Action Routines |
----------------*/ |
WindowPtr InstallWindow(short iNum,StringPtr iTitle,Rect *iRect,short iType,short iFlags, |
beUpdateProcPtr iUpdate,beClickProcPtr iClick,beKeyProcPtr iKey,beGoAwayProcPtr iGoAway, |
beActivateProcPtr iActivate,beDeactivateProcPtr iDeactivate,beIdleProcPtr iIdle) |
/* |
* Add a window to BigEasy's list. If the window is |
* already up somewhere, bring it to the front and |
* visualize it. |
*/ |
{ |
TEasyWindow *thisWindow; |
Rect stagRect,**oldPos; |
Boolean isVisible; |
RgnHandle rh; |
KeyMap km; |
Boolean opt; |
GetKeys(km); |
opt =km[58/8] & (1<< (58%8) ); |
isVisible = iNum>0; |
if(!isVisible) |
iNum = -iNum; |
EnoughEasyWindows(iNum); /* Make sure there's space for new one */ |
thisWindow = &gEasyWindowList[iNum]; |
if (thisWindow->wUsed) /* something already assigned to this window? */ |
{ |
Show(iNum); |
goto goHome; |
} |
oldPos = (Rect **)Get1Resource(kWinPosType,iNum); /* attempt to find saved window position */ |
stagRect = *iRect; |
if(oldPos && !opt) /* (option key "forgets" old window */ |
OffsetRect(&stagRect, |
(**oldPos).left - stagRect.left,(**oldPos).top - stagRect.top); |
{ |
Rect lilRect; |
lilRect.top = stagRect.top - 10; |
lilRect.left = stagRect.left + 4; |
lilRect.bottom = lilRect.top + 1; |
lilRect.right = lilRect.left + 1; |
rh = NewRgn(); |
RectRgn(rh,&lilRect); |
SectRgn(rh,*(RgnHandle *)0x9EE,rh); |
if(EmptyRgn(rh) && gWindowsInView) |
OffsetRect(&stagRect,50 - iRect->left,80 - iRect->top); |
if(gStaggerWindows) |
{ |
gStagX = (gStagX + gStagStepX)%kStagLimX; |
gStagY = (gStagY + gStagStepY)%kStagLimY; |
OffsetRect(&stagRect,gStagX,gStagY); |
} |
DisposeRgn(rh); |
} |
thisWindow->wUsed = 1; |
if(gHasColor) |
thisWindow->wWindow = NewCWindow(0,&stagRect,(StringPtr)iTitle,isVisible, |
((iFlags & wZoomable) != 0) ? zoomDocProc : iType, |
(WindowPtr)-1,iGoAway!=0,0); |
else |
thisWindow->wWindow = NewWindow(0,&stagRect,(StringPtr)iTitle,isVisible, |
((iFlags & wZoomable) != 0) ? zoomDocProc : iType, |
(WindowPtr)-1,iGoAway!=0,0); |
SetPort(thisWindow->wWindow); |
thisWindow->flags = iFlags; |
thisWindow->iNum = iNum < 0 ? -iNum : iNum; |
thisWindow->wUpdateProc = iUpdate; |
thisWindow->wClickProc = iClick; |
thisWindow->wKeyProc = iKey; |
thisWindow->wGoAwayProc = iGoAway; |
thisWindow->wZoomProc = nil; |
thisWindow->wActivateProc = iActivate; |
thisWindow->wDeactivateProc = iDeactivate; |
thisWindow->wIdleProc = iIdle; |
thisWindow->wResizeProc = nil; |
thisWindow->wGrowWindowProc = nil; |
thisWindow->wMoveWindowProc = nil; |
thisWindow->wEventProc = nil; |
#ifdef BigEasyGXPrinting |
thisWindow->job = nil; |
#endif |
goHome: |
return thisWindow->wWindow; |
} |
#ifdef BigEasyGXPrinting |
void MakeSureWeHaveJob(TEasyWindow *thisWindow) |
{ |
if(!thisWindow->job) |
if((thisWindow->flags & wPrintDraw) && gHasGX) |
{ |
GoWatch(); |
GXNewJob(&thisWindow->job); |
GoArrow(); |
} |
} |
#endif |
void UninstallWindow(short iNum) |
{ |
register TEasyWindow *thisWindow; |
register beDeactivateProcPtr fp; |
gCoolDragState = 0; /* just in case we were dragging the dissappeared window */ |
if(!(thisWindow = GoodWNum(iNum))) |
return; |
SetPort(thisWindow->wWindow); |
fp = thisWindow->wDeactivateProc; |
if(fp) |
(*fp)(iNum); |
CloseWindow(thisWindow->wWindow); |
EnDisEdits(-1,-1,-1,-1,-1); |
#ifdef BigEasyGXPrinting |
if((thisWindow->flags & wPrintDraw) && gHasGX) |
GXDisposeJob(thisWindow->job); |
#endif |
thisWindow->wUsed = 0; |
} |
void Show(short iNum) |
{ |
register TEasyWindow *thisWindow; |
thisWindow = GoodWNum(iNum); |
if(thisWindow) |
{ |
if(!((WindowPeek)(thisWindow->wWindow))->visible) /* If so, just show it, and bring it to the front. */ |
ShowWindow(thisWindow->wWindow); |
SelectWindow(thisWindow->wWindow); |
} |
} |
void Hide(short iNum) |
/* |
* Just do HideWindow to the |
* specified window number. |
*/ |
{ |
register TEasyWindow *thisWindow; |
gCoolDragState = 0; /* It might have been this window */ |
thisWindow = GoodWNum(iNum); |
if(thisWindow) |
HideWindow(thisWindow->wWindow); |
} |
void GetWindowRect(short n,Rect *r) |
/* |
* return the window's current rectangle |
* in global cordinate space. |
*/ |
{ |
TEasyWindow *thisWindow; |
WindowPtr g; |
if(!(thisWindow = GoodWNum(n))) |
return; |
if(thisWindow->wUsed) |
{ |
g = thisWindow->wWindow; |
SetPort(g); |
*r = g->portRect; |
LocalToGlobal((Point *)r); |
LocalToGlobal((Point *)( (char*)r + 4)); |
} |
} |
WindowPtr GetWindowPtr(short n) |
/* |
* return the windowptr for |
* the specified window number |
*/ |
{ |
TEasyWindow *thisWindow; |
WindowPtr g; |
if(!(thisWindow = GoodWNum(n))) |
g = 0; |
else |
g = thisWindow->wWindow; |
return g; |
} |
Boolean GetWindowVisible(short n) |
/* |
* return true if the window exists, |
* and is visible, or false if its invisible |
* or doesn't exist. |
*/ |
{ |
register WindowPtr g; |
g = GetWindowPtr(n); |
if(g) |
return ((WindowPeek)g)->visible; |
else |
return false; |
} |
void SaveWindowPosition(short n) |
/* |
* Save the position of window number n, |
* or all windows if n = -1; |
*/ |
{ |
Rect **rH; |
register Rect *r; |
register short i; |
register short n1,n2; |
TEasyWindow *thisWindow; |
rH = (Rect **)NewHandleClear(sizeof(Rect)); |
FailNil((long)rH); |
HLock((Handle)rH); |
r = *rH; |
if(n < 0) |
{ |
n1 = 0; |
n2 = gEasyWindowListSize-1; |
} |
else |
n1 = n2 = n; |
for(i = n1; i<=n2; i++) |
{ |
thisWindow = GoodWNum(i); |
if(thisWindow && thisWindow->wUsed) |
{ |
GetWindowRect(i,r); |
if( !((WindowPeek)(thisWindow->wWindow))->visible ) |
SwapShort(r->left,r->right); |
Replace1Resource((Handle)rH,kWinPosType,i); |
} |
} |
DisposHandle( (Handle)rH ); |
} |
void ForgetWindowPosition(short n) |
/* |
* Forget the saved window position n, |
* or all windows if n<0. |
*/ |
{ |
register short i; |
register short n1,n2; |
register TEasyWindow *thisWindow; |
if(n < 0) |
{ |
n1 = 0; |
n2 = gEasyWindowListSize-1; |
} |
else |
n1 = n2 = n; |
for(i = n1; i<=n2; i++) |
{ |
thisWindow = GoodWNum(i); |
if(thisWindow && thisWindow->wUsed) |
Replace1Resource(0,kWinPosType,i); |
} |
} |
void Replace1Resource(Handle h,long type,short id) |
/* |
* This is AddResource with a |
* RmveResource if necessary. |
* Pass h==nil to delete the resource. |
*/ |
{ |
Handle old; |
/* |
* A lame hack to prevent writing resources |
* to a lightspeed project file. |
*/ |
if( *(StringPtr)(0x910 + (*(StringPtr)0x910)) == '¹') |
{ |
/* do nothing */ |
} |
else |
{ |
old = Get1Resource(type,id); |
if(old) |
RemoveResource(old); |
if(h) |
{ |
AddResource(h,type,id,(StringPtr)"\p"); |
WriteResource(h); |
DetachResource(h); |
} |
} |
} |
void CheckMenubar(void) |
{ |
if(gInvalidMenuBar) |
{ |
DrawMenuBar(); |
gInvalidMenuBar = false; |
} |
} |
/*---------------- |
Event Routines |
----------------*/ |
Boolean HandleUpdateEvent(EventRecord *er) |
/* |
* Update the appropriate window, if we know who it is. |
*/ |
{ |
Boolean result; |
short wNum; |
TEasyWindow *thisEasyWindow; |
WindowPtr w; |
GrafPtr oldPort; |
GetPort(&oldPort); |
result = false; |
if(er->what != updateEvt) |
{ |
result = false; |
goto goHome; |
} |
w = (WindowPtr)er->message; |
wNum = ScanWindowList(w); /* other than null or click, scan list */ |
thisEasyWindow = GoodWNum(wNum); /* and get record */ |
if(thisEasyWindow) |
{ |
Rect visBounds; |
beUpdateProcPtr fp; |
SetPort(w); |
BeginUpdate(w); |
result = true; |
visBounds = (**w->visRgn).rgnBBox; |
fp = thisEasyWindow->wUpdateProc; |
if(fp) |
{ |
SetPort(thisEasyWindow->wWindow); /* Set port to window */ |
(*fp)(wNum); /* Call drawing proc */ |
} |
SetOrigin(0,0); |
if (thisEasyWindow->flags & wGrowable) /* Draw growbox, if... */ |
MyDrawGrowIcon(w); |
ClipRect(&gBigRect); |
DrawControls(w); |
EndUpdate(w); |
} |
else |
result = false; |
goHome: |
SetPort(oldPort); |
return result; |
} |
Boolean ActivateWindow(WindowPtr w, Boolean activate) |
{ |
Boolean result; |
short wNum; |
TEasyWindow *thisEasyWindow; |
GrafPtr oldPort; |
GetPort(&oldPort); |
wNum = ScanWindowList(w); /* other than null or click, scan list */ |
thisEasyWindow = GoodWNum(wNum); /* and get record */ |
if(!thisEasyWindow) |
{ |
result = false; |
goto goHome; |
} |
result = true; |
FrontDAEdits(); |
if(thisEasyWindow) |
{ |
SetPort(thisEasyWindow->wWindow); |
if(activate) |
{ |
beActivateProcPtr fp; |
short copyItem,printItems; |
if(thisEasyWindow->flags & wCopyDraw) |
copyItem = 1; |
else |
copyItem = -1; |
EnDisEdits(-1,-1,copyItem,-1,-1); |
if(((thisEasyWindow->flags & wPrintDraw) && gHasGX) |
|| (gAppPageSetupProc && gAppPrintProc) ) |
printItems = 1; |
else |
printItems = -1; |
SetMenuItem(mPageSetup,printItems,0,0,nil); |
SetMenuItem(mPrint,printItems,0,0,nil); |
fp = thisEasyWindow->wActivateProc; |
if(fp) |
(*fp)(wNum); |
} |
else |
{ |
beDeactivateProcPtr fp; |
EnDisEdits(-1,-1,-1,-1,-1); |
SetMenuItem(mPageSetup,-1,0,0,nil); |
SetMenuItem(mPrint,-1,0,0,nil); |
fp = thisEasyWindow->wDeactivateProc; |
if(fp) |
(*fp)(wNum); |
} |
InitCursor(); |
if (thisEasyWindow->flags & wGrowable) /* Draw growbox, if... */ |
MyDrawGrowIcon(w); |
} |
goHome: |
SetPort(oldPort); |
return result; |
} |
Boolean HandleActivateEvent(EventRecord *er) |
/* |
* Handle it, if we can find out who it is. |
*/ |
{ |
Boolean result; |
result = true; |
switch(er->what) |
{ |
case activateEvt: |
ActivateWindow((WindowPtr)er->message,er->modifiers & 1); |
break; |
case kOSEvent: |
switch ((unsigned long) er->message >> 24) /* high byte of message */ |
{ |
case kSuspendResumeMessage: |
ActivateWindow(FrontWindow(),er->modifiers & 1); |
break; |
default: |
result = false; |
break; |
} |
break; |
default: |
result = false; |
break; |
} |
goHome: |
return result; |
} |
void EventLoop(void) |
{ |
EventRecord er; |
short i; |
register short wNum; |
WindowPtr w; |
register TEasyWindow *thisEasyWindow; |
Boolean tookKey,tookEvent; |
CheckMenubar(); |
WaitNextEvent(0xffff,&er,gSleep,nil); |
{ |
gLastModifiers = er.modifiers; |
gLastEventTime = er.when; |
if(er.what > 5 && er.what < 12) /* update event or higher: in message */ |
w = (WindowPtr)er.message; |
else |
w = FrontWindow(); /* else, use FrontW */ |
if(er.what > 1) |
{ |
wNum = ScanWindowList(w); /* other than null or click, scan list */ |
thisEasyWindow = GoodWNum(wNum); /* and get record */ |
} |
else |
thisEasyWindow = 0; |
SetPort(w); |
if(thisEasyWindow && thisEasyWindow->wEventProc) |
(*thisEasyWindow->wEventProc)(wNum,&er,&tookEvent); |
else |
tookEvent = 0; |
if(!tookEvent) |
switch (er.what) |
{ |
case 0: /* null event */ |
break; |
case mouseDown: |
FrontDAEdits(); |
DoMouseClick(&er); |
break; |
case keyDown: |
case autoKey: |
FrontDAEdits(); |
tookKey = false; |
if( (!gMenuNeedsCmdKey) || (er.modifiers & 256) ) |
tookKey = DoKeyPress(er.message); |
if(!tookKey && ((!gMenuNeedsCmdKey) || (er.modifiers & 256)) ) |
tookKey = CoolBigEasyCmdKeys(er.message & 0xFF); |
if(!tookKey) |
if(thisEasyWindow) |
{ |
beKeyProcPtr fp; |
fp = thisEasyWindow->wKeyProc; |
if(fp) |
{ |
SetPort(thisEasyWindow->wWindow); /* Set port to window */ |
(*fp)(wNum, /* Call key proc */ |
(short)(er.message&0xff), /* with the key */ |
(short)((er.message>>8)&0xff), /* the key code */ |
er.modifiers); /* and the modifiers */ |
} |
} |
break; |
case updateEvt: |
HandleUpdateEvent(&er); |
break; |
case activateEvt: |
HandleActivateEvent(&er); |
break; |
case kOSEvent: |
switch ((unsigned long) er.message >> 24) /* high byte of message */ |
{ |
case kSuspendResumeMessage: |
if(thisEasyWindow) /* just like activate event... */ |
{ |
ActivateWindow(FrontWindow(), |
er.message & kResumeMask); |
} |
break; |
} |
break; |
case kHighLevelEvent: |
AEProcessAppleEvent(&er); |
break; |
case diskEvt: |
if (er.message & 0xffff0000) { |
Point where = {100,100}; |
// DIBadMount(where, er.message); |
} |
break; |
default: |
/*Debugger();/**/ |
; |
} |
} |
/* |
* See if we're doing a fake cool drag-window |
*/ |
if(gCoolDragState) |
{ |
Point p,q; |
SetPort(gCoolDragEW->wWindow); |
GetMouse(&p); |
LocalToGlobal(&p); |
if( (p.v!=gCoolDragPoint.v) || (p.h!=gCoolDragPoint.h) ) |
{ |
q.h = gCoolDragEW->wWindow->portRect.left; |
q.v = gCoolDragEW->wWindow->portRect.top; |
LocalToGlobal(&q); |
MoveWindow(gCoolDragEW->wWindow, |
q.h+p.h-gCoolDragPoint.h, |
q.v+p.v-gCoolDragPoint.v,0); |
gCoolDragPoint = p; |
{ |
beMoveWindowProcPtr fp; |
fp = gCoolDragEW->wMoveWindowProc; |
if(fp) |
(fp)(gCoolDragWindowNumber); |
} |
} |
if(!Button()) |
gCoolDragState = 0; |
} |
SystemTask(); |
w = FrontWindow(); |
if ( w == gLastFrontIdle) /* Minor optimization, wins if the same */ |
wNum = gLastFrontWindowNumber; /* window is frontmost for a while. */ |
else |
{ |
wNum = ScanWindowList(w); |
gLastFrontIdle = w; |
gLastFrontWindowNumber = wNum; |
} |
if(er.what != mouseDown && er.what != activateEvt && !gQuitApp) /* anything but a mousedown or [de]activate */ |
{ |
gIdleSeed ++; |
if(gIdleSeed & 1) /* every other chance... */ |
for(i = 1; i<gEasyWindowListSize; i++) |
{ |
if(gEasyWindowList[i].wUsed && gEasyWindowList[i].wIdleProc) |
{ |
SetPort(gEasyWindowList[i].wWindow); |
(*gEasyWindowList[i].wIdleProc) |
((short)i,(Boolean)(w == gEasyWindowList[i].wWindow)); |
} |
} |
} |
if (gMasterIdleProc && !gQuitApp) |
(*gMasterIdleProc)(); |
} |
Boolean CoolBigEasyCmdKeys(short key) |
{ |
WindowRecord *w; |
switch(key) |
{ |
/* |
* Rotate active window |
*/ |
case 9: /* <tab> */ |
w = *(WindowRecord **)0x9D6; /* windowlist */ |
if(w) |
{ |
while (w->nextWindow) |
w = w->nextWindow; |
SelectWindow((WindowPtr)w); |
} |
break; |
default: |
return false; |
} |
return true; |
} |
void IdleWindow(short n) |
/* |
* Idle window number n, or |
* -1 to idle all windows. |
*/ |
{ |
register short i; |
short lo,hi; |
WindowPtr w; |
register TEasyWindow *ew; |
GrafPtr oldPort; |
GetPort(&oldPort); |
if(n<0) |
{ |
lo = 1; |
hi = gEasyWindowListSize; |
} |
else |
{ |
lo = n; |
hi = n + 1; |
} |
w = FrontWindow(); |
ew = &gEasyWindowList[lo]; |
for(i = lo; i < hi; i++) |
{ |
if(ew->wUsed && ew->wIdleProc) |
{ |
SetPort(ew->wWindow); |
(*ew->wIdleProc)((short)i,ew->wWindow == w); |
} |
ew++; |
} |
SetPort(oldPort); |
SystemTask(); |
} |
void MyDrawGrowIcon(WindowPtr w) |
{ |
Rect r; |
SetPort(w); |
GetGrowRect(w,&r); |
ClipRect(&r); |
DrawGrowIcon(w); |
ClipRect(&gBigRect); |
} |
void SetMasterOpenAppProc(beOpenAppProcPtr openAppProc) |
{ |
gMasterOpenAppProc = openAppProc; |
if(gHasAppleEvents) |
AEInstallEventHandler(kCoreEventClass, kAEOpenApplication, |
(AEEventHandlerUPP)BigEasyOpenAppThang, 0, false); |
} |
void SetMasterOpenDocProc(beOpenDocProcPtr openDocProc) |
{ |
gMasterOpenDocProc = openDocProc; |
if(gHasAppleEvents) |
AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, |
(AEEventHandlerUPP)BigEasyOpenDocThang, 0, false); |
} |
void SetMasterQuitAppProc(beQuitAppProcPtr quitAppProc) |
{ |
gMasterQuitAppProc = quitAppProc; |
} |
pascal OSErr BigEasyOpenAppThang(AppleEvent *theEvent, AppleEvent *reply,long refCon) |
{ |
#pragma unused (reply,refCon,theEvent) |
return noErr; |
} |
pascal OSErr BigEasyOpenDocThang(AppleEvent *message, AppleEvent *reply,long refCon) |
{ |
FSSpec fSpec; |
AEDescList docList; |
long index, itemsInList; |
Size actualSize; |
AEKeyword keywd; |
DescType typeCode; |
OSErr thisError; |
#pragma unused (reply,refCon) |
thisError = AEGetParamDesc(message, keyDirectObject, typeAEList, &docList); |
if(thisError) |
goto goHome; |
thisError = MissedAEParameters(message); |
if(thisError) |
goto goHome; |
thisError = AECountItems(&docList, &itemsInList); |
if(thisError) |
goto goHome; |
for (index = 1; index <= itemsInList; index++) |
{ |
thisError = AEGetNthPtr(&docList, index, typeFSS, &keywd, &typeCode, |
(Ptr)&fSpec, sizeof(FSSpec), &actualSize); |
if(thisError) |
goto goHome; |
if(gMasterOpenDocProc) |
(*gMasterOpenDocProc)(&fSpec); |
} |
thisError = AEDisposeDesc(&docList); |
goHome: |
return thisError; |
} |
pascal OSErr BigEasyQuitAppThang(AppleEvent *theEvent, AppleEvent *reply,long refCon) |
{ |
OSErr thisError; |
#pragma unused (reply,refCon) |
thisError = MissedAEParameters(theEvent); |
if (!thisError) |
{ |
++ gQuitApp; |
if(gMasterQuitAppProc) |
(*gMasterQuitAppProc)(); |
} |
return thisError; |
} |
OSErr MissedAEParameters (AppleEvent *message) |
{ |
DescType typeCode; |
Size actualSize; |
OSErr err; |
err = AEGetAttributePtr(message, keyMissedKeywordAttr, typeWildCard, |
&typeCode, nil, 0L, &actualSize); |
if (err == errAEDescNotFound) |
return(noErr); |
return(err = noErr ? errAEEventNotHandled : err); |
} |
void InitBigEasy(void) |
{ |
long result; |
InstallMyExitToShell(); |
gMasterOpenAppProc = nil; |
gMasterOpenDocProc = nil; |
gMasterIdleProc = nil; |
gAboutProc = nil; |
gQuitApp = false; |
gMenuNeedsCmdKey = true; |
gStaggerWindows = true; |
gWindowsInView = true; |
gSleep = 0; |
gInvalidMenuBar = false; |
gStagStepX = 7; |
gStagStepY = 7; |
SetRect(&gBigRect,-16000,-16000,16000,16000); |
gEasyWindowListH = (TEasyWindow**)NewHandleClear(sizeof(TEasyWindow)); |
HLock((Handle)gEasyWindowListH); |
gEasyWindowList = *gEasyWindowListH; |
gEasyWindowList[0].wUsed = 0; |
gEasyWindowListSize = 1; |
gLastFrontIdle = (WindowPtr) 0; |
gLastFrontWindowNumber = -1; |
gCoolDragState = 0; |
/* |
* 7.0 Feature stuff |
*/ |
gSystemVersion = (Gestalt('sysv', &result)) ? 0 : result; |
gHasAppleEvents = (Gestalt(gestaltAppleEventsAttr, &result) ? false : result != 0); |
gHasColor = (Gestalt('qdrw',&result)) ? |
false : (result & (1<<gestaltHasDeepGWorlds)) != 0; |
/* |
* The quit-app message, if available. |
*/ |
gMasterQuitAppProc = nil; |
if(gHasAppleEvents) |
AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, |
(AEEventHandlerUPP)BigEasyQuitAppThang, 0, false); |
/* |
* GX Feature stuff |
*/ |
#ifdef BigEasyGXPrinting |
gHasGX = WantsGX |
&& ( (Gestalt(gestaltGXVersion,&result)) ? false : true ); |
if(gHasGX) |
{ |
GXEnterGraphics(); |
GXInitPrinting(); |
} |
#else |
gHasGX = false; |
#endif |
} |
static void ExitBigEasy(void) |
{ |
#ifdef BigEasyGXPrinting |
if(gHasGX) |
{ |
GXExitGraphics(); |
GXExitPrinting(); |
} |
#endif |
} |
void main(void) |
{ |
#if 0 |
#ifdef THINK_C_PROFILE |
freopen("profile output","w+",stdout); |
InitProfile(1000,50); |
#endif THINK_C_PROFILE |
#endif |
MaxApplZone(); |
MoreMasters(); |
MoreMasters(); |
InitToolbox(); |
StartMenus(); |
InitBigEasy(); |
Bootstrap(); |
#if THINK_C >= 5 |
#if defined(STACK_KILLER) || defined(TIMING_PROFILE) |
prepStackKiller(); /** slime from HELL **/ |
#ifdef TIMING_PROFILE |
InitTimingProfile(150); /* call depth */ |
#endif TIMING_PROFILE |
#endif |
#endif |
while (!gQuitApp) |
EventLoop(); |
FlushEvents(0xffff,0); |
#ifdef TIMING_PROFILE |
DumpProfile(0, 0, "\ptiming stats"); |
#endif |
ExitBigEasy(); |
ExitToShell(); |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-03-19