home *** CD-ROM | disk | FTP | other *** search
- /* File Example.c Copyright (C) 1996 by John R. Montbriand. All Rights Reserved. */
-
- /* File Example.c
-
- Copyright (C) 1996 by John Montbriand. All Rights Reserved.
-
- Distribute freely in areas where the laws of copyright apply.
-
- Use at your own risk.
-
- Do not distribute modified copies.
-
- These various BitMap libraries and examples are for free!
-
- See the accompanying file BitMap.txt for details.
-
- */
-
- /* written in Geneva 9, tabs at 4 */
-
- /* •••••••••••••••••••••• INCLUDES •••••••••••••••••••••• */
-
- #include <Types.h>
- #include <QuickDraw.h>
- #include <Fonts.h>
- #include <Windows.h>
- #include <Menus.h>
- #include <TextEdit.h>
- #include <Dialogs.h>
- #include <AppleEvents.h>
- #include <TextUtils.h>
- #include <OSUtils.h>
- #include <ToolUtils.h>
- #include <Desk.h>
- #include <Memory.h>
- #include <Errors.h>
- #include <Gestalt.h>
- #include <Traps.h>
- #include <SegLoad.h>
-
- #include "BitMap.h"
-
- /* •••••••••••••••••••••• CONSTANTS •••••••••••••••••••••• */
-
- #define kAboutBoxID 128
- #define kErrorBoxID 129
- #define kMainWindID 128
- #define kMenuBarID 128
-
- #define mApple 128
- #define iAbout 1
- #define iAccessoryOne 3
-
- #define mFile 129
- #define iQuit 1
-
- #define mEdit 130
- #define iUndo 1
- #define iCut 3
- #define iCopy 4
- #define iPaste 5
- #define iClear 6
-
- /* •••••••••••••••••••••• GLOBALS •••••••••••••••••••••• */
-
- Boolean PROGRAM_RUNNING = true;
- Boolean PROGRAM_FRONT = true;
- Boolean HAS_APPLEEVENTS = false;
- Boolean HAS_WAITNEXTEVENT = false;
-
- QDGlobals qd;
-
- DialogPtr gABOUTBOX = NULL;
- WindowPtr gMAIN_WINDOW = NULL;
-
-
- /* •••••••••••••••••••••• ERROR HANDLER •••••••••••••••••••••• */
-
- /* Terminate, displays an error box containing the error number and then terminates
- the application. */
- void Terminate(OSErr err) {
- Str255 s;
- NumToString(err, s);
- ParamText(s, NULL, NULL, NULL);
- Alert(kErrorBoxID, NULL);
- ExitToShell();
- }
-
- /* •••••••••••••••••••••• THE EXAMPLE PART •••••••••••••••••••••• */
- /* NOTE: all of the example code to do with bitmaps is included in this part of the
- program. The rest of the program has to do with the usual things that go into
- applications. */
-
- Rect gBounds;
- CursHandle gPaintCursor;
- BitMap *pic_bits, *mask_bits;
-
-
- /*DrawWindowContents is called in response to every update event for the main
- window. this is the part where we do drawing in the bitmaps */
- void DrawWindowContents(WindowPtr wp) {
- if (mask_bits == NULL) {
-
- /* no mask, just draw the image... */
- PlotBitMap(pic_bits, 5, 5, srcCopy);
-
- } else {
- BitMap *gray_mask, *drawn_bits;
- BitMapPort* bmp;
-
- /* calculate the masks */
- gray_mask = NULL;
- drawn_bits = NULL;
-
- /* calculate the painted area in gray */
- gray_mask = DuplicateBitMap(mask_bits);
- if (gray_mask == NULL) goto bail;
- WithBitMap(gray_mask, bmp) {
- PenMode(patBic);
- PenPat(&qd.gray);
- PaintRect(&gray_mask->bounds);
- }
-
- /* add the painted area to the drawn area */
- drawn_bits = BitMapOR(gray_mask, pic_bits);
- if (drawn_bits == NULL) goto bail;
-
- /* draw the image */
- PlotBitMap(drawn_bits, 5, 5, srcCopy);
-
- bail:
- if (gray_mask != NULL) KillBitMap(gray_mask);
- if (drawn_bits != NULL) KillBitMap(drawn_bits);
- }
- }
-
-
- /*ClickWindowContents is called every time a mouse down event occurs in the
- main program window allowing for some interaction. Here, we track the
- mouse re-drawing the window appropriately as the mouse is dragged
- accross the window*/
- void ClickWindowContents(WindowPtr wp, Point where) {
- Point location, lastpos;
- BitMap* next_mask;
- location = where;
- SetPt(&lastpos, 0, 0);
- do {
- if (PtInRect(location, &gBounds) && !EqualPt(lastpos, location)) {
- lastpos = location;
-
- /* map the point from the drawn position, to the image */
- MapPt(&location, &gBounds, &pic_bits->bounds);
-
- /* make a new mask */
- next_mask = PaintBucketBitMap(pic_bits, location.h, location.v);
- if (next_mask == NULL) Terminate(memFullErr);
-
- /* redraw the window only if a change occured */
- if (!EqualBitMaps(mask_bits, next_mask)) {
-
- /* replace the old mask */
- if (mask_bits != NULL)
- KillBitMap(mask_bits);
- mask_bits = next_mask;
-
- /* redraw the window */
- DrawWindowContents(wp);
-
- } else KillBitMap(next_mask);
-
- }
- GetMouse(&location);
- } while (StillDown());
- }
-
-
- /* InitExample is called at program startup after the main window has been
- created to allow the example to set itself up. I put it here so all the example
- code would be together in one section. */
- OSErr InitExample(WindowPtr wp) {
- PicHandle pic;
- OSErr err;
-
- /* initial state */
- pic_bits = NULL;
- mask_bits = NULL;
-
- /* get the resources */
- gPaintCursor = GetCursor(128);
- if (gPaintCursor == NULL) { err = resNotFound; goto bail; }
- pic = GetPicture(129);
- if (pic == NULL) { err = resNotFound; goto bail; }
-
- /* make the bitmap */
- pic_bits = PICTToBitMap(pic);
- if (pic == NULL) { err = memFullErr; goto bail; }
-
- /* adjust the window size */
- SizeWindow(wp, pic_bits->bounds.right+10, pic_bits->bounds.bottom+10, true);
- gBounds = pic_bits->bounds;
- OffsetRect(&gBounds, 5, 5);
-
- /* done */
- return noErr;
- bail:
- if (pic_bits != NULL) KillBitMap(pic_bits);
- return err;
- }
-
-
- /* AdjustCursor is called once every time through the main loop so we
- can set up the cursor to look like a paint bucket when it's over the
- image. */
- void AdjustCursor(void) {
- if (FrontWindow() == gMAIN_WINDOW) {
- Point mouseLoc;
- SetPort(gMAIN_WINDOW);
- GetMouse(&mouseLoc);
- if (PtInRect(mouseLoc, &gBounds)) {
- SetCursor(*gPaintCursor);
- return;
- }
- }
- InitCursor();
- }
-
- /* •••••••••••••••••••••• MENU COMMANDS •••••••••••••••••••••• */
-
- /* HandleMenuCommand is called after MenuKey or MenuSelect to handle the processing
- of menu commands. Here there aren't too many, just the standard ones */
- void HandleMenuCommand(short menu, short item) {
- if (menu == mApple) {
- if (item == iAbout) {
- if (gABOUTBOX != NULL)
- SelectWindow(gABOUTBOX);
- else gABOUTBOX = GetNewDialog(kAboutBoxID, NULL, (WindowPtr) (-1));
- } else if (item >= iAccessoryOne) {
- Str255 itemString;
- GetItem(GetMHandle(menu), item, itemString);
- OpenDeskAcc(itemString);
- }
- } else if (menu == mFile) {
- switch (item) {
- case iQuit:
- PROGRAM_RUNNING = false;
- break;
- }
- } else if (menu == mEdit) {
- SystemEdit(item-1);
- }
- HiliteMenu(0);
- }
-
- /* MenuPreflightCheck is called immediately before MenuKey or MenuSelect. In your
- application you would use this routine to appropriately enable or disable different
- commands depending on what can be done at the time of the mouse click or key
- command. */
- void MenuPreflightCheck(void) {
- /* none here*/
- }
-
-
- /* •••••••••••••••••••••• EVENT HANDLING •••••••••••••••••••••• */
-
- /* HandleMouseDownEvent is called to process mouse down events */
- void HandleMouseDownEvent(EventRecord *ev) {
- WindowPtr target;
- switch ( FindWindow(ev->where, &target) ) {
- case inDesk:
- break;
- case inSysWindow:
- SystemClick(ev, target);
- break;
- case inContent:
- if (target != FrontWindow())
- SelectWindow(target);
- else if (target == gMAIN_WINDOW) {
- Point where;
- where = ev->where;
- SetPort(target);
- GlobalToLocal(&where);
- ClickWindowContents(target, where);
- }
- break;
- case inDrag:
- { Rect r = qd.screenBits.bounds;
- if (target != FrontWindow()) SelectWindow(target);
- SetPort(target);
- InsetRect(&r, 4, 4);
- r.top += 20;
- DragWindow(target, ev->where, &r);
- }
- break;
- case inGoAway:
- if (TrackGoAway(target, ev->where)) {
- if (target == gABOUTBOX) {
- DisposeDialog(gABOUTBOX);
- gABOUTBOX = NULL;
- } else PROGRAM_RUNNING = false;
- }
- break;
- case inMenuBar:
- { long mnRes;
- MenuPreflightCheck();
- if (HiWord(mnRes = MenuSelect(ev->where)) != 0)
- HandleMenuCommand(HiWord(mnRes), LoWord(mnRes));
- }
- break;
- }
- }
-
- /* SystemSwapTask can be called from anywhere in your application. basically it collects
- events and gives the system time to do its thing. */
- void SystemSwapTask(void) {
- EventRecord ev;
-
- /* get the next event */
- if (HAS_WAITNEXTEVENT) {
- if (!WaitNextEvent(everyEvent, &ev, 0, NULL)) ev.what = nullEvent;
- } else {
- if (!GetNextEvent(everyEvent, &ev)) ev.what = nullEvent;
- SystemTask();
- }
-
- AdjustCursor();
-
- if ((ev.what == keyDown || ev.what == autoKey) && (ev.modifiers & cmdKey) != 0) {
- long mnRes;
- MenuPreflightCheck();
- if (HiWord(mnRes = MenuKey((char) (ev.message & charCodeMask))) != 0)
- HandleMenuCommand(HiWord(mnRes), LoWord(mnRes));
- } else if (IsDialogEvent(&ev)) {
- DialogPtr theDialog;
- short itemHit;
- DialogSelect(&ev, &theDialog, &itemHit);
- } else if (ev.what == mouseDown) {
- HandleMouseDownEvent(&ev);
- } else if (ev.what == updateEvt) {
- WindowPtr wp;
- wp = (WindowPtr) ev.message;
- SetPort(wp);
- BeginUpdate(wp);
- DrawWindowContents(wp);
- EndUpdate(wp);
- } else if (ev.what == kHighLevelEvent) {
- if (HAS_APPLEEVENTS)
- AEProcessAppleEvent(&ev);
- } else if (ev.what == osEvt) {
- if (((ev.message >> 24) & 0x0FF) == suspendResumeMessage)
- PROGRAM_FRONT = (ev.message & resumeFlag) != 0;
- }
-
- }
-
-
- /* •••••••••••••••••••••• APPLE EVENTS •••••••••••••••••••••• */
-
- /* QuitEventHandler called for quit apple events. all we do here is set the running
- flag to false */
- pascal OSErr QuitEventHandler(const AppleEvent *appleEvt, AppleEvent* reply, long refcon) {
- DescType retType;
- Size actSize;
- OSErr err;
- err = AEGetAttributePtr(appleEvt, keyMissedKeywordAttr, typeWildCard, &retType, NULL, 0, &actSize);
- if (err == errAEDescNotFound) {
- PROGRAM_RUNNING = false;
- return noErr;
- } else if (err == noErr)
- return errAEEventNotHandled;
- else return err;
- }
-
-
- /* •••••••••••••••••••••• TEST FOR TRAPS •••••••••••••••••••••• */
-
- unsigned short NumToolboxTraps(void) {
- if (NGetTrapAddress(_InitGraf, ToolTrap) == NGetTrapAddress(0xAA6E, ToolTrap))
- return 0x0200;
- else return 0x0400;
- }
-
- TrapType FindTrapType(unsigned short theTrap) {
- if (theTrap & 0x0800)
- return ToolTrap;
- else return OSTrap;
- }
-
- Boolean TrapAvailable(unsigned short theTrap) {
- unsigned short localTrap = theTrap;
- TrapType tType = FindTrapType(localTrap);
- if ( tType == ToolTrap ) {
- localTrap &= 0x07FF;
- if ( localTrap >= NumToolboxTraps() )
- localTrap = _Unimplemented;
- }
- return NGetTrapAddress(localTrap, tType) != NGetTrapAddress(_Unimplemented, ToolTrap);
- }
-
-
- /* •••••••••••••••••••••• MAIN PROGRAM •••••••••••••••••••••• */
-
- void main(void) {
- OSErr err;
- long response;
-
- /* determine features of the machine */
- if (Gestalt(gestaltAppleEventsAttr, &response) != noErr) response = 0;
- HAS_APPLEEVENTS = ((response & (1<<gestaltAppleEventsPresent)) != 0);
- HAS_WAITNEXTEVENT = TrapAvailable(_WaitNextEvent);
-
- /* initialize the toolbox, etc.. */
- SetApplLimit( GetApplLimit() - (8*1024) );
- MaxApplZone();
- InitGraf(&qd.thePort);
- InitFonts();
- InitWindows();
- TEInit();
- InitMenus();
- InitDialogs(NULL);
- InitCursor();
- if (HAS_APPLEEVENTS) {
- err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
- NewAEEventHandlerProc(QuitEventHandler), 0, false);
- if (err != noErr) goto bail;
- }
- SetMenuBar(GetNewMBar(kMenuBarID));
- AddResMenu(GetMHandle(mApple), 'DRVR');
- DrawMenuBar();
- gMAIN_WINDOW = GetNewWindow(kMainWindID, NULL, (WindowPtr) (-1));
- SetPort(gMAIN_WINDOW);
- err = InitExample(gMAIN_WINDOW);
-
- /* set up some globals */
- PROGRAM_RUNNING = true;
- PROGRAM_FRONT = true;
-
- /* loop until PROGRAM_RUNNING is false */
- while (PROGRAM_RUNNING)
- SystemSwapTask();
-
- return;
-
- bail:
- Terminate(err);
- }
-
-
- /* end File BitMap.c */
-
-