home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / mac / developm / scnote / sample.001 / SampleMisc.a < prev    next >
Text File  |  1989-06-01  |  35KB  |  904 lines

  1. *
  2. *    Apple Macintosh Developer Technical Support
  3. *
  4. *    MultiFinder-Aware Simple Sample Application
  5. *
  6. *    Sample
  7. *
  8. *    SampleMisc.a    -    Assembler Source
  9. *
  10. *    Copyright ⌐ 1989 Apple Computer, Inc.
  11. *    All rights reserved.
  12. *
  13. *    Versions:    
  14. *        1.00            08/88
  15. *        1.01            11/88
  16. *        1.02            04/89
  17. *        1.03            06/89
  18. *
  19. *    Components:
  20. *        Sample.p        June 1, 1989
  21. *        Sample.c        June 1, 1989
  22. *        Sample.a        June 1, 1989
  23. *        Sample.inc1.a        June 1, 1989
  24. *        SampleMisc.a        June 1, 1989
  25. *        Sample.r        June 1, 1989
  26. *        Sample.h        June 1, 1989
  27. *        PSample.make        June 1, 1989
  28. *        CSample.make        June 1, 1989
  29. *        ASample.make        June 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. * -------------- INCLUDES SECTION ----------------
  54. * ================================================
  55.  
  56.     PRINT    PUSH,OFF            ; don't print any of this stuff
  57.  
  58.     INCLUDE    'ToolEqu.a'
  59.     INCLUDE    'Traps.a'
  60.     INCLUDE    'PackMacs.a'
  61.     INCLUDE    'QuickEqu.a'
  62.     INCLUDE    'SysEqu.a'
  63.     INCLUDE    'Sample.inc1.a'            ; all our macros and data templates
  64.  
  65.     PRINT    POP                ; restore the PRINT options
  66.  
  67.  
  68. * ================================================
  69. * -----------  DATA STORAGE USAGE  ---------------
  70. * ================================================
  71. * Here we will IMPORT the data that is being from the
  72. * DATA STORAGE ALLOCATION section of ASample.a.  By IMPORTing them
  73. * at this point, they will be accessible by this entire source file.
  74. * The symbol is IMPORTed and associated with the original template
  75. * as defined in the ASample.inc1.a file.  This allows us to use
  76. * the identifiers in the template.
  77.  
  78.         IMPORT    QD:QDGlobals
  79.         IMPORT    G:AppGlobals
  80.  
  81.  
  82. * ================================================
  83. * FUNCTION TrapAvailable(tNumber: INTEGER): BOOLEAN;
  84. * ================================================
  85. * Check to see if a given trap is implemented. This is only used by the
  86. * Initialize routine in this program, so we put it in the Initialize segment.
  87. * The recommended approach to see if a trap is implemented is to see if
  88. * the address of the trap routine is the same as the address of the
  89. * Unimplemented trap. Needs to be called after call to _SysEnvirons so that it can
  90. * check if a ToolTrap is out of range of a pre-Mac II ROM.  This routine
  91. * assumes we're running on 128k ROMs. It also requires the entire trap
  92. * word so that it knows if it is a ToolTrap or an OSTrap.
  93.  
  94.         SEG    'Initialize'        ; case sensitive
  95. TrapAvailable    FUNC    EXPORT            ; any source file can use this routine
  96.  
  97. StackFrame    RECORD    {A6Link},DECR        ; build a stack frame record
  98. Result        DS.W    1            ; function's result returned to caller
  99. ParamBegin    EQU    *            ; start parameters after this point
  100. tNumber        DS.W    1            ; the trap number passed by caller
  101. ParamSize    EQU    ParamBegin-*        ; size of all the passed parameters
  102. RetAddr     DS.L    1            ; place holder for return address
  103. A6Link        DS.L    1            ; place holder for A6 link
  104. TrapAddress    DS.L    1            ; local copy of trap address
  105. LocalSize    EQU     *            ; size of all the local variables
  106.         ENDR
  107.  
  108.         WITH    StackFrame        ; cover our local stack frame
  109.         LINK    A6,#LocalSize        ; allocate our local stack frame
  110.  
  111.         MOVE.W    #False,Result(A6)    ; initialize function's result
  112.  
  113.         MOVE.W    tNumber(A6),D0        ; get trap word into D0
  114.         BTST    #ToolTrapBit,D0        ; test if number is Tool trap
  115.         BEQ.S    GetOSTrap        ; off means a new OS trap number
  116.         
  117.         MOVE.W    G.Mac.machineType,D1    ; get the machine type we're running
  118.         CMPI.W    #envMachUnknown,D1    ; are we on a future machine?
  119.         BEQ.S    GetToolTrap        ; yes, go ahead and test for a new Tool trap
  120.         
  121.         CMPI.W    #envMacII,D1        ; are we on a Mac II or better?
  122.         BGE.S    GetToolTrap        ; yes, go ahead and test for a new Tool trap
  123.  
  124. * ------------- TEST FOR EXCEEDING TRAP TABLE -------------
  125. * At this point we know we're on a Mac 512E, Plus, or SE and need to
  126. * test the trap number for being in the range of < $0200
  127.  
  128.         AND.W    #$03FF,D0        ; mask off the ToolTrap bits
  129.         CMPI.W    #$01FF,D0        ; is this trap in our trap table?
  130.         BLE.S    GetToolTrap        ; yes, go ahead and test for a new Tool trap
  131.         BRA.S    Exit            ; no, then this trap cannot be present
  132.         
  133. * ------------- TEST FOR NEW TOOL TRAP -------------
  134.  
  135. GetToolTrap    _GetTrapAddress ,NewTool    ; NewTool trap macro, trap is in D0
  136.         MOVE.L    A0,TrapAddress(A6)    ; save a copy of the trap address
  137.         BRA.S    TestUnimp        ; test against Unimplemented trap
  138.         
  139. * ------------- TEST FOR NEW OS TRAP -------------
  140.  
  141. GetOSTrap    _GetTrapAddress ,NewOS        ; NewOS trap macro, trap is in D0
  142.         MOVE.L    A0,TrapAddress(A6)    ; save a copy of the trap address
  143. TestUnimp    MOVE.W    #Unimplemented,D0    ; get address of Unimplemented trap
  144.         _GetTrapAddress
  145.         CMPA.L    TrapAddress(A6),A0    ; see if trap is implemented
  146.         BEQ.S    Exit            ; nope, they're the same
  147.         MOVE.W    #True,Result(A6)    ; yes, we've got the trap
  148.  
  149. Exit        UNLK    A6            ; destroy the link
  150.         MOVEA.L    (SP)+,A0        ; pull off the return address
  151.         ADDA.L    #ParamSize,SP        ; strip all of the caller's parameters
  152.         JMP    (A0)            ; return to the caller
  153.  
  154.         DbgInfo    TrapAval        ; this name will appear in the debugger
  155.         ENDF
  156.  
  157. * ================================================
  158. * FUNCTION GoGetRect(rectID: INTEGER; VAR theRect: Rect) : BOOLEAN;
  159. * ================================================
  160. * This utility loads the global rectangles that are used by the window
  161. * drawing routines. It shows how the resource manager can be used to hold
  162. * values in a convenient manner. These values are then easily altered without
  163. * having to re-compile the source code. GoGetRect will return a BOOLEAN that
  164. * indicates if it was successful in getting the rectangle.
  165.  
  166. * A0 is being used for resource handle.
  167.  
  168.         SEG    'Initialize'        ; case sensitive
  169. GoGetRect    FUNC    EXPORT            ; any source file can use this routine
  170.  
  171. StackFrame    RECORD    {A6Link},DECR        ; build a stack frame record
  172. Result        DS.W    1            ; function's result returned to caller
  173. ParamBegin    EQU    *            ; start parameters after this point
  174. RectID        DS.W    1            ; resource ID of rect passed by caller
  175. TheRect        DS.L    1            ; the rect's pointer passed by caller
  176. ParamSize    EQU    ParamBegin-*        ; size of all the passed parameters
  177. RetAddr     DS.L    1            ; place holder for return address
  178. A6Link        DS.L    1            ; place holder for A6 link
  179. LocalSize    EQU     *            ; size of all the local variables
  180.         ENDR
  181.  
  182.         WITH    StackFrame        ; cover our local stack frame
  183.         LINK    A6,#LocalSize        ; allocate our local stack frame
  184.  
  185.         MOVE.W    #False,Result(A6)    ; initialize function's result
  186.  
  187.         CLR.L    -(SP)            ; create space for result
  188.         MOVE.L    #'RECT',-(SP)
  189.         MOVE.W    RectID(A6),-(SP)    ; get the stop light's rect
  190.         _GetResource
  191.         MOVEA.L    (SP)+,A0        ; handle to RECT resource in A0
  192.         CMPA.L    #NIL,A0            ; test for NIL handle
  193.         BEQ.S    Exit            ; didn't get resource, exit this procedure
  194.  
  195.  
  196. * -------- COPY THE RESOURCE TO THE RECT --------
  197.  
  198.         MOVE.W    #True,Result(A6)    ; we got the resource, return true
  199.         MOVEA.L    (A0),A0            ; pointer to RECT resource in A0
  200.         MOVEA.L    TheRect(A6),A1        ; pointer to the dest. RECT in A1
  201.         MOVE.L    topLeft(A0),topLeft(A1)    ; copy to the rect passed to us
  202.         MOVE.L    botRight(A0),botRight(A1)
  203.  
  204. Exit        UNLK    A6            ; destroy the link
  205.         MOVEA.L    (SP)+,A0        ; pull off the return address
  206.         ADDA.L    #ParamSize,SP        ; strip all of the caller's parameters
  207.         JMP    (A0)            ; return to the caller
  208.  
  209.         DbgInfo    GetRect            ; this name will appear in the debugger
  210.         ENDF
  211.  
  212. * ================================================
  213. * FUNCTION IsDAWindow(window: WindowPtr): BOOLEAN;
  214. * ================================================
  215. * Check if a window belongs to a desk accessory.  DA window has a negitive kind.
  216.  
  217.         SEG    'Main'
  218. IsDAWindow    FUNC    EXPORT            ; any source file can use this routine
  219.  
  220. StackFrame    RECORD    {A6Link},DECR        ; build a stack frame record
  221. Result        DS.W    1            ; function's result returned to caller
  222. ParamBegin    EQU    *            ; start parameters after this point
  223. TheWindow    DS.L    1            ; a window's pointer passed by caller
  224. ParamSize    EQU    ParamBegin-*        ; size of all the passed parameters
  225. RetAddr     DS.L    1            ; place holder for return address
  226. A6Link        DS.L    1            ; place holder for A6 link
  227. LocalSize    EQU     *            ; size of all the local variables
  228.         ENDR
  229.  
  230.         WITH    StackFrame        ; cover our local stack frame
  231.         LINK    A6,#LocalSize        ; allocate our local stack frame
  232.  
  233.         MOVE.W    #False,Result(A6)    ; first, initialize the result
  234.         CMPI.L    #NIL,TheWindow(A6)    ; valid pointer?
  235.         BEQ.S    Exit            ; it was NIL, look out!
  236.  
  237.         MOVEA.L    TheWindow(A6),A0    ; get the window pointer
  238.         MOVE.W    WindowKind(A0),D0    ; what kind of window was it?
  239.         BPL.S    Exit            ; DA windows are negitive
  240.  
  241.         MOVE.W    #True,Result(A6)    ; return true to the caller
  242. Exit        UNLK    A6            ; destroy the link
  243.         MOVEA.L    (SP)+,A0        ; pull off the return address
  244.         ADDA.L    #ParamSize,SP        ; strip all of the caller's parameters
  245.         JMP    (A0)            ; return to the caller
  246.  
  247.         DbgInfo    IsDAWind        ; this name will appear in the debugger
  248.         ENDF
  249.  
  250. * ================================================
  251. * FUNCTION IsAppWindow(window: WindowPtr): BOOLEAN;
  252. * ================================================
  253. * Check to see if a window belongs to the application. If the window pointer
  254. * passed was NIL, then it could not be an application window. WindowKinds
  255. * that are negative belong to the system and windowKinds less than userKind
  256. * are reserved by Apple except for windowKinds equal to dialogKind, which
  257. * means it is a dialog.
  258. * In order to reduce the chance of accidentally treating some window
  259. * as an AppWindow that shouldn't be, we'll only return true if the windowkind
  260. * is userKind. If you add different kinds of windows to Sample you'll need
  261. * to change how this all works.
  262.  
  263.         SEG    'Main'
  264. IsAppWindow    FUNC    EXPORT            ; any source file can use this routine
  265.  
  266. StackFrame    RECORD    {A6Link},DECR        ; build a stack frame record
  267. Result        DS.W    1            ; function's result returned to caller
  268. ParamBegin    EQU    *            ; start parameters after this point
  269. TheWindow    DS.L    1            ; a window's pointer passed by caller
  270. ParamSize    EQU    ParamBegin-*        ; size of all the passed parameters
  271. RetAddr     DS.L    1            ; place holder for return address
  272. A6Link        DS.L    1            ; place holder for A6 link
  273. LocalSize    EQU     *            ; size of all the local variables
  274.         ENDR
  275.  
  276.         WITH    StackFrame        ; cover our local stack frame
  277.         LINK    A6,#LocalSize        ; allocate our local stack frame
  278.  
  279.         MOVE.W    #False,Result(A6)    ; first, initialize the result
  280.         CMPI.L    #NIL,TheWindow(A6)    ; valid pointer?
  281.         BEQ.S    Exit            ; it was NIL, look out!
  282.  
  283.         MOVEA.L    TheWindow(A6),A0    ; get the window pointer
  284.         MOVE.W    WindowKind(A0),D0    ; what kind of window was it?
  285.         CMPI.W    #UserKind,D0        ; was it an application window?
  286.         BNE.S    Exit            ; no, result is going to be false
  287.  
  288.         MOVE.W    #True,Result(A6)    ; return true to the caller
  289.  
  290. Exit        UNLK    A6            ; destroy the link
  291.         MOVEA.L    (SP)+,A0        ; pull off the return address
  292.         ADDA.L    #ParamSize,SP        ; strip all of the caller's parameters
  293.         JMP    (A0)            ; return to the caller
  294.  
  295.         DbgInfo    IsAppWin        ; this name will appear in the debugger
  296.         ENDF
  297.  
  298. * ================================================
  299. * PROCEDURE AlertUser;
  300. * ================================================
  301. * Display an alert that tells the user an error occurred, then exit the program.
  302. * This routine is used as an ultimate bail-out for serious errors that prohibit
  303. * the continuation of the application. Errors that do not require the termination
  304. * of the application should be handled in a different manner. Error checking and
  305. * reporting has a place even in the simplest application. For simplicity, the alert
  306. * displayed here only says that an error occurred, but not what it was. There are
  307. * various methods available for being more specific.
  308.  
  309.         SEG    'Main'        ; case sensitive
  310. AlertUser    PROC    EXPORT            ; any source file can use this routine
  311.  
  312. StackFrame    RECORD    {A6Link},DECR        ; build a stack frame record
  313. ParamBegin    EQU    *            ; start parameters after this point
  314. ParamSize    EQU    ParamBegin-*        ; size of all the passed parameters
  315. RetAddr     DS.L    1            ; place holder for return address
  316. A6Link        DS.L    1            ; place holder for A6 link
  317. LocalSize    EQU     *            ; size of all the local variables
  318.         ENDR
  319.  
  320.         WITH    StackFrame        ; cover our local stack frame
  321.         LINK    A6,#LocalSize        ; allocate our local stack frame
  322.  
  323.         CLR.W    -(SP)            ; space for result of Alert
  324.         MOVE.W    #rUserAlert,-(SP)    ; resource for alert dialog
  325.         CLR.L    -(SP)            ; no filter procedure used here
  326.         _Alert                ; read the resource and display it
  327.         MOVE.W    (SP)+,D0        ; I don't care which item is was
  328.         _ExitToShell            ; we're out of here, no error recovery
  329.  
  330. Exit        UNLK    A6            ; destroy the link
  331.         MOVEA.L    (SP)+,A0        ; pull off the return address
  332.         ADDA.L    #ParamSize,SP        ; strip all of the caller's parameters
  333.         JMP    (A0)            ; return to the caller
  334.  
  335.         DbgInfo    AlrtUser        ; this name will appear in the debugger
  336.         ENDP
  337.  
  338. * ================================================
  339. * FUNCTION DoCloseWindow(window: WindowPtr) : BOOLEAN;
  340. * ================================================
  341. * At this point, if there was a document associated with a window, you could
  342. * do any document saving processing if it is 'dirty'.  DoCloseWindow would
  343. * return TRUE if the window actually closes, i.e., the user does not cancel
  344. * from a save dialog. This result is handy when the user quits an application,
  345. * but then cancels a save of a document associated with a window. We also added
  346. * code to close the application window since otherwise, the termination routines
  347. * would never stop looping, waiting for FrontWindow to return NIL.
  348.  
  349.          SEG    'Main'            ; case sensitive
  350. DoCloseWindow    FUNC    EXPORT            ; any source file can use this routine
  351.  
  352. StackFrame    RECORD    {A6Link},DECR        ; build a stack frame record
  353. Result        DS.W    1            ; function's result returned to caller
  354. ParamBegin    EQU    *            ; start parameters after this point
  355. WindowPtr    DS.L    1            ; passed window pointer parameter
  356. ParamSize    EQU    ParamBegin-*        ; size of all the passed parameters
  357. RetAddr     DS.L    1            ; place holder for return address
  358. A6Link        DS.L    1            ; place holder for A6 link
  359. LocalSize    EQU     *            ; size of all the local variables
  360.         ENDR
  361.  
  362.         WITH    StackFrame        ; cover our local stack frame
  363.         LINK    A6,#LocalSize        ; allocate our local stack frame
  364.  
  365.         MOVE.W    #True,Result(A6);    ; initialize the function's result
  366.  
  367.         CLR.W    -(SP)            ; space for result of IsDAWindow
  368.         MOVE.L    WindowPtr(A6),-(SP)    ; pass the window pointer
  369.         BSR    IsDAWindow
  370.         MOVE.W    (SP)+,D0        ; result of IsDAWindow
  371.         CMPI.W    #True,D0
  372.         BNE.S    @1            ; this wasn't a DA window
  373.  
  374.         MOVEA.L    WindowPtr(A6),A0    ; get window pointer
  375.         MOVE.W    WindowKind(A0),-(SP)    ; pass the refNum of DA
  376.         _CloseDeskAcc
  377.         BRA.S    Exit            ; all done
  378.  
  379. @1        CLR.W    -(SP)            ; space for result of IsAppWindow
  380.         MOVE.L    WindowPtr(A6),-(SP)    ; pass a the window pointer
  381.         BSR    IsAppWindow
  382.         MOVE.W    (SP)+,D0        ; result of IsAppWindow
  383.         CMPI.W    #True,D0
  384.         BNE.S    Exit            ; it wasn't our application's window
  385.  
  386.         MOVE.L    WindowPtr(A6),-(SP)    ; close window, it shouldn't be a dialog
  387.         _CloseWindow            ; close the application window
  388.  
  389. Exit        UNLK    A6            ; destroy the link
  390.         MOVEA.L    (SP)+,A0        ; pull off the return address
  391.         ADDA.L    #ParamSize,SP        ; strip all of the caller's parameters
  392.         JMP    (A0)            ; return to the caller
  393.  
  394.         DbgInfo    ClosWind        ; this name will appear in the debugger
  395.         ENDF
  396.  
  397. * ================================================
  398. * PROCEDURE Terminate;
  399. * ================================================
  400. * Clean up the application and exit. We close all of the windows so that
  401. * they can update their documents, if any.  We don't have much to do here.
  402. * Just close our windows and then exit.  If we find out that a Cancel has
  403. * occurred (DoCloseWindow will return False) we won't exit to the shell,
  404. * but will simply exit this procedure.
  405.  
  406.         SEG    'Main'            ; case sensitive
  407. Terminate    PROC    EXPORT
  408.  
  409. StackFrame    RECORD    {A6Link},DECR        ; build a stack frame record
  410. ParamBegin    EQU    *            ; start parameters after this point
  411. ParamSize    EQU    ParamBegin-*        ; size of all the passed parameters
  412. RetAddr     DS.L    1            ; place holder for return address
  413. A6Link        DS.L    1            ; place holder for A6 link
  414. WindowPtr    DS.L    1            ; local variable for a window pointer
  415. Closed        DS.W    1            ; local variable for looping
  416. LocalSize    EQU     *            ; size of all the local variables
  417.         ENDR
  418.  
  419.         IMPORT    DoCloseWindow
  420.  
  421.         WITH    StackFrame        ; cover our local stack frame
  422.         LINK    A6,#LocalSize        ; allocate our local stack frame
  423.  
  424.         MOVE.W    #True,Closed(A6)    ; initialize local variable
  425.  
  426. Loop        CLR.L    -(SP)            ; space for front window pointer
  427.         _FrontWindow
  428.         MOVE.L    (SP)+,WindowPtr(A6)    ; get the front window pointer
  429.         CMPI.L    #NIL,WindowPtr(A6)    ; is there a front window?
  430.         BEQ.S    @1            ; there are no more windows
  431.  
  432.         CLR.W    -(SP)            ; space for result of DoCloseWindow
  433.         MOVE.L    WindowPtr(A6),-(SP)    ; pass the window pointer
  434.         BSR    DoCloseWindow        ; close all our windows
  435.         MOVE.W    (SP)+,Closed(A6)    ; get result of DoCloseWindow
  436.         CMPI.W    #True,Closed(A6)    ; what's the result of DoCloseWindow?
  437.         BNE.S    Exit            ; user didn't want to close that window
  438.  
  439.         BRA.S    Loop            ; loop again and close the next window
  440.  
  441. @1        CMPI.W    #True,Closed(A6)    ; should we really terminate?
  442.         BNE.S    Exit            ; no, exit this procedure
  443.  
  444.         _ExitToShell            ; we're done, let's get out of here
  445.  
  446. Exit        UNLK    A6            ; destroy the link
  447.         MOVEA.L    (SP)+,A0        ; pull off the return address
  448.         ADDA.L    #ParamSize,SP        ; strip all of the caller's parameters
  449.         JMP    (A0)            ; return to the caller
  450.  
  451.         DbgInfo    Terminat        ; this name will appear in the debugger
  452.         ENDP
  453.  
  454. * ================================================
  455. * PROCEDURE SetLight(window: WindowPtr; newStopped: BOOLEAN);
  456. * ================================================
  457. * Change the setting of the light and force an update event.
  458. * newStopped is the state of the stop light the user is requesting.
  459.  
  460.         SEG    'Main'            ; case sensitive
  461. SetLight    PROC    EXPORT            ; any source file can use this routine
  462.  
  463. StackFrame    RECORD    {A6Link},DECR        ; build a stack frame record
  464. ParamBegin    EQU    *            ; start parameters after this point
  465. WindowPtr    DS.L    1            ; passed parameter of the window pointer
  466. newStopped    DS.W    1            ; test value passed by caller
  467. ParamSize    EQU    ParamBegin-*        ; size of all the passed parameters
  468. RetAddr     DS.L    1            ; place holder for return address
  469. A6Link        DS.L    1            ; place holder for A6 link
  470. LocalSize    EQU     *            ; size of all the local variables
  471.         ENDR
  472.  
  473.         WITH    StackFrame        ; cover our local stack frame
  474.         LINK    A6,#LocalSize        ; allocate our local stack frame
  475.  
  476.         MOVE.W    G.Stopped,D0        ; get state of stop light
  477.         CMP.W    newStopped(A6),D0    ; compare to the new state
  478.         BEQ.S    Exit            ; they're the same, stupid user!
  479.  
  480.         MOVE.W    newStopped(A6),G.Stopped ; set global to the new state
  481.         MOVE.L    WindowPtr(A6),-(SP)
  482.         _SetPort            ; set the port to us
  483.         MOVEA.L    WindowPtr(A6),A0    ; force update event for window
  484.         PEA    portRect(A0)        ; invalidate entire window
  485.         _InvalRect
  486.  
  487. Exit        UNLK    A6            ; destroy the link
  488.         MOVEA.L    (SP)+,A0        ; pull off the return address
  489.         ADDA.L    #ParamSize,SP        ; strip all of the caller's parameters
  490.         JMP    (A0)            ; return to the caller
  491.  
  492.         DbgInfo    SetLight        ; this name will appear in the debugger
  493.         ENDP
  494.  
  495. * ================================================
  496. * PROCEDURE AdjustMenus;
  497. * ================================================
  498. * Enable and disable menus based on the current state.  The user can only select
  499. * enabled menu items. We set up all the menu items before calling MenuSelect or
  500. * MenuKey, since these are the only times that a menu item can be selected. Note
  501. * that MenuSelect is also the only time the user will see menu items. This
  502. * approach to deciding what enable/disable state a menu item has the advantage
  503. * of concentrating all the decision making in one routine, as opposed to being
  504. * spread throughout the application.  Other application designs may take a
  505. * different approach that are just as valid.
  506.  
  507.         SEG    'Main'            ; case sensitive
  508. AdjustMenus    PROC    EXPORT            ; any source file can use this routine
  509.  
  510. StackFrame    RECORD    {A6Link},DECR        ; build a stack frame record
  511. ParamBegin    EQU    *            ; start parameters after this point
  512. ParamSize    EQU    ParamBegin-*        ; size of all the passed parameters
  513. RetAddr     DS.L    1            ; place holder for return address
  514. A6Link        DS.L    1            ; place holder for A6 link
  515. FrontMost    DS.L    1            ; local copy of the front window
  516. Menu        DS.L    1            ; local copy of the menu handle
  517. LocalSize    EQU     *            ; size of all the local variables
  518.         ENDR
  519.  
  520.         WITH    StackFrame        ; cover our local stack frame
  521.         LINK    A6,#LocalSize        ; allocate our local stack frame
  522.  
  523.         CLR.L    -(SP)            ; space for result
  524.         _FrontWindow
  525.         MOVE.L    (SP)+,FrontMost(A6)    ; save the front window
  526.  
  527. * ------------- ADJUST THE FILE MENU -------------
  528. AdjustFile
  529.         CLR.L    -(SP)            ; space for result
  530.         MOVE.W    #FileMenu,-(SP)        ; get the File menu handle
  531.         _GetMHandle
  532.         MOVE.L    (SP)+,Menu(A6)        ; save the menu handle
  533.         CLR.W    -(SP)            ; space for result
  534.         MOVE.L    FrontMost(A6),-(SP)
  535.         BSR    IsDAWindow
  536.         MOVE.W    (SP)+,D0        ; get the result of the function
  537.         CMPI.W    #True,D0        ; was it the DA window?
  538.         BNE.S    @1            ; no, then disable the close item
  539.  
  540.         MOVE.L    Menu(A6),-(SP)        ; it was an application window
  541.         MOVE.W    #CloseItem,-(SP)
  542.         _EnableItem            ; enable the close for DAs only
  543.         BRA.S    AdjustEdit
  544.  
  545. @1        MOVE.L    Menu(A6),-(SP)        ; it was not a DA window
  546.         MOVE.W    #CloseItem,-(SP)
  547.         _DisableItem            ; disable close for all others
  548.  
  549. * ------------- ADJUST THE EDIT MENU -------------
  550. AdjustEdit
  551.         CLR.L    -(SP)            ; space for result
  552.         MOVE.W    #EditMenu,-(SP)        ; get the Edit menu handle
  553.         _GetMHandle
  554.         MOVE.L    (SP)+,Menu(A6)        ; save the menu handle
  555.         CLR.W    -(SP)            ; space for result
  556.         MOVE.L    FrontMost(A6),-(SP)
  557.         BSR    IsDAWindow
  558.         MOVE.W    (SP)+,D0        ; get the result of the function
  559.         CMPI.W    #True,D0        ; was it the DA window?
  560.         BNE.S    @2            ; no, disable the edit menu
  561.  
  562.         MOVE.L    Menu(A6),-(SP)        ; it was for a DA window
  563.         MOVE.W    #CutItem,-(SP)
  564.         _EnableItem            ; enable the Cut
  565.         MOVE.L    Menu(A6),-(SP)
  566.         MOVE.W    #CopyItem,-(SP)
  567.         _EnableItem            ; enable the Copy
  568.         MOVE.L    Menu(A6),-(SP)
  569.         MOVE.W    #PasteItem,-(SP)
  570.         _EnableItem            ; enable the Paste
  571.         MOVE.L    Menu(A6),-(SP)
  572.         MOVE.W    #ClearItem,-(SP)
  573.         _EnableItem            ; enable the Clear
  574.         BRA.S    AdjustLight        ; done with the edit menu
  575.  
  576. @2        MOVE.L    Menu(A6),-(SP)        ; disable the edit menu
  577.         MOVE.W    #UndoItem,-(SP)
  578.         _DisableItem            ; disable the Undo
  579.         MOVE.L    Menu(A6),-(SP)
  580.         MOVE.W    #CutItem,-(SP)
  581.         _DisableItem            ; disable the Cut
  582.         MOVE.L    Menu(A6),-(SP)
  583.         MOVE.W    #CopyItem,-(SP)
  584.         _DisableItem            ; disable the Copy
  585.         MOVE.L    Menu(A6),-(SP)
  586.         MOVE.W    #PasteItem,-(SP)
  587.         _DisableItem            ; disable the Paste
  588.         MOVE.L    Menu(A6),-(SP)
  589.         MOVE.W    #ClearItem,-(SP)
  590.         _DisableItem            ; disable the Clear
  591.  
  592. * ------------- ADJUST THE LIGHT MENU -------------
  593. AdjustLight
  594.         CLR.L    -(SP)            ; space for result
  595.         MOVE.W    #LightMenu,-(SP)    ; get the Edit menu handle
  596.         _GetMHandle
  597.         MOVE.L    (SP)+,Menu(A6)        ; save the menu handle
  598.         CLR.W    -(SP)            ; space for result
  599.         MOVE.L    FrontMost(A6),-(SP)    ; the front window
  600.         BSR    IsAppWindow
  601.         MOVE.W    (SP)+,D3        ; save the result of the function
  602.         CMPI.W    #True,D3        ; was our window in front?
  603.         BNE.S    @3            ; no, disable the menu items
  604.  
  605.         MOVE.L    Menu(A6),-(SP)        ; enable the light menu
  606.         MOVE.W    #StopItem,-(SP)
  607.         _EnableItem            ; enable the stop
  608.         MOVE.L    Menu(A6),-(SP)
  609.         MOVE.W    #GoItem,-(SP)
  610.         _EnableItem            ; enable the go for our window
  611.         BRA.S    @4            ; now check the menu items
  612.  
  613. @3        MOVE.L    Menu(A6),-(SP)        ; disable the light menu
  614.         MOVE.W    #StopItem,-(SP)
  615.         _DisableItem            ; disable the stop
  616.         MOVE.L    Menu(A6),-(SP)
  617.         MOVE.W    #GoItem,-(SP)
  618.         _DisableItem            ; disable the go
  619.         BRA.S    Exit            ; nothing to check, get out of here
  620.  
  621. @4        MOVE.W    G.Stopped,D0        ; get the current state of the light
  622.         CMPI.W    #True,D0        ; is the stop light on?
  623.         BNE.S    @5            ; no, the green light is on
  624.  
  625.         MOVE.L    Menu(A6),-(SP)        ; set menu to red light = on
  626.         MOVE.W    #StopItem,-(SP)
  627.         MOVE.W    #True,-(SP)
  628.         _CheckItem            ; check the StopItem in the menu
  629.         MOVE.L    Menu(A6),-(SP)
  630.         MOVE.W    #GoItem,-(SP)
  631.         MOVE.W    #False,-(SP)
  632.         _CheckItem            ; un-check the GoItem in the menu
  633.         BRA.S    Exit            ; now we're done, get out of here
  634.  
  635. @5        MOVE.L    Menu(A6),-(SP)        ; set menu to green light = on
  636.         MOVE.W    #StopItem,-(SP)
  637.         MOVE.W    #False,-(SP)
  638.         _CheckItem            ; un-check the StopItem in the menu
  639.         MOVE.L    Menu(A6),-(SP)
  640.         MOVE.W    #GoItem,-(SP)
  641.         MOVE.W    #True,-(SP)
  642.         _CheckItem            ; check the GoItem in the menu
  643.  
  644. Exit        UNLK    A6            ; destroy the link
  645.         MOVEA.L    (SP)+,A0        ; pull off the return address
  646.         ADDA.L    #ParamSize,SP        ; strip all of the caller's parameters
  647.         JMP    (A0)            ; return to the caller
  648.  
  649.         DbgInfo    AdjstMnu        ; this name will appear in the debugger
  650.         ENDP
  651.  
  652. * ================================================
  653. * PROCEDURE DrawWindow(window: WindowPtr);
  654. * ================================================
  655. * Draw the contents of the application's window. We do some drawing in color,
  656. * using Classic QuickDraw's color capabilities. This will be black and white on
  657. * old machines, but color on color machines. The window's visRgn has been set by
  658. * the Update routine to cause drawing only where it needs to be done.
  659.  
  660.         SEG    'Main'            ; case sensitive
  661. DrawWindow    PROC    EXPORT            ; any source file can use this routine
  662.  
  663. StackFrame    RECORD    {A6Link},DECR        ; build a stack frame record
  664. ParamBegin    EQU    *            ; start parameters after this point
  665. WindowPtr    DS.L    1            ; passed parameter of the window pointer
  666. ParamSize    EQU    ParamBegin-*        ; size of all the passed parameters
  667. RetAddr     DS.L    1            ; place holder for return address
  668. A6Link        DS.L    1            ; place holder for A6 link
  669. LocalSize    EQU     *            ; size of all the local variables
  670.         ENDR
  671.  
  672.         WITH    StackFrame        ; cover our local stack frame
  673.         LINK    A6,#LocalSize        ; allocate our local stack frame
  674.  
  675.         MOVE.L    WindowPtr(A6),-(SP)
  676.         _SetPort            ; set the current port to us
  677.         MOVEA.L    WindowPtr(A6),A0    ; erase the entire window
  678.         PEA    portRect(A0)        ; the window's rect
  679.         _EraseRect            ; clear out anything remaining
  680.         MOVE.W    G.Stopped,D0        ; find the state of the lights
  681.         CMPI.W    #True,D0
  682.         BNE.S    @1            ; red light should be off
  683.  
  684. * ------------- RED LIGHT -------------
  685.  
  686.         MOVE.L    #redColor,-(SP)        ; make the red light go on
  687.         _ForeColor
  688.         PEA    G.StopRect
  689.         _PaintOval
  690.         MOVE.L    #whiteColor,-(SP)    ; make the green light go off
  691.         _ForeColor
  692.         PEA    G.GoRect
  693.         _PaintOval
  694.         BRA.S    @2
  695.  
  696. * ------------- GREEN LIGHT -------------
  697.  
  698. @1        MOVE.L    #greenColor,-(SP)    ; make the green light go on
  699.         _ForeColor
  700.         PEA    G.GoRect
  701.         _PaintOval
  702.         MOVE.L    #whiteColor,-(SP)    ; make the red light go off
  703.         _ForeColor
  704.         PEA    G.StopRect
  705.         _PaintOval
  706.  
  707. * ------------- FRAME THE LIGHTS -------------
  708.  
  709. @2        MOVE.L    #blackColor,-(SP)
  710.         _ForeColor
  711.         PEA    G.StopRect
  712.         _FrameOval            ; draw black line around light
  713.         PEA    G.GoRect
  714.         _FrameOval            ; draw black line around light
  715.  
  716. Exit        UNLK    A6            ; destroy the link
  717.         MOVEA.L    (SP)+,A0        ; pull off the return address
  718.         ADDA.L    #ParamSize,SP        ; strip all of the caller's parameters
  719.         JMP    (A0)            ; return to the caller
  720.  
  721.         DbgInfo    DrawWind        ; this name will appear in the debugger
  722.         ENDP
  723.  
  724. * ================================================
  725. * PROCEDURE GetGlobalMouse(VAR mouse: Point);
  726. * ================================================
  727. * Get the global coordinates of the mouse. When you call OSEventAvail
  728. * it will return either a pending event or a null event. In either case,
  729. * the where field of the event record will contain the current position
  730. * of the mouse in global coordinates and the modifiers field will reflect
  731. * the current state of the modifiers. Another way to get the global
  732. * coordinates is to call GetMouse and LocalToGlobal, but that requires
  733. * being sure that thePort is set to a valid port.}
  734.  
  735.         SEG    'Main'            ; case sensitive
  736. GetGlobalMouse    PROC    EXPORT            ; any source file can use this routine
  737.  
  738. StackFrame    RECORD    {A6Link},DECR        ; build a stack frame record
  739. ParamBegin    EQU    *            ; start parameters after this point
  740. Mouse        DS.L    1            ; passed reference to mouse position
  741. ParamSize    EQU    ParamBegin-*        ; size of all the passed parameters
  742. RetAddr     DS.L    1            ; place holder for return address
  743. A6Link        DS.L    1            ; place holder for A6 link
  744. TheEvent     DS    EventRecord         ; local copy of the event record
  745. LocalSize    EQU     *            ; size of all the local variables
  746.         ENDR
  747.  
  748.         WITH    StackFrame        ; cover our local stack frame
  749.         LINK    A6,#LocalSize        ; allocate our local stack frame
  750.  
  751.         MOVE.W    #NoEvents,D0        ; we aren't interested in any events
  752.         LEA    TheEvent(A6),A0        ; point to event record
  753.         _OSEventAvail            ; just the mouse position
  754.         MOVE.L    Mouse(A6),A0        ; deref address of mouse
  755.         MOVE.L    TheEvent.Where(A6),(A0)    ; stuff new value
  756.  
  757.         UNLK    A6            ; destroy the link
  758.         MOVEA.L    (SP)+,A0        ; pull off the return address
  759.         ADDA.L    #ParamSize,SP        ; strip all of the caller's parameters
  760.         JMP    (A0)            ; return to the caller
  761.  
  762.         DbgInfo    GetGlobalMouse        ; this name will appear in the debugger
  763.         ENDP
  764.  
  765. * ================================================
  766. * PROCEDURE AdjustCursor(mouse: Point; region: RgnHandle);
  767. * ================================================
  768. * Change the cursor's shape, depending on its position. This also calculates the
  769. * region where the current cursor resides (for WaitNextEvent). If the mouse is
  770. * ever outside of that region, an event would be generated, causing this routine
  771. * to be called, allowing us to change the region to the region the mouse is
  772. * currently in. If there is more to the event than just the mouse moved, we
  773. * get called before the event is processed to make sure the cursor is the right
  774. * one. In any (ahem) event, this is called again before we fall back into WNE.
  775. * 1.02 - Removed the mouse position parameter and instead use the current position
  776. * of the mouse by calling GetMouse and LocalToGlobal.
  777.  
  778.         SEG    'Main'            ; case sensitive
  779. AdjustCursor    PROC    EXPORT
  780.  
  781. StackFrame    RECORD    {A6Link},DECR        ; build a stack frame record
  782. ParamBegin    EQU    *            ; start parameters after this point
  783. Where        DS.L    1            ; the mouse location passed to us
  784. MouseRegion    DS.L    1            ; passed pointer to current region
  785. ParamSize    EQU    ParamBegin-*        ; size of all the passed parameters
  786. RetAddr     DS.L    1            ; place holder for return address
  787. A6Link        DS.L    1            ; place holder for A6 link
  788. FrontMost    DS.L    1            ; local pointer to the front window
  789. ArrowRgn    DS.L    1            ; local handle to the arrow cursor region
  790. PlusRgn        DS.L    1            ; local handle to the plus cursor region
  791. LocalSize    EQU     *            ; size of all the local variables
  792.         ENDR
  793.  
  794.         IMPORT    IsDAWindow,IsAppWindow
  795.  
  796.         WITH    StackFrame        ; cover our local stack frame
  797.         LINK    A6,#LocalSize        ; allocate our local stack frame
  798.  
  799.         CLR.W    -(SP)            ; space for result of IsAppWindow
  800.         CLR.L    -(SP)            ; space for result of FrontWindow
  801.         _FrontWindow            ; push front window pointer
  802.         MOVE.L    (SP),FrontMost(A6)    ; copy pointer and keep it on stack
  803.         BSR    IsDAWindow        ; is this an application window?
  804.         MOVE.W    (SP)+,D0
  805.         CMPI.W    #True,D0
  806.         BEQ.W    Exit            ; not our window, don't adjust the cursor
  807.         CMPI.W    #True,G.InBackground
  808.         BEQ.W    Exit            ; and do nothing if we're in the background
  809.  
  810. * ------------- INITIALIZE SOME REGION DATA -------------
  811.  
  812.         CLR.L    -(SP)
  813.         _NewRgn                ; create an empty plus region
  814.         MOVE.L    (SP)+,PlusRgn(A6)
  815.         CLR.L    -(SP)
  816.         _NewRgn                ; create an empty arrow region
  817.         MOVE.L    (SP)+,ArrowRgn(A6)
  818.         MOVE.L    ArrowRgn(A6),-(SP)    ; arrow region handle
  819.         MOVE.W    #ExtremeNeg,-(SP)    ; big left corner
  820.         MOVE.W    #ExtremeNeg,-(SP)    ; big top corner
  821.         MOVE.W    #ExtremePos,-(SP)    ; big right corner
  822.         MOVE.W    #ExtremePos,-(SP)    ; big bottom corner
  823.         _SetRecRgn            ; really big rectangular region
  824.  
  825.         CLR.W    -(SP)
  826.         MOVE.L    FrontMost(A6),-(SP)
  827.         BSR    IsAppWindow        ; is this an application window?
  828.         MOVE.W    (SP)+,D0
  829.         CMPI.W    #True,D0
  830.         BNE.S    @1            ; our window isn't in front?
  831.  
  832. * ------------- CALCULATE THE PLUS REGION -------------
  833.  
  834.         MOVE.L    FrontMost(A6),-(SP)
  835.         _SetPort            ; set the current port to us
  836.         MOVEA.L    FrontMost(A6),A0
  837.         MOVE.W    portBits+bounds+left(A0),D0
  838.         NEG.W    D0            ; offset window's left edge...
  839.         MOVE.W    D0,-(SP)        ; to the screen's left edge
  840.         MOVEA.L    FrontMost(A6),A0
  841.         MOVE.W    portBits+bounds+top(A0),D0
  842.         NEG.W    D0            ; offset window's top edge...
  843.         MOVE.W    D0,-(SP)        ; to the screen's top edge
  844.         _SetOrigin            ; make window rect global
  845.         MOVE.L    PlusRgn(A6),-(SP)    ; handle to empty plus region
  846.         MOVEA.L    FrontMost(A6),A0    ; pointer to our window
  847.         PEA    portRect(A0)        ; window rect's global coordinates
  848.         _RectRgn            ; make global window rect into region
  849.         MOVE.L    PlusRgn(A6),-(SP)    ; get intersection of plus and window region
  850.         MOVEA.L    FrontMost(A6),A0
  851.         MOVE.L    visRgn(A0),-(SP)    ; get front window's visRgn
  852.         MOVE.L    PlusRgn(A6),-(SP)    ; resulting region will be in PlusRgn
  853.         _SectRgn            ; intersection the two regions
  854.         CLR.L    -(SP)            ; reset the origin of our window to 0,0
  855.         _SetOrigin
  856.  
  857. @1        MOVE.L    ArrowRgn(A6),-(SP)    ; the really big rectangular region
  858.         MOVE.L    PlusRgn(A6),-(SP)    ; the region of our window
  859.         MOVE.L    ArrowRgn(A6),-(SP)    ; intersetion of the Arrow and Plus region
  860.         _DiffRgn            ; this is the region where the Arrow shows
  861.         CLR.W    -(SP)            ; space for result of PtInRect
  862.         MOVE.L    Where(A6),-(SP)        ; here's the mouse
  863.         MOVE.L    PlusRgn(A6),-(SP)    ; where the arrow should show up
  864.         _PtInRgn            ; was cursor in the arrow region?
  865.         MOVE.W    (SP)+,D0
  866.         CMPI.W    #True,D0
  867.         BNE.S    @2            ; cursor was in arrow region
  868.  
  869. * ------------- SET THE CURSOR AND NEW MOUSE REGION -------------
  870.  
  871.         CLR.L    -(SP)            ; space for result
  872.         MOVE.W    #plusCursor,-(SP)    ; I want the plus cursor now!
  873.         _GetCursor
  874.         MOVEA.L    (SP)+,A0        ; get the handle
  875.         CMPA.L    #NIL,A0
  876.         BEQ.S    Exit            ; check for NIL like a good boy
  877.         MOVE.L    (A0),-(SP)        ; got the plus cursor
  878.         _SetCursor            ; set cursor to plus
  879.         MOVE.L    PlusRgn(A6),-(SP)    ; current region containing cursor
  880.         MOVE.L    MouseRegion(A6),-(SP)    ; set it to the new region
  881.         _CopyRgn
  882.         BRA.S    @3            ; we're done, get out of here
  883.  
  884. @2        PEA    QD.Arrow        ; got arrow cursor at InitGraf
  885.         _SetCursor            ; set cursor to the Arrow
  886.         MOVE.L    ArrowRgn(A6),-(SP)    ; current region containing cursor
  887.         MOVE.L    MouseRegion(A6),-(SP)    ; set it to the new region
  888.         _CopyRgn
  889.  
  890. @3        MOVE.L    PlusRgn(A6),-(SP)    ; dispose of our two temporary regions
  891.         _DisposRgn
  892.         MOVE.L    ArrowRgn(A6),-(SP)
  893.         _DisposRgn
  894.  
  895. Exit        UNLK    A6            ; destroy the link
  896.         MOVEA.L    (SP)+,A0        ; pull off the return address
  897.         ADDA.L    #ParamSize,SP        ; strip all of the caller's parameters
  898.         JMP    (A0)            ; return to the caller
  899.  
  900.         DbgInfo    AdjstCur        ; this name will appear in the debugger
  901.         ENDP
  902.  
  903.         END                ; end of this source file
  904.