CLUTSample.inc1.a

*
*   Apple Macintosh Developer Technical Support
*
*   CLUTSample
*
*   CLUTSample.inc1.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.
 
* ----------- DEBUGGING INFORMATION -------------
* This is used as a global switch to turn off the generation of debugging information.
* The MACRO "DbgInfo" will generate this debugging information if set to 1.
 
DebuggerInfo    EQU 1
 
 
* ================================================
* --------   MACRO DEFINITIONS SECTION  ----------
* ================================================
 
* ------------- GENERATE A PASCAL "CASE" OR "IF" SEQUENCE -------------
* The following macro is used to generate a branch based on an index value
* in a D-register with a value from 0 to N.  The branch is through a table
* of relative addresses also generated by this macro. The macro is called
* in one of two forms as follows:
 
*  {Form #1}    Case#       (Dreg,Default),case0,case1,...caseN
*  {Form #2}    Case#.<size>    (Dreg,IF),(cst0,case0),...,(cstN,caseN)
 
* In Form #1, the "Default" specifies a label for any omitted case labels not
* specified explicitly. The "case0", "case1",..."caseN" are case labels
* identifying the various cases to be processed.  A case label may be omitted,
* in which case the "Default" is used. The "Default" may also be omitted, but
* in that case all case labels must be specified. If there are fewer case labels
* than there are cases, but there are N possible values for the case index, the
* proper number of trailing commas must be supplied to generate the defaults.
 
* In Form #2, the default is specified as the word "IF".  In this form the macro
* generates a set of compares (CMPI's) and branches (BEQ) for each specified
* case (there is no implicit default).  Each case is a constant/label pair.
* The constant is compared (CMPI.W) and an branch is done (BEQ) to the case if
* the Dreg equals the constant.  A size may be specified for all the branches
* as a <size> attribute to the Case# call itself.  This must either be an "S"
* or "W" to generate BEQ.S's or BEQ.W's.  The default is for "S".
 
        MACRO
        Case#.&Size     &IdxDef
        PRINT       Push,NoMDir     ; only list generated code
        LCLA        &i      ; index to macro parameters
        LCLA        &n      ; total number of macro parameters
        LCLC        &Dreg,&Def  ; the Dreg and Default parameters
        LCLC        &sz         ; the <size> value
 
&Dreg       SETC        &IdxDef[1]  ; pick off 1st opnd of sublist
&Def        SETC        &IdxDef[2]  ; pick off 2nd opnd of sublist
&n      SETA        &Nbr(&Syslist)  ; done for efficiency
&i      SETA        2       ; cases start at 2nd parameter
 
 IF &UpCase(&Def) <> 'IF' THEN
.* Create the jump table and the index value
* -----------------------------------------------
    ADD         &Dreg,&Dreg
    MOVE        Case&SysNdx(&Dreg),&Dreg
    JMP         Case&SysNdx(&Dreg)
 
Case&SysNdx
    WHILE &i <= &n DO               ; process each case label
       IF &SysList[&i] <> '' THEN
        DC.W        &SysList[&i]-Case&SysNdx
       ELSE
        DC.W        &Def-Case&SysNdx
       ENDIF
       &i: SETA &i+1                ; count off parameter
    ENDWHILE
 ELSE                           ; process (Cst,lbl) pairs
 
.* Create a series of CMPI and BEQ instructions
* -----------------------------------------------
    &Sz: SETC &Default(&Size, 'S')          ; setup size attribute
    WHILE &i <= &n DO               ; process each (Cst,lbl) pair
       CMPI     #&SysList[&i,1],&Dreg
       BEQ.&Sz  &SysList[&i,2]
       &i: SETA &i+1                ; count off parameter
    ENDWHILE
 ENDIF
 
        PRINT   Pop                 ; restore original print status
        ENDM
 
 
* ------------- GENERATE DEBUGGER SYMBOL INFORMATION -------------
* This Macro will generate information for the debugger to read and display
* as its module name.  This aids in debugging Asm code while looking at it
* in the debugger.  This macro can only work if called at the end of stack
* frame.  The appearance of the Macro statement in the source code must occur
* immediately after the final "JMP   (A0)" or "RTS" instruction following the UNLINK.
* Spaces may be included in the name, but no quotes are allowed.
 
*  {Form #1}    DbgInfo     ModName
*  {Form #2}    DbgInfo.New Really Long Module Name For MacsBug 6.0
 
* There are now two naming conventions used in MacsBug, Form #1 is the older MacsBug,
* or TMON, and Form #2 is the newer MacsBug 6.0.  The older method would only
* allow for a fixed length of eight characters.  If a shorter name is passed to
* this Macro, it will extend the length to 8 chars with trailing spaces.
* MacsBug 6.0 will now allow for a variable length C type string. This Macro will
* create the proper DC statements and takes into account word alignment issues.
 
 
        MACRO
        DbgInfo.&Opt    &ModName#   ; the name to be used in the Debugger
        PRINT       Push,NoMDir     ; Only list generated code
        LCLC        &DbgName#   ; name to generate for MacsBug
        LCLC        &DbgTemp    ; temporary name variable
        LCLC        &New        ; variable used to test old vs. new
        LCLC        &S      ; variable used to save PRINT state
 
 IF DebuggerInfo THEN                       ; do we want debugging info?
    IF &ModName# ­ '' THEN                  ; did we get a module name?
    &New: SETC &UpCase(&Opt)                ; make option all upper case
    IF (&New = 'NEW') THEN                  ; do we want new style?
 
.* Create the new MacsBug naming convention
* -----------------------------------------------
       &DbgTemp: SETC   &ModName#           ; generate new type symbols
       IF &Len(&ModName#) < 32 THEN             ; if module name < 32 chars
        IF &Len(&ModName#) // 2 = 0 THEN        ; add space if even so that...
           &DbgTemp: SETC &Concat(&ModName#,' ')    ; string length plus length byte...
        ENDIF                       ; will align to word boundary
       &DbgName#: SETC &Concat(&Chr($80 + &Len(&ModName#)), &DbgTemp)
       ELSE                         ; Length > 32 characters
        IF &Len(&ModName#) // 2 = 1 THEN        ; add space if length is odd
           &DbgTemp: SETC &Concat(&ModName#,' ')
        ENDIF
       &DbgName#: SETC &Concat(&Chr($80), &Chr(&Len(&ModName#)), &DbgTemp)
       ENDIF
    ELSE                            ; make it the older style
 
.* Create the older MacsBug naming convention
* -----------------------------------------------
       IF &Len(&ModName#) < 8 THEN              ; if module name < 8 chars
        &DbgName#: SETC &Concat(&ModName#,'       ')    ; add at least 7 spaces
        &DbgName#: SETC &Concat(&Chr($80 + &ORD(&SubStr(&DbgName#,1,1))), &SubStr(&DbgName#,2,7))
       ELSE                         ; there are at least 8 chars
        &DbgName#: SETC &Concat(&Chr($80 + &ORD(&SubStr(&ModName#,1,1))), &SubStr(&ModName#,2,7))
       ENDIF
    ENDIF
 
.* Create the DC.B with the debugger name, and include the NULs if new MacsBug option
* -----------------------------------------------
    &S: SETC &Setting('STRING')     ; preserve STRING status
    IF &S ­ 'ASIS' THEN         ; only change it if not already ASIS
       STRING    ASIS
       DC.B      '&DbgName#'
       IF (&New = 'NEW') THEN
        DC.W        0       ; fake literal size for new MacsBug
       ENDIF
       STRING    &S
    ELSE
       DC.B      '&DbgName#'
       IF (&New = 'NEW') THEN
        DC.W        0       ; fake literal size for new MacsBug
       ENDIF
    ENDIF
   ENDIF
 ENDIF
 
        PRINT   Pop             ; restore original print status
        ENDM
 
 
* ================================================
* ---------------  EQUATE SECTION  ---------------
* ================================================
 
* Some various EQUATES we'll use throughout the program.
* -----------------------------------------------
False       EQU 0       ; the value of False
True        EQU $0100       ; and you thought True = 1, HA!
NIL     EQU 0       ; a NIL pointer to test against
 
ToolTrapBit EQU 11      ; this bit is on for Tool traps
WaitNextEvent   EQU $A860       ; the WaitNextEvent trap number
Unimplemented   EQU $A89F       ; the Unimplemented trap number
EnvironsVersion EQU 1       ; this is the version of the SysEnvirons we want
SleepValue  EQU $7FFFFFFF   ; the sleeping time ($7FFFFFFF = MaxLongInt)
SuspendResume   EQU 1       ; the suspend/resume event number of an OSEvent
NoEvents    EQU 0       ; no events mask
ExtremeNeg  EQU -32768      ; for wide open rects and regions, see AdjustCursor
ExtremePos  EQU 32767-1     ; -1 is because of a bug in regions, see AdjustCursor
 
* This is the minimum result from the following equation:
 
*   applLimit - applZone = minimum heap size
 
* for the application to run. It will insure that enough memory will
* be around for reasonable-sized scraps, FKEYs, etc. to exist with the
* application, and still give the application some 'breathing room'.
* To derive this number, we ran under a MultiFinder partition that was
* our requested minimum size, as given in the 'SIZE' resource.
 
MinHeap     EQU 21*1024     ; minimum heap size in bytes
 
* This is the minimum exceptable result from PurgeSpace, when called
* at initialization time, for the application to run. This number acts
* as a double-check to insure that there really is enough memory for the
* application to run, including what has been taken up already by
* pre-loaded resources, the scrap, code, and other sundry memory blocks.
 
MinSpace    EQU 8*1024      ; minimum stack space in bytes
 
 
* The following equates use for resources.  That's why they have a "r" in front.
* -----------------------------------------------
rMenuBar    EQU 128     ; application's menu bar
rUserAlert  EQU 129     ; error alert for user
rWindow     EQU 128     ; application's window
rAboutAlert EQU 128     ; about alert
 
* The following equates are for menu definitions, obviously.
* -----------------------------------------------
AppleMenu   EQU 128     ;  Apple menu
AboutItem   EQU 1
 
FileMenu    EQU 129     ;  File menu
NewItem     EQU 1
CloseItem   EQU 2
QuitItem    EQU 4
 
* -----------------------------------------------
DITopLeft   EQU $00500070   ; position of Disk Init dialogs
 
* ================================================
* ----------------  RECORD TYPES  ----------------
* ================================================
* This section is declaring record structures.  These records are
* templates.  No data is allocated at this point.  These are just
* structures, similar to Pascal TYPEs.  They simply generate a list
* of equate offsets.  Since none of these types are defined already
* in the MPW AIncludes, we'll need to define them.
 
* ------------- MOUSE POINT TYPE -------------
 
Point       RECORD  0
v       DS.W    1
h       DS.W    1
        ORG     v
vh      DS.W    h
        ENDR
 
* ------------- RECTANGLE TYPE -------------
 
Rect        RECORD  0
Top         DS.W    1
Left        DS.W    1
Bottom      DS.W    1
Right       DS.W    1
        ORG     Top
TopLeft     DS.L    1
BotRight    DS.L    1
        ENDR
 
* ------------- BITMAP TYPE -------------
 
BitMap      RECORD  0
baseAddr    DS.L    1
rowBytes    DS.W    1
bounds      DS.L    Rect
        ENDR
 
* ------------- EVENT RECORD TYPE -------------
 
EventRecord     RECORD  0
What        DS.W    1
Message     DS.L    1
When        DS.L    1
Where       DS.L    Point
Modify      DS.W    1
        ENDR
 
* ------------- THE QUICKDRAW WORLD -------------
 
MyQDGlobals RECORD  0,DECREMENT
thePort     DS.L    1
White       DS.B    8
Black       DS.B    8
Gray        DS.B    8
LtGray      DS.B    8
DkGray      DS.B    8
Arrow       DS.B    cursRec
ScreenBits  DS.B    BitMap
RandSeed    DS.L    1
        ORG     -GrafSize
        ENDR
 
* ------------- ALL OF OUR GLOBAL DATA -------------
* Note the minimal amount of globals we're using.  Data such as
* the EventRecord, WindowRecords, etc. do not belong in global data
* allocation.  Only data that basically doesn't change through out the
* execution of the program is considered global.  The boolean flags are
* global, since they affect the state of the program at any given time.
* Also note that any appearance of a DS outside of a stack frame will
* be allocated off of A5 and becomes part of global data storage.
 
AppGlobals  RECORD  0       ; this is our global data storage
Stopped     DS.W    1       ; boolean for the state of the light
HasWNEvent  DS.W    1       ; boolean for WaitNextEvent trap, see ForceEnvirons
InBackground    DS.W    1       ; boolean for if in background, see OSEvent
StopRect    DS  Rect        ; rect for the Stop light, set from a resource
GoRect      DS  Rect        ; rect for the Go light, set from a resource
Mac     DS  SysEnvRec   ; the system environment record, see ForceEnvirons
        ENDR
 
* ------------- CLUT Window Data TYPEs -------------
 
ClutWData   RECORD  0
UpdateRtn   DS.L    1
MouseDnRtn  DS.L    1
ClutWDataSize   Equ *
        ENDR