home *** CD-ROM | disk | FTP | other *** search
/ develop, the CD; issue 1 / Apple_Develop_1989.bin / Compatibility / Sample.c < prev    next >
C/C++ Source or Header  |  1989-10-16  |  31KB  |  888 lines

  1. /*------------------------------------------------------------------------------
  2. #
  3. #    Apple Macintosh Developer Technical Support
  4. #
  5. #    MultiFinder-Aware Simple Sample Application
  6. #
  7. #    Sample
  8. #
  9. #    Sample.c    -    C Source
  10. #
  11. #    Copyright © 1989 Apple Computer, Inc.
  12. #    All rights reserved.
  13. #
  14. #    Versions:    
  15. #                1.00                08/88
  16. #                1.01                11/88
  17. #                1.02                04/89
  18. #
  19. #    Components:
  20. #                Sample.p            April 1, 1989
  21. #                Sample.c            April 1, 1989
  22. #                Sample.a            April 1, 1989
  23. #                Sample.inc1.a        April 1, 1989
  24. #                SampleMisc.a        April 1, 1989
  25. #                Sample.r            April 1, 1989
  26. #                Sample.h            April 1, 1989
  27. #                PSample.make        April 1, 1989
  28. #                CSample.make        April 1, 1989
  29. #                ASample.make        April 1, 1989
  30. #
  31. #    Sample is an example application that demonstrates how to
  32. #    initialize the commonly used toolbox managers, operate 
  33. #    successfully under MultiFinder, handle desk accessories, 
  34. #    and create, grow, and zoom windows.
  35. #
  36. #    It does not by any means demonstrate all the techniques 
  37. #    you need for a large application. In particular, Sample 
  38. #    does not cover exception handling, multiple windows/documents, 
  39. #    sophisticated memory management, printing, or undo. All of 
  40. #    these are vital parts of a normal full-sized application.
  41. #
  42. #    This application is an example of the form of a Macintosh 
  43. #    application; it is NOT a template. It is NOT intended to be 
  44. #    used as a foundation for the next world-class, best-selling, 
  45. #    600K application. A stick figure drawing of the human body may 
  46. #    be a good example of the form for a painting, but that does not 
  47. #    mean it should be used as the basis for the next Mona Lisa.
  48. #
  49. #    We recommend that you review this program or TESample before 
  50. #    beginning a new application.
  51. #
  52. ------------------------------------------------------------------------------*/
  53.  
  54.  
  55. /* Segmentation strategy:
  56.  
  57.    This program consists of three segments. Main contains most of the code,
  58.    including the MPW libraries, and the main program. Initialize contains
  59.    code that is only used once, during startup, and can be unloaded after the
  60.    program starts. %A5Init is automatically created by the Linker to initialize
  61.    globals for the MPW libraries and is unloaded right away. */
  62.  
  63.  
  64. /* SetPort strategy:
  65.  
  66.    Toolbox routines do not change the current port. In spite of this, in this
  67.    program we use a strategy of calling SetPort whenever we want to draw or
  68.    make calls which depend on the current port. This makes us less vulnerable
  69.    to bugs in other software which might alter the current port (such as the
  70.    bug (feature?) in many desk accessories which change the port on OpenDeskAcc).
  71.    Hopefully, this also makes the routines from this program more self-contained,
  72.    since they don't depend on the current port setting. */
  73.  
  74.  
  75. #include <Values.h>
  76. #include <Types.h>
  77. #include <Resources.h>
  78. #include <QuickDraw.h>
  79. #include <Fonts.h>
  80. #include <Events.h>
  81. #include <Windows.h>
  82. #include <Menus.h>
  83. #include <TextEdit.h>
  84. #include <Dialogs.h>
  85. #include <Desk.h>
  86. #include <ToolUtils.h>
  87. #include <Memory.h>
  88. #include <SegLoad.h>
  89. #include <Files.h>
  90. #include <OSUtils.h>
  91. #include <OSEvents.h>
  92. #include <DiskInit.h>
  93. #include <Packages.h>
  94. #include <Traps.h>
  95. #include <Sample.h>        /* bring in all the #defines for Sample */
  96.  
  97.  
  98. /* The "g" prefix is used to emphasize that a variable is global. */
  99.  
  100. /* GMac is used to hold the result of a SysEnvirons call. This makes
  101.    it convenient for any routine to check the environment. */
  102. SysEnvRec    gMac;                /* set up by Initialize */
  103.  
  104. /* GHasWaitNextEvent is set at startup, and tells whether the WaitNextEvent
  105.    trap is available. If it is false, we know that we must call GetNextEvent. */
  106. Boolean        gHasWaitNextEvent;    /* set up by Initialize */
  107.  
  108. /* GInBackground is maintained by our osEvent handling routines. Any part of
  109.    the program can check it to find out if it is currently in the background. */
  110. Boolean        gInBackground;        /* maintained by Initialize and DoEvent */
  111.  
  112.  
  113. /* The following globals are the state of the window. If we supported more than
  114.    one window, they would be attatched to each document, rather than globals. */
  115.  
  116. /* GStopped tells whether the stop light is currently on stop or go. */
  117. Boolean        gStopped;            /* maintained by Initialize and SetLight */
  118.  
  119. /* GStopRect and gGoRect are the rectangles of the two stop lights in the window. */
  120. Rect        gStopRect;            /* set up by Initialize */
  121. Rect        gGoRect;            /* set up by Initialize */
  122.  
  123.  
  124. /* Here are declarations for all of the C routines. In MPW 3.0 we can use
  125.    actual prototypes for parameter type checking. */
  126. void EventLoop( void );
  127. void DoEvent( EventRecord *event );
  128. void AdjustCursor( Point mouse, RgnHandle region );
  129. void GetGlobalMouse( Point *mouse );
  130. void DoUpdate( WindowPtr window );
  131. void DoActivate( WindowPtr window, Boolean becomingActive );
  132. void DoContentClick( WindowPtr window );
  133. void DrawWindow( WindowPtr window );
  134. void AdjustMenus( void );
  135. void DoMenuCommand( long menuResult );
  136. void SetLight( WindowPtr window, Boolean newStopped );
  137. Boolean DoCloseWindow( WindowPtr window );
  138. void Terminate( void );
  139. void Initialize(WindowPtr *win);
  140. Boolean GoGetRect( short rectID, Rect *theRect );
  141. void ForceEnvirons( void );
  142. Boolean IsAppWindow( WindowPtr window );
  143. Boolean IsDAWindow( WindowPtr window );
  144. Boolean TrapAvailable( short tNumber, TrapType tType );
  145. void AlertUser( void );
  146.  
  147.  
  148. /* Define HiWrd and LoWrd macros for efficiency. */
  149. #define HiWrd(aLong)    (((aLong) >> 16) & 0xFFFF)
  150. #define LoWrd(aLong)    ((aLong) & 0xFFFF)
  151.  
  152. /* Define TopLeft and BotRight macros for convenience. Notice the implicit
  153.    dependency on the ordering of fields within a Rect */
  154. #define TopLeft(aRect)    (* (Point *) &(aRect).top)
  155. #define BotRight(aRect)    (* (Point *) &(aRect).bottom)
  156.  
  157.  
  158. extern void _DataInit();
  159.  
  160. /* This routine is part of the MPW runtime library. This external
  161.    reference to it is done so that we can unload its segment, %A5Init. */
  162.  
  163.  
  164. #pragma segment Main
  165. main()
  166. {
  167.     WindowPtr    window;
  168.  
  169.     UnloadSeg((Ptr) _DataInit);        /* note that _DataInit must not be in Main! */
  170.     
  171.     /* 1.01 - call to ForceEnvirons removed */
  172.     
  173.     /*    If you have stack requirements that differ from the default,
  174.         then you could use SetApplLimit to increase StackSpace at 
  175.         this point, before calling MaxApplZone. */
  176.     MaxApplZone();                    /* expand the heap so code segments load at the top */
  177.  
  178.     Initialize(&window);                /* initialize the program */
  179.     UnloadSeg((Ptr) Initialize);    /* note that Initialize must not be in Main! */
  180.     InstallCVBL();                    /* demo our VBL task */
  181.     if (window)
  182.         ShowWindow (window);        /* show traffic light window */
  183.     EventLoop();                    /* call the main event loop */
  184. }
  185.  
  186.  
  187. /*    Get events forever, and handle them by calling DoEvent.
  188.     Get the events by calling WaitNextEvent, if it's available, otherwise
  189.     by calling GetNextEvent. Also call AdjustCursor each time through the loop. */
  190.  
  191. #pragma segment Main
  192. void EventLoop()
  193. {
  194.     RgnHandle    cursorRgn;
  195.     Boolean        gotEvent;
  196.     EventRecord    event;
  197.     Point        mouse;
  198.  
  199.     cursorRgn = NewRgn();            /* we'll pass WNE an empty region the 1st time thru */
  200.     do {
  201.         /* use WNE if it is available */
  202.         if ( gHasWaitNextEvent ) {
  203.             GetGlobalMouse(&mouse);
  204.             AdjustCursor(mouse, cursorRgn);
  205.             gotEvent = WaitNextEvent(everyEvent, &event, MAXLONG, cursorRgn);
  206.         }
  207.         else {
  208.             SystemTask();
  209.             gotEvent = GetNextEvent(everyEvent, &event);
  210.         }
  211.         if ( gotEvent ) {
  212.             /* make sure we have the right cursor before handling the event */
  213.             AdjustCursor(event.where, cursorRgn);
  214.             DoEvent(&event);
  215.         }
  216.         /*    If you are using modeless dialogs that have editText items,
  217.             you will want to call IsDialogEvent to give the caret a chance
  218.             to blink, even if WNE/GNE returned FALSE. However, check FrontWindow
  219.             for a non-NIL value before calling IsDialogEvent. */
  220.     } while ( true );    /* loop forever; we quit via ExitToShell */
  221. } /*EventLoop*/
  222.  
  223.  
  224. /* Do the right thing for an event. Determine what kind of event it is, and call
  225.  the appropriate routines. */
  226.  
  227. #pragma segment Main
  228. void DoEvent(event)
  229.     EventRecord    *event;
  230. {
  231.     short        part, err;
  232.     WindowPtr    window;
  233.     Boolean        hit;
  234.     char        key;
  235.     Point        aPoint;
  236.  
  237.     switch ( event->what ) {
  238.         case mouseDown:
  239.             part = FindWindow(event->where, &window);
  240.             switch ( part ) {
  241.                 case inMenuBar:                /* process a mouse menu command (if any) */
  242.                     AdjustMenu