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.
CLUTSampleMisc.a
* |
* Apple Macintosh Developer Technical Support |
* |
* CLUTSample |
* |
* CLUTSampleMisc.a - Assembler Source |
* |
* |
* Loosely based in the sample SAMPLE this program shows |
* how to create a window and display on it the colors of the CLUT |
* associated with the device the window sits on top of. |
* |
* Left to the curious reader are some improvements such as, remembering the |
* positions of each open window, so if you use this program to monitor your |
* color tables it will position the windows in the last place you opened them. |
* The treatment of direct devices is kind of 'casual' a better color display may |
* be appropriate. Last, it may be desireable to change the size of the color |
* rectangles depending on the depth of the color table. |
* Check Sample sources for more detailed documentation. |
* Copyright © 1990 Apple Computer, Inc. |
* All rights reserved. |
* ================================================ |
* -------------- INCLUDES SECTION ---------------- |
* ================================================ |
PRINT PUSH,OFF ; don't print any of this stuff |
INCLUDE 'ToolEqu.a' |
INCLUDE 'Traps.a' |
INCLUDE 'PackMacs.a' |
INCLUDE 'QuickEqu.a' |
INCLUDE 'SysEqu.a' |
INCLUDE 'CLUTSample.inc1.a' ; all our macros and data templates |
PRINT POP ; restore the PRINT options |
* ================================================ |
* ----------- DATA STORAGE USAGE --------------- |
* ================================================ |
IMPORT QD:QDGlobals |
IMPORT G:AppGlobals |
* ================================================ |
* FUNCTION TrapAvailable(tNumber: INTEGER): BOOLEAN; |
* ================================================ |
SEG 'Initialize' ; case sensitive |
TrapAvailable FUNC EXPORT ; any source file can use this routine |
StackFrame RECORD {A6Link},DECR ; build a stack frame record |
Result DS.W 1 ; function's result returned to caller |
ParamBegin EQU * ; start parameters after this point |
tNumber DS.W 1 ; the trap number passed by caller |
ParamSize EQU ParamBegin-* ; size of all the passed parameters |
RetAddr DS.L 1 ; place holder for return address |
A6Link DS.L 1 ; place holder for A6 link |
TrapAddress DS.L 1 ; local copy of trap address |
LocalSize EQU * ; size of all the local variables |
ENDR |
WITH StackFrame ; cover our local stack frame |
LINK A6,#LocalSize ; allocate our local stack frame |
MOVE.W #False,Result(A6) ; initialize function's result |
MOVE.W tNumber(A6),D0 ; get trap word into D0 |
BTST #ToolTrapBit,D0 ; test if number is Tool trap |
BEQ.S GetOSTrap ; off means a new OS trap number |
MOVE.W G.Mac.machineType,D1 ; get the machine type we're running |
CMPI.W #envMachUnknown,D1 ; are we on a future machine? |
BEQ.S GetToolTrap ; yes, go ahead and test for a new Tool trap |
CMPI.W #envMacII,D1 ; are we on a Mac II or better? |
BGE.S GetToolTrap ; yes, go ahead and test for a new Tool trap |
* ------------- TEST FOR EXCEEDING TRAP TABLE ------------- |
* At this point we know we're on a Mac 512E, Plus, or SE and need to |
* test the trap number for being in the range of < $0200 |
AND.W #$03FF,D0 ; mask off the ToolTrap bits |
CMPI.W #$01FF,D0 ; is this trap in our trap table? |
BLE.S GetToolTrap ; yes, go ahead and test for a new Tool trap |
BRA.S Exit ; no, then this trap cannot be present |
* ------------- TEST FOR NEW TOOL TRAP ------------- |
GetToolTrap _GetTrapAddress ,NewTool ; NewTool trap macro, trap is in D0 |
MOVE.L A0,TrapAddress(A6) ; save a copy of the trap address |
BRA.S TestUnimp ; test against Unimplemented trap |
* ------------- TEST FOR NEW OS TRAP ------------- |
GetOSTrap _GetTrapAddress ,NewOS ; NewOS trap macro, trap is in D0 |
MOVE.L A0,TrapAddress(A6) ; save a copy of the trap address |
TestUnimp MOVE.W #Unimplemented,D0 ; get address of Unimplemented trap |
_GetTrapAddress |
CMPA.L TrapAddress(A6),A0 ; see if trap is implemented |
BEQ.S Exit ; nope, they're the same |
MOVE.W #True,Result(A6) ; yes, we've got the trap |
Exit UNLK A6 ; destroy the link |
MOVEA.L (SP)+,A0 ; pull off the return address |
ADDA.L #ParamSize,SP ; strip all of the caller's parameters |
JMP (A0) ; return to the caller |
DbgInfo TrapAval ; this name will appear in the debugger |
ENDF |
* ================================================ |
* FUNCTION GoGetRect(rectID: INTEGER; VAR theRect: Rect) : BOOLEAN; |
* ================================================ |
* This utility loads the global rectangles that are used by the window |
* drawing routines. It shows how the resource manager can be used to hold |
* values in a convenient manner. These values are then easily altered without |
* having to re-compile the source code. GoGetRect will return a BOOLEAN that |
* indicates if it was successful in getting the rectangle. |
* A0 is being used for resource handle. |
SEG 'Initialize' ; case sensitive |
GoGetRect FUNC EXPORT ; any source file can use this routine |
StackFrame RECORD {A6Link},DECR ; build a stack frame record |
Result DS.W 1 ; function's result returned to caller |
ParamBegin EQU * ; start parameters after this point |
RectID DS.W 1 ; resource ID of rect passed by caller |
TheRect DS.L 1 ; the rect's pointer passed by caller |
ParamSize EQU ParamBegin-* ; size of all the passed parameters |
RetAddr DS.L 1 ; place holder for return address |
A6Link DS.L 1 ; place holder for A6 link |
LocalSize EQU * ; size of all the local variables |
ENDR |
WITH StackFrame ; cover our local stack frame |
LINK A6,#LocalSize ; allocate our local stack frame |
MOVE.W #False,Result(A6) ; initialize function's result |
CLR.L -(SP) ; create space for result |
MOVE.L #'RECT',-(SP) |
MOVE.W RectID(A6),-(SP) ; get the stop light's rect |
_GetResource |
MOVEA.L (SP)+,A0 ; handle to RECT resource in A0 |
CMPA.L #NIL,A0 ; test for NIL handle |
BEQ.S Exit ; didn't get resource, exit this procedure |
* -------- COPY THE RESOURCE TO THE RECT -------- |
MOVE.W #True,Result(A6) ; we got the resource, return true |
MOVEA.L (A0),A0 ; pointer to RECT resource in A0 |
MOVEA.L TheRect(A6),A1 ; pointer to the dest. RECT in A1 |
MOVE.L topLeft(A0),topLeft(A1) ; copy to the rect passed to us |
MOVE.L botRight(A0),botRight(A1) |
Exit UNLK A6 ; destroy the link |
MOVEA.L (SP)+,A0 ; pull off the return address |
ADDA.L #ParamSize,SP ; strip all of the caller's parameters |
JMP (A0) ; return to the caller |
DbgInfo GetRect ; this name will appear in the debugger |
ENDF |
* ================================================ |
* FUNCTION IsDAWindow(window: WindowPtr): BOOLEAN; |
* ================================================ |
* Check if a window belongs to a desk accessory. DA window has a negitive kind. |
SEG 'Main' |
IsDAWindow FUNC EXPORT ; any source file can use this routine |
StackFrame RECORD {A6Link},DECR ; build a stack frame record |
Result DS.W 1 ; function's result returned to caller |
ParamBegin EQU * ; start parameters after this point |
TheWindow DS.L 1 ; a window's pointer passed by caller |
ParamSize EQU ParamBegin-* ; size of all the passed parameters |
RetAddr DS.L 1 ; place holder for return address |
A6Link DS.L 1 ; place holder for A6 link |
LocalSize EQU * ; size of all the local variables |
ENDR |
WITH StackFrame ; cover our local stack frame |
LINK A6,#LocalSize ; allocate our local stack frame |
MOVE.W #False,Result(A6) ; first, initialize the result |
CMPI.L #NIL,TheWindow(A6) ; valid pointer? |
BEQ.S Exit ; it was NIL, look out! |
MOVEA.L TheWindow(A6),A0 ; get the window pointer |
MOVE.W WindowKind(A0),D0 ; what kind of window was it? |
BPL.S Exit ; DA windows are negitive |
MOVE.W #True,Result(A6) ; return true to the caller |
Exit UNLK A6 ; destroy the link |
MOVEA.L (SP)+,A0 ; pull off the return address |
ADDA.L #ParamSize,SP ; strip all of the caller's parameters |
JMP (A0) ; return to the caller |
DbgInfo IsDAWind ; this name will appear in the debugger |
ENDF |
* ================================================ |
* FUNCTION IsAppWindow(window: WindowPtr): BOOLEAN; |
* ================================================ |
* Check to see if a window belongs to the application. If the window pointer |
* passed was NIL, then it could not be an application window. WindowKinds |
* that are negative belong to the system and windowKinds less than userKind |
* are reserved by Apple except for windowKinds equal to dialogKind, which |
* means it is a dialog. |
* In order to reduce the chance of accidentally treating some window |
* as an AppWindow that shouldn't be, we'll only return true if the windowkind |
* is userKind. If you add different kinds of windows to Sample you'll need |
* to change how this all works. |
SEG 'Main' |
IsAppWindow FUNC EXPORT ; any source file can use this routine |
StackFrame RECORD {A6Link},DECR ; build a stack frame record |
Result DS.W 1 ; function's result returned to caller |
ParamBegin EQU * ; start parameters after this point |
TheWindow DS.L 1 ; a window's pointer passed by caller |
ParamSize EQU ParamBegin-* ; size of all the passed parameters |
RetAddr DS.L 1 ; place holder for return address |
A6Link DS.L 1 ; place holder for A6 link |
LocalSize EQU * ; size of all the local variables |
ENDR |
WITH StackFrame ; cover our local stack frame |
LINK A6,#LocalSize ; allocate our local stack frame |
MOVE.W #False,Result(A6) ; first, initialize the result |
CMPI.L #NIL,TheWindow(A6) ; valid pointer? |
BEQ.S Exit ; it was NIL, look out! |
MOVEA.L TheWindow(A6),A0 ; get the window pointer |
MOVE.W WindowKind(A0),D0 ; what kind of window was it? |
CMPI.W #UserKind,D0 ; was it an application window? |
BNE.S Exit ; no, result is going to be false |
MOVE.W #True,Result(A6) ; return true to the caller |
Exit UNLK A6 ; destroy the link |
MOVEA.L (SP)+,A0 ; pull off the return address |
ADDA.L #ParamSize,SP ; strip all of the caller's parameters |
JMP (A0) ; return to the caller |
DbgInfo IsAppWin ; this name will appear in the debugger |
ENDF |
* ================================================ |
* PROCEDURE AlertUser; |
* ================================================ |
* Display an alert that tells the user an error occurred, then exit the program. |
* This routine is used as an ultimate bail-out for serious errors that prohibit |
* the continuation of the application. Errors that do not require the termination |
* of the application should be handled in a different manner. Error checking and |
* reporting has a place even in the simplest application. For simplicity, the alert |
* displayed here only says that an error occurred, but not what it was. There are |
* various methods available for being more specific. |
SEG 'Main' ; case sensitive |
AlertUser PROC EXPORT ; any source file can use this routine |
StackFrame RECORD {A6Link},DECR ; build a stack frame record |
ParamBegin EQU * ; start parameters after this point |
ParamSize EQU ParamBegin-* ; size of all the passed parameters |
RetAddr DS.L 1 ; place holder for return address |
A6Link DS.L 1 ; place holder for A6 link |
LocalSize EQU * ; size of all the local variables |
ENDR |
WITH StackFrame ; cover our local stack frame |
LINK A6,#LocalSize ; allocate our local stack frame |
CLR.W -(SP) ; space for result of Alert |
MOVE.W #rUserAlert,-(SP) ; resource for alert dialog |
CLR.L -(SP) ; no filter procedure used here |
_Alert ; read the resource and display it |
MOVE.W (SP)+,D0 ; I don't care which item is was |
_ExitToShell ; we're out of here, no error recovery |
Exit UNLK A6 ; destroy the link |
MOVEA.L (SP)+,A0 ; pull off the return address |
ADDA.L #ParamSize,SP ; strip all of the caller's parameters |
JMP (A0) ; return to the caller |
DbgInfo AlrtUser ; this name will appear in the debugger |
ENDP |
* ================================================ |
* FUNCTION DoCloseWindow(window: WindowPtr) : BOOLEAN; |
* ================================================ |
* At this point, if there was a document associated with a window, you could |
* do any document saving processing if it is 'dirty'. DoCloseWindow would |
* return TRUE if the window actually closes, i.e., the user does not cancel |
* from a save dialog. This result is handy when the user quits an application, |
* but then cancels a save of a document associated with a window. We also added |
* code to close the application window since otherwise, the termination routines |
* would never stop looping, waiting for FrontWindow to return NIL. |
SEG 'Main' ; case sensitive |
DoCloseWindow FUNC EXPORT ; any source file can use this routine |
StackFrame RECORD {A6Link},DECR ; build a stack frame record |
Result DS.W 1 ; function's result returned to caller |
ParamBegin EQU * ; start parameters after this point |
WindowPtr DS.L 1 ; passed window pointer parameter |
ParamSize EQU ParamBegin-* ; size of all the passed parameters |
RetAddr DS.L 1 ; place holder for return address |
A6Link DS.L 1 ; place holder for A6 link |
LocalSize EQU * ; size of all the local variables |
ENDR |
WITH StackFrame ; cover our local stack frame |
LINK A6,#LocalSize ; allocate our local stack frame |
MOVE.W #True,Result(A6); ; initialize the function's result |
CLR.W -(SP) ; space for result of IsDAWindow |
MOVE.L WindowPtr(A6),-(SP) ; pass the window pointer |
BSR IsDAWindow |
MOVE.W (SP)+,D0 ; result of IsDAWindow |
CMPI.W #True,D0 |
BNE.S @1 ; this wasn't a DA window |
MOVEA.L WindowPtr(A6),A0 ; get window pointer |
MOVE.W WindowKind(A0),-(SP) ; pass the refNum of DA |
_CloseDeskAcc |
BRA.S Exit ; all done |
@1 CLR.W -(SP) ; space for result of IsAppWindow |
MOVE.L WindowPtr(A6),-(SP) ; pass a the window pointer |
BSR IsAppWindow |
MOVE.W (SP)+,D0 ; result of IsAppWindow |
CMPI.W #True,D0 |
BNE.S Exit ; it wasn't our application's window |
MOVE.L WindowPtr(A6),-(SP) ; close window, it shouldn't be a dialog |
_CloseWindow ; close the application window |
Exit UNLK A6 ; destroy the link |
MOVEA.L (SP)+,A0 ; pull off the return address |
ADDA.L #ParamSize,SP ; strip all of the caller's parameters |
JMP (A0) ; return to the caller |
DbgInfo ClosWind ; this name will appear in the debugger |
ENDF |
* ================================================ |
* PROCEDURE Terminate; |
* ================================================ |
* Clean up the application and exit. We close all of the windows so that |
* they can update their documents, if any. We don't have much to do here. |
* Just close our windows and then exit. If we find out that a Cancel has |
* occurred (DoCloseWindow will return False) we won't exit to the shell, |
* but will simply exit this procedure. |
SEG 'Main' ; case sensitive |
Terminate PROC EXPORT |
StackFrame RECORD {A6Link},DECR ; build a stack frame record |
ParamBegin EQU * ; start parameters after this point |
ParamSize EQU ParamBegin-* ; size of all the passed parameters |
RetAddr DS.L 1 ; place holder for return address |
A6Link DS.L 1 ; place holder for A6 link |
WindowPtr DS.L 1 ; local variable for a window pointer |
Closed DS.W 1 ; local variable for looping |
LocalSize EQU * ; size of all the local variables |
ENDR |
IMPORT DoCloseWindow |
WITH StackFrame ; cover our local stack frame |
LINK A6,#LocalSize ; allocate our local stack frame |
MOVE.W #True,Closed(A6) ; initialize local variable |
Loop CLR.L -(SP) ; space for front window pointer |
_FrontWindow |
MOVE.L (SP)+,WindowPtr(A6) ; get the front window pointer |
CMPI.L #NIL,WindowPtr(A6) ; is there a front window? |
BEQ.S @1 ; there are no more windows |
CLR.W -(SP) ; space for result of DoCloseWindow |
MOVE.L WindowPtr(A6),-(SP) ; pass the window pointer |
BSR DoCloseWindow ; close all our windows |
MOVE.W (SP)+,Closed(A6) ; get result of DoCloseWindow |
CMPI.W #True,Closed(A6) ; what's the result of DoCloseWindow? |
BNE.S Exit ; user didn't want to close that window |
BRA.S Loop ; loop again and close the next window |
@1 CMPI.W #True,Closed(A6) ; should we really terminate? |
BNE.S Exit ; no, exit this procedure |
_ExitToShell ; we're done, let's get out of here |
Exit UNLK A6 ; destroy the link |
MOVEA.L (SP)+,A0 ; pull off the return address |
ADDA.L #ParamSize,SP ; strip all of the caller's parameters |
JMP (A0) ; return to the caller |
DbgInfo Terminat ; this name will appear in the debugger |
ENDP |
* ================================================ |
* PROCEDURE AdjustMenus; |
* ================================================ |
* Enable and disable menus based on the current state. The user can only select |
* enabled menu items. We set up all the menu items before calling MenuSelect or |
* MenuKey, since these are the only times that a menu item can be selected. Note |
* that MenuSelect is also the only time the user will see menu items. This |
* approach to deciding what enable/disable state a menu item has the advantage |
* of concentrating all the decision making in one routine, as opposed to being |
* spread throughout the application. Other application designs may take a |
* different approach that are just as valid. |
SEG 'Main' ; case sensitive |
AdjustMenus PROC EXPORT ; any source file can use this routine |
StackFrame RECORD {A6Link},DECR ; build a stack frame record |
ParamBegin EQU * ; start parameters after this point |
ParamSize EQU ParamBegin-* ; size of all the passed parameters |
RetAddr DS.L 1 ; place holder for return address |
A6Link DS.L 1 ; place holder for A6 link |
FrontMost DS.L 1 ; local copy of the front window |
Menu DS.L 1 ; local copy of the menu handle |
LocalSize EQU * ; size of all the local variables |
ENDR |
WITH StackFrame ; cover our local stack frame |
LINK A6,#LocalSize ; allocate our local stack frame |
CLR.L -(SP) ; space for result |
_FrontWindow |
MOVE.L (SP)+,FrontMost(A6) ; save the front window |
Exit UNLK A6 ; destroy the link |
MOVEA.L (SP)+,A0 ; pull off the return address |
ADDA.L #ParamSize,SP ; strip all of the caller's parameters |
JMP (A0) ; return to the caller |
DbgInfo AdjstMnu ; this name will appear in the debugger |
ENDP |
* ================================================ |
* PROCEDURE GetGlobalMouse(VAR mouse: Point); |
* ================================================ |
* Get the global coordinates of the mouse. When you call OSEventAvail |
* it will return either a pending event or a null event. In either case, |
* the where field of the event record will contain the current position |
* of the mouse in global coordinates and the modifiers field will reflect |
* the current state of the modifiers. Another way to get the global |
* coordinates is to call GetMouse and LocalToGlobal, but that requires |
* being sure that thePort is set to a valid port.} |
SEG 'Main' ; case sensitive |
GetGlobalMouse PROC EXPORT ; any source file can use this routine |
StackFrame RECORD {A6Link},DECR ; build a stack frame record |
ParamBegin EQU * ; start parameters after this point |
Mouse DS.L 1 ; passed reference to mouse position |
ParamSize EQU ParamBegin-* ; size of all the passed parameters |
RetAddr DS.L 1 ; place holder for return address |
A6Link DS.L 1 ; place holder for A6 link |
TheEvent DS EventRecord ; local copy of the event record |
LocalSize EQU * ; size of all the local variables |
ENDR |
WITH StackFrame ; cover our local stack frame |
LINK A6,#LocalSize ; allocate our local stack frame |
MOVE.W #NoEvents,D0 ; we aren't interested in any events |
LEA TheEvent(A6),A0 ; point to event record |
_OSEventAvail ; just the mouse position |
MOVE.L Mouse(A6),A0 ; deref address of mouse |
MOVE.L TheEvent.Where(A6),(A0) ; stuff new value |
UNLK A6 ; destroy the link |
MOVEA.L (SP)+,A0 ; pull off the return address |
ADDA.L #ParamSize,SP ; strip all of the caller's parameters |
JMP (A0) ; return to the caller |
DbgInfo GetGlobalMouse ; this name will appear in the debugger |
ENDP |
* ================================================ |
* PROCEDURE DrawClut(window: WindowPtr); |
* ================================================ |
* |
* This procedure finds the max depth device for the window port and uses that |
* device to draw the colors in the window. |
SEG 'Main' ; case sensitive |
DrawClut PROC EXPORT ; any source file can use this routine |
StackFrame RECORD {A6Link},DECR ; build a stack frame record |
ParamBegin EQU * ; start parameters after this point |
WindowPtr DS.L 1 ; passed parameter of the window pointer |
ParamSize EQU ParamBegin-* ; size of all the passed parameters |
RetAddr DS.L 1 ; place holder for return address |
A6Link DS.L 1 ; place holder for A6 link |
Color DS.W 3 |
OldGDev DS.l 1 ; save current GDevice |
wRectBR DS.L 1 ; |
wRectTL DS.L 1 ; local storage for rect |
LocalSize EQU * ; size of all the local variables |
ENDR |
WITH StackFrame,ClutWData ; cover our local stack frame |
LINK A6,#LocalSize ; allocate our local stack frame |
MOVE.L WindowPtr(A6),-(SP) |
_SetPort ; set the current port to use |
MOVE.L theGDevice,OldGDev(a6) ; save current device |
; Now we want to check the max device the window is on in order to use its color table |
; to display colors. |
move.l WindowPtr(a6), A0 ; get pointer to port |
ADD.L #$10,A0 ; point to rectangle |
LEA wRectTL(a6),a1 |
MOVE.L (a0)+,(a1)+ ; copy topleft |
MOVE.L (a0)+,(a1)+ ; copy bottomright |
PEA wRectTL(a6) ; push rect |
_LocalToGlobal ; globalize topleft |
PEA wRectBR(a6) ; push rect |
_LocalToGlobal ; globalize bottomright |
clr.l -(sp) ; make room for result |
PEA wRectTL(a6) ; push rect |
_GetMaxDevice ; don't touch result |
CMP.L #0,(sp) ; check result |
BEQ @1 ; if nil use current device |
_SetGDevice ; the max dev is in the stack |
@1 Move.L #255,D3 |
Move.w #4,-(SP) |
Move.w #4,-(SP) |
_PenSize |
ClutLoop: |
Move.L D3,-(SP) |
Pea Color(A6) |
_Index2Color |
Pea Color(A6) |
_RGBForeColor |
; Build 16*16 array = 256 colors |
Move.w D3,D0 ; Current color index |
And.w #$000F,D0 ; mod 16 (16 colors per row) |
ASL.w #2,D0 ; times 4 (pen width) |
Move.w D0,-(SP) ; set ÔleftÕ for MoveTo |
Move.w D3,D0 ; Current index |
LSR.w #4,D0 ; divided by 16 (and lose low order bits) |
ASL.w #2,D0 ; times 4 (pen width) |
Move.w D0,-(SP) ; set ÔtopÕ for MoveTo |
_MoveTo |
Clr.l -(SP) |
_Line ; Line length of zero ÔstampsÕ in pen |
DBRA D3,ClutLoop |
Exit MOVE.L OldGDev(a6),theGDevice ; restore current device |
UNLK A6 ; destroy the link |
MOVEA.L (SP)+,A0 ; pull off the return address |
ADDA.L #ParamSize,SP ; strip all of the caller's parameters |
JMP (A0) ; return to the caller |
DbgInfo DrawClut |
ENDP |
* ================================================ |
* PROCEDURE NulMouse(window: WindowPtr; event: EventRecord); |
* ================================================ |
SEG 'Main' ; case sensitive |
NulMouse PROC EXPORT |
StackFrame RECORD {A6Link},DECR ; build a stack frame record |
ParamBegin EQU * ; start parameters after this point |
WindowPtr DS.L 1 ; passed parameter of the window pointer |
EventPtr DS.L 1 ; pointer to the event record |
ParamSize EQU ParamBegin-* ; size of all the passed parameters |
RetAddr DS.L 1 ; place holder for return address |
A6Link DS.L 1 ; place holder for A6 link |
* insert locals here |
LocalSize EQU * ; size of all the local variables |
ENDR |
; IMPORT |
WITH StackFrame ; cover our local stack frame |
LINK A6,#LocalSize ; allocate our local stack frame |
Exit UNLK A6 ; destroy the link |
MOVEA.L (SP)+,A0 ; pull off the return address |
ADDA.L #ParamSize,SP ; strip all of the caller's parameters |
JMP (A0) ; return to the caller |
DbgInfo NulMouse |
ENDP |
* ================================================ |
* PROCEDURE AdjustCursor(mouse: Point; region: RgnHandle); |
* ================================================ |
* Change the cursor's shape, depending on its position. This also calculates the |
* region where the current cursor resides (for WaitNextEvent). If the mouse is |
* ever outside of that region, an event would be generated, causing this routine |
* to be called, allowing us to change the region to the region the mouse is |
* currently in. If there is more to the event than just the mouse moved, we |
* get called before the event is processed to make sure the cursor is the right |
* one. In any (ahem) event, this is called again before we fall back into WNE. |
* 1.02 - Removed the mouse position parameter and instead use the current position |
* of the mouse by calling GetMouse and LocalToGlobal. |
SEG 'Main' ; case sensitive |
AdjustCursor PROC EXPORT |
StackFrame RECORD {A6Link},DECR ; build a stack frame record |
ParamBegin EQU * ; start parameters after this point |
Where DS.L 1 ; the mouse location passed to us |
MouseRegion DS.L 1 ; passed pointer to current region |
ParamSize EQU ParamBegin-* ; size of all the passed parameters |
RetAddr DS.L 1 ; place holder for return address |
A6Link DS.L 1 ; place holder for A6 link |
FrontMost DS.L 1 ; local pointer to the front window |
ArrowRgn DS.L 1 ; local handle to the arrow cursor region |
PlusRgn DS.L 1 ; local handle to the plus cursor region |
LocalSize EQU * ; size of all the local variables |
ENDR |
IMPORT IsDAWindow,IsAppWindow |
WITH StackFrame ; cover our local stack frame |
LINK A6,#LocalSize ; allocate our local stack frame |
CLR.W -(SP) ; space for result of IsAppWindow |
CLR.L -(SP) ; space for result of FrontWindow |
_FrontWindow ; push front window pointer |
MOVE.L (SP),FrontMost(A6) ; copy pointer and keep it on stack |
BSR IsDAWindow ; is this an application window? |
MOVE.W (SP)+,D0 |
CMPI.W #True,D0 |
BEQ.W Exit ; not our window, don't adjust the cursor |
CMPI.W #True,G.InBackground |
BEQ.W Exit ; and do nothing if we're in the background |
* ------------- INITIALIZE SOME REGION DATA ------------- |
CLR.L -(SP) |
_NewRgn ; create an empty plus region |
MOVE.L (SP)+,PlusRgn(A6) |
CLR.L -(SP) |
_NewRgn ; create an empty arrow region |
MOVE.L (SP)+,ArrowRgn(A6) |
MOVE.L ArrowRgn(A6),-(SP) ; arrow region handle |
MOVE.W #ExtremeNeg,-(SP) ; big left corner |
MOVE.W #ExtremeNeg,-(SP) ; big top corner |
MOVE.W #ExtremePos,-(SP) ; big right corner |
MOVE.W #ExtremePos,-(SP) ; big bottom corner |
_SetRecRgn ; really big rectangular region |
CLR.W -(SP) |
MOVE.L FrontMost(A6),-(SP) |
BSR IsAppWindow ; is this an application window? |
MOVE.W (SP)+,D0 |
CMPI.W #True,D0 |
BNE.S @1 ; our window isn't in front? |
* ------------- CALCULATE THE PLUS REGION ------------- |
MOVE.L FrontMost(A6),-(SP) |
_SetPort ; set the current port to us |
MOVEA.L FrontMost(A6),A0 |
MOVE.W portBits+bounds+left(A0),D0 |
NEG.W D0 ; offset window's left edge... |
MOVE.W D0,-(SP) ; to the screen's left edge |
MOVEA.L FrontMost(A6),A0 |
MOVE.W portBits+bounds+top(A0),D0 |
NEG.W D0 ; offset window's top edge... |
MOVE.W D0,-(SP) ; to the screen's top edge |
_SetOrigin ; make window rect global |
MOVE.L PlusRgn(A6),-(SP) ; handle to empty plus region |
MOVEA.L FrontMost(A6),A0 ; pointer to our window |
PEA portRect(A0) ; window rect's global coordinates |
_RectRgn ; make global window rect into region |
MOVE.L PlusRgn(A6),-(SP) ; get intersection of plus and window region |
MOVEA.L FrontMost(A6),A0 |
MOVE.L visRgn(A0),-(SP) ; get front window's visRgn |
MOVE.L PlusRgn(A6),-(SP) ; resulting region will be in PlusRgn |
_SectRgn ; intersection the two regions |
CLR.L -(SP) ; reset the origin of our window to 0,0 |
_SetOrigin |
@1 MOVE.L ArrowRgn(A6),-(SP) ; the really big rectangular region |
MOVE.L PlusRgn(A6),-(SP) ; the region of our window |
MOVE.L ArrowRgn(A6),-(SP) ; intersetion of the Arrow and Plus region |
_DiffRgn ; this is the region where the Arrow shows |
CLR.W -(SP) ; space for result of PtInRect |
MOVE.L Where(A6),-(SP) ; here's the mouse |
MOVE.L PlusRgn(A6),-(SP) ; where the arrow should show up |
_PtInRgn ; was cursor in the arrow region? |
MOVE.W (SP)+,D0 |
CMPI.W #True,D0 |
BNE.S @2 ; cursor was in arrow region |
* ------------- SET THE CURSOR AND NEW MOUSE REGION ------------- |
CLR.L -(SP) ; space for result |
MOVE.W #plusCursor,-(SP) ; I want the plus cursor now! |
_GetCursor |
MOVEA.L (SP)+,A0 ; get the handle |
CMPA.L #NIL,A0 |
BEQ.S Exit ; check for NIL like a good boy |
MOVE.L (A0),-(SP) ; got the plus cursor |
_SetCursor ; set cursor to plus |
MOVE.L PlusRgn(A6),-(SP) ; current region containing cursor |
MOVE.L MouseRegion(A6),-(SP) ; set it to the new region |
_CopyRgn |
BRA.S @3 ; we're done, get out of here |
@2 PEA QD.Arrow ; got arrow cursor at InitGraf |
_SetCursor ; set cursor to the Arrow |
MOVE.L ArrowRgn(A6),-(SP) ; current region containing cursor |
MOVE.L MouseRegion(A6),-(SP) ; set it to the new region |
_CopyRgn |
@3 MOVE.L PlusRgn(A6),-(SP) ; dispose of our two temporary regions |
_DisposRgn |
MOVE.L ArrowRgn(A6),-(SP) |
_DisposRgn |
Exit UNLK A6 ; destroy the link |
MOVEA.L (SP)+,A0 ; pull off the return address |
ADDA.L #ParamSize,SP ; strip all of the caller's parameters |
JMP (A0) ; return to the caller |
DbgInfo AdjstCur ; this name will appear in the debugger |
ENDP |
END ; end of this source file |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14