Include build script, System and MPW

This commit is contained in:
Elliot Nunn 2019-06-29 22:03:22 +08:00
parent 3d158703bf
commit 93dfc883a1
1378 changed files with 461892 additions and 0 deletions

View File

@ -0,0 +1,626 @@
TITLE 'Count - An MPW tool using -model far'
*-------------------------------------------------------------------------------------------
*
* NAME
* Count.a -- count lines and characters
*
* SYNOPSIS
* Count [-l] [-c] [file…]
*
* DESCRIPTION
* "Count" counts the lines and characters in its input, and writes the
* counts to standard output. If no files are specified standard input is
* read. If more than one file is specified, separate counts are written
* for each file, one per line, preceeded by the file name. A total is also
* written following the list of files.
*
* COPYRIGHT
* Copyright Apple Computer, Inc. 1985-1990
* All rights reserved.
*
* Demonstration of use of "32-bit everything" addressing.
* for MPW 3.2b2/3.
* Briefly, "32-bit everything" allows the use of absolute long addressing mode of
* 680x0instructions in Macintosh code, to refer to both code and data. Normally,
* because everything in the Macintosh is considered relocatable, this addressing mode
* could not be used; the only "absolute" addresses were low memory globals (and there
* have been warnings about using those!). However, with a patch to LoadSeg to allow
* for a different format of the CODE 0 segment jump table, and to allow run-time patching
* of these "absolute" addresses, it is now possible to use the absolute long addressing
* mode. (Note that the linker adds the patch installer/de-installer code to the user's
* code, so the effect is localized). Thus, the MPW compilers and linker allow, uh,
* "relocatable" (by runtime patch) "absolute" (by 680x0 addressing mode) instructions.
* You invoke the feature by using the "-model far" option on the command line for
* compilers, assembler and linker.
* In addition to the "-model far", the user must enable the feature on a "per-instruction"
* basis. This program is a modified version of the count program provided
* in the :Aexamples:folder to demonstrate how to use the Assembler
* to get the 32-bit everything references. Unlike the compilers, the user must specify --
* by explicitly using the absolute addressing mode syntax ("(Mylabel).L") -- which
* instructions will use this feature. Further, the label used must be "imported".
* To make life easier, there are "implicit" imports provided by the Assembler:
* Within the same file, preceding data references are implicitly imported,
* as are all preceding module names (you cannot, at this time) use a 32-bit reference
* on to refer to a module name within that module, however). Note that the use of 32-bit
* addressing in the Assembler is independent of the CODEREFS and DATAREFS directive
* settings, and that the 32-bit displacements of the 68020+ addressing modes are not
* affected -- for backward compatibility.
* Within this program, then, you will see absolute references to all kinds of data
* references: simple Data references, qualified field references and field references
* under a 'WITH' statement. Since "data" is implicitly imported, no matter where it is
* found, Main data and data defined in the 'DATA' section of a code module can be
* successfully reference.
* Additionally, but more simply, there are numerous JSRs and JMPs to other code
* modules, showing both intrasegment and intersegment branching. To show that it is
* possible to mix-n-match, some references are made which use A5 and PC-relative
* addressing. J. Kettenhofen, Cupertino, 10/15/90.
*
*-------------------------------------------------------------------------------------------
CASE OBJ
INCLUDE 'traps.a' ; for Pack7
INCLUDE 'packmacs.a' ; for NumToStr, which calls Pack7
INCLUDE 'intenv.a' ; so we can get our args, open files, etc.
INCLUDE 'signal.a' ; so we can handle 'Command-.'
IMPORT INITCURSORCTL ; to init the spinning beach ball
IMPORT ROTATECURSOR ; for the spinning beach ball
RC_Normal EQU 0
RC_ParmErrs EQU 1
RC_Abort EQU 2 ; Return codes
;SIGINT EQU 2
EOLChar EQU $0D ; the Return character marks the end of line
STRING Pascal ; length byte strings
BufSize EQU 1024 ; size of input buffer
* global data--these declarations outside of any module are allocated and accessed
* relative to register A5
Globals RECORD
ArgV DS.L 1 ; the address of our arguments
ArgC DS.L 1 ; the number of our arguments
RetCode DC.B RC_Normal ; set to RC_ …
CRStr DC.W $010D ; a 'string' that is a return character
Interrupted DC.B 0 ; not interrupted yet
progname DS.L 1 ; the address of our name
NumFiles DC.W 0 ; the number of files to process
WriteChars DC.B 0 ; TRUE if the user wants line count
WriteLines DC.B 0 ; TRUE if the user wants char count
Opts DC.B 0 ; TRUE if user has selected either line or char
LineCount DC.L 0
CharCount DC.L 0
TotalLines DC.L 0
TotalChars DC.L 0
Max DC.B 5 ; length of 'Total' string, or the longest filename
myBuf DS.B BufSize ; for reading from the file
curByte DC.W -1 ; the current offset in myBuf
lastByte DS.W 1 ; last valid byte in myBuf
ENDR
*******************************************************************
* ROUTINE WriteStrings
* FUNCTION calls write for an arbitrary number of strings
* INPUT a NIL pointer on stack, followed by arbitrary number of string pointers,
* and the file descriptor
* OUTPUT none
* NOTES PROCEDURE WriteStrings (NIL, Str^ …,FD);
*******************************************************************
SEG 'Write'
WriteStrings PROC
Link A6,#0 ; set up a stack frame
Move.L A2,-(SP) ; and save one permanent register
LEA 8(A6),A2 ; point A2 at first (last) parameter
* next, create a call block for the write routine on the stack
Clr.L -(SP) ; set the length to zero
SubQ #8,SP ; make room for the buffer and fd
Move.L (A2)+,(SP) ; put the file descriptor in its place
* now pull the arguments off the stack and write them out
@1 Move.L (A2)+,D0 ; get the string pointer
BEQ.S @0 ; the list of strings is NIL terminated
Move.L D0,A0 ; move the pointer so we can use it
Move.B (A0)+,11(SP) ; to move the length byte into the length arg
Move.L A0,4(SP) ; move the pointer into the buffer arg
JSR (write).L ; write it--CASE is significant
BRA.S @1 ; and try again
* done writing. Clean up the stack and return
@0 Move.L A2,A1 ; we still need this
Move.L -4(A6),A2 ; restore A2
UNLK A6 ; throw away the scratch stack stuff
Move.L (SP),A0 ; get the return address
Move.L A1,SP ; throw away the parameters
JMP (A0) ; and bail out
ENDPROC
*******************************************************************
* ROUTINE Stop
* FUNCTION terminates execution
* INPUT Message(A6)--error message to display on exit
* OUTPUT Tool execution is terminated--return to MPW shell
* NOTES call with a JMP, not a JSR--it doesn't return to caller anyway
*******************************************************************
SEG 'STOP'
Stop PROC
* don't bother to save permanent registers--we're never going back to the caller
WITH Globals
MoveQ #0,D0
Move.B (RetCode).L,D0 ; we'll return this status
TST.B Interrupted
BEQ.S @1
Move.B #RC_Abort,D0 ; unless we were interrupted
@1 Move.L D0,-(SP)
JSR (exit).L ; (does not return)
ENDWITH
ENDPROC
*******************************************************************
* ROUTINE Intr
* FUNCTION sets the global Interrupted to TRUE--passed to the Runtime routine
* INPUT
* OUTPUT Interrupted is set TRUE
* NOTES
*******************************************************************
Intr PROC
ST Globals.Interrupted
RTS
ENDPROC
*******************************************************************
* ROUTINE SyntaxError
* FUNCTION Report a syntax error for the command line
* INPUT above(A7)--pointers to strings to append to the error message
* OUTPUT displays error message and calls Stop to terminate program execution
* NOTES call with a JMP, not a JSR--it doesn't return anyway
*******************************************************************
SyntaxError PROC
WITH Globals
DC.W $A9FF
PEA #' - '
Move.L (progName).L,-(SP)
PEA #'### '
PEA DiagnosticFD
JSR (WriteStrings).L ; finish writing the error line
CLR.L -(SP)
PEA CrStr
PEA #' [-l] [-c] [files…].'
Move.L progName,-(SP)
PEA #'# Usage - '
PEA (DiagnosticFD).L
JSR (WriteStrings).L ; and write the 'usage' line
JMP (Stop).L
ENDWITH
ENDPROC
*******************************************************************
* ROUTINE LetterOpt
* FUNCTION Set a letter option
* INPUT D0--char
* D4--ArgVIndex
* A1--address of current option
* OUTPUT if char = valid option, set option flag, else syntaxerror
* NOTES PROCEDURE LetterOpt(Opt: Char; VAR ArgVIndex: Integer);
* ArgVIndex can be updated by this routine to skip arguments to options
*******************************************************************
LetterOpt PROC
Cmp.B #'l',D0
BEQ.S @0
Cmp.B #'L',D0 ; -l?
BNE.S @1
@0 ST (Globals.WriteLines).L ; means only lines
ADDQ #1,Globals.Opts ; yes, an option has been selected
RTS
@1 Cmp.B #'c',D0 ; -c?
BEQ.S @2
Cmp.B #'C',D0
BNE.S @3
@2 ST Globals.WriteChars ; means only characters
ADDQ #1,Globals.Opts ; yes, an option has been selected
RTS
@3 Clr.L -(SP) ; otherwise it's a bad option
PEA Globals.CRStr
PEA #'" is not an option.'
Move.L A1,-(SP) ; pointer to current option
PEA #'"' ; the leading quote around the option
JMP SyntaxError
* SyntaxError never returns
ENDPROC
*******************************************************************
* ROUTINE Init
* FUNCTION Tool initalization
* INPUT
* OUTPUT
* NOTES PROCEDURE Init;
*******************************************************************
SEG 'INIT'
Init PROC
ForPascal EQU 1 ; Make envp & argv strings "Pascal" format
; (preceded with a length byte)
; Comments about the Init.SF structure
; 1. TEMPLATE. Note that this is a template, not a record;
; it is equivalent to a 'struct' in C or a type
; definition in Pascal. It does not allocate space.
; 2. DECREMENT. It is used to describe a "stack frame". Since
; the stack grows downward, the keyword 'Decrement' is used.
; 3. The bracketed parameter, '{OldA6}'. This tells the Assembler to
; calculate field offsets using this field as the '0' offset.
; This is explained more fully in the MPW Assembler Manual.
; 4. SIZE field. The size field here is the calculated as the
; difference from 0...this turns out to be -4, which
; turns out to be the amount of space that we have to
; allocate on the stack via a Link instruction for our
; local parameters.
; If we were to have incoming parameters, then we
; could allocate them above the OldA6 field; what
; order the parameters are found, and their relation
; to the routine Return Address varies between C and
; Pascal; appendices in the MPW language manuals contain
; more details about language calling conventions.
InitSF RECORD {OldA6},DECREMENT
ShellRet DS.L 1 ;'RetPC' in Ch. 12 of MPW Manual
RetAddress DS.L 1
OldA6 DS.L 1
EnvP DS.L 1
Size EQU *
ENDR
WITH Globals
Link A6,#InitSF.Size
PEA ForPascal ; optimized Move.L #1,-(SP)
PEA InitSF.EnvP(A6) ; for Shell Exported variables
PEA ArgV ; Address to store ptr to Command Line Arguments
PEA ArgC ; Address to store ptr to # of Cmd Line Args.
Move.L InitSF.ShellRet(A6),-(SP)
JSR (_RTInit).L ; get things set up
LEA InitSF.Size(A6),SP ; throw away the arguments
PEA Intr ; our interrupt handler
Move.L #SIGINT,-(SP)
JSR (signal).L ; so we can handle user interrupts
* D0 has handle to prevSig, which we will ignore
LEA InitSF.Size(A6),SP ; throw away the arguments
MoveM.L A2/D3-D4,-(SP) ; let's do some ArgV processing
Move.L ArgV,A2
Move.L ArgC,D3
Move.L (A2)+,progName ; we now have a global that points to our name
Move.B #RC_ParmErrs,(RetCode).L
MoveQ #0,D4 ; ArgVIndex := 0;
@0 AddQ #1,D4
Cmp.L D4,D3
BLE.S DoneArgOptions
Move.L (A2)+,A0 ; get the next arg
Move.L A0,A1 ; keep a pointer to the start of the string
Move.B (A0)+,D1 ; get the len
BEQ.S @0 ; arg := ''; get the next one
Move.B (A0)+,D0
Cmp.B #'-',D0 ; is it an option?
BNE.S @1
Move.B (A0)+,D0
JSR (LetterOpt).L
* caller to LetterOpt can check if ArgIndex changed--if so, skip the increment of ArgIndex
BRA.S @0 ; go again
@1 AddQ #1,NumFiles ; bump the file count
Cmp.B Max,D1 ; a new longest name?
BLE.S @0
Move.B D1,Max ; a new max
BRA.S @0
DoneArgOptions
Move.B #RC_Normal,RetCode ; parameters ok so far
Clr.L -(SP)
JSR (InitCursorCtl).L ; initialize the spinning cursor
Tst.B Interrupted ; user break yet?
BEQ.S @3
JMP Stop
@3 MoveM.L (SP)+,A2/D3-D4
UNLK A6
RTS
ENDWITH
ENDPROC
*******************************************************************
* ROUTINE PrintCount
* FUNCTION writes the filename (if needed), linecount and/or charcount to standard output
* INPUT pointer to the filename in A2 (if counting multiple files)
* OUTPUT
* NOTES
*******************************************************************
PrintCount PROC
PrintSF RECORD 0,DECREMENT
LineBuf DS.B 256
tempStr DS.B 10
MaxBlanks DS.B 1
ALIGN
Size EQU *
ENDR
LINK A6,#PrintSF.Size
MoveM.L D6/A3,-(SP)
Move.W #(256/4)-1,D0 ; fill LineBuf with blanks
Move.L #' ',D1
LEA PrintSF.LineBuf(A6),A0
@0 Move.L D1,(A0)+
DBRA D0,@0
WITH Globals
MoveQ #3,D6 ; skip first three blanks
LEA 4+PrintSF.LineBuf(A6),A3 ; A3 is the current offset into lineBuf
Cmp.W #1,NumFiles ; >1 if more than one file
BLE.S noName
Move.L D7,A0 ; D7 points to the current filename
MoveQ #0,D1
Move.B (A0)+,D1 ; get the length byte
Add.B D1,D6 ; update the new length
MoveQ #0,D0
Move.B Max,D0 ; Max is the longest name
Sub.B D1,D0 ; D0 is how much shorter current is than max
AddQ #3,D0
Add.B D0,D6 ; update the counter
BRA.S @2 ; zero base the length
@1 Move.B (A0)+,(A3)+
@2 DBRA D1,@1 ; move in the filename
Add.W D0,A3 ; and update our roving pointer
noName
ENTRY DoLines,DoChars,WriteBuf
; if no options selected, print both lines and chars.
TST.B Opts
BNE.S @0
JSR DoLines ; insert lines into buffer
JSR DoChars ; insert chars into buffer
BRA.S @Exit
@0 TST.B WriteLines ; do we want to print the line count?
BEQ.S @1
JSR DoLines ; insert lines into buffer
@1 TST.B WriteChars
BEQ.S @Exit
JSR DoChars ; insert chars into buffer
@Exit
Move.B D6,PrintSF.lineBuf(A6) ; set the length byte
CLR.L -(SP) ; set up the stack for WriteStrings
PEA CRStr
PEA PrintSF.linebuf(A6)
PEA OutputFD
JSR WriteStrings
MoveM.L (SP)+,D6/A3
UNLK A6
RTS
DoLines
Move.L lineCount,D0
add.w #10,D6 ; update counter
JMP WriteBuf
DoChars
MOVE.L charcount,D0
add.w #13,D6 ; add field length and 3 blanks to counter
JMP WriteBuf
WriteBuf
LEA PrintSF.tempStr(A6),A0
_NumToString
MoveQ #0,D1
Move.B (A0)+,D1
MoveQ #10,D0 ; we'll say this field is 10 long
Sub.B D1,D0 ; D0 := field length-length of numstring
Add.W D0,A3 ; skip the extra padding
BRA.S @2 ; zero base by doing the DBCC first
@1 Move.B (A0)+,(A3)+
@2 DBRA D1,@1 ; move in the number
RTS
ENDWITH
ENDPROC
*******************************************************************
* ROUTINE PrintTotals
* FUNCTION writes the summary line to standard output
* INPUT
* OUTPUT
* NOTES calls PrintCount to print the totals if appropriate
*******************************************************************
SEG 'PrintTotals'
PrintTotals PROC
Cmp.W #1,Globals.numFiles
BGT.S @0
RTS ; do nothing if only one file
@0 LEA #'Total',A0
Move.L A0,D7 ; our new 'filename'
Move.L Globals.totallines,Globals.linecount
Move.L Globals.totalchars,Globals.charcount
JSR (PrintCount).L ; recycled code
RTS
ENDPROC
*******************************************************************
* ROUTINE GetChar
* FUNCTION reads from the file in hunks, and hands out a character at a time
* INPUT fd: long in D4--the file descriptor for the file to read
* OUTPUT the next character in D0--zero = TRUE means end of file
* NOTES
*******************************************************************
SEG 'GetChar'
GetChar PROC
WITH Globals
Move.W curByte,D1 ; get the current offset
BPL.S @0 ; we have a valid block currently
@1 PEA BufSize ; Move.L #BufSize,-(SP)--count
PEA mybuf ; where
Move.L D4,-(SP) ; the file descriptor
JSR (read).L ; read the next block
LEA 12(SP),SP ; clean up the stack
MoveQ #0,D1 ; start at the beginning again
Move.W D0,lastByte
BNE.S @2 ; end of file?
RTS ; pass the zero flag back to the caller
@0 Move.W lastByte,D0 ; get the last valid byte
@2 Cmp.W D0,D1
BGE.S @1
LEA mybuf,A0
Move.B 0(A0,D1),D0 ; read the next character
AddQ.W #1,D1
Move.W D1,curByte ; update curByte
RTS
ENDWITH
ENDPROC
*******************************************************************
* ROUTINE CountFile (fd:filedescriptor)
* FUNCTION counts the lines and characters in fd
* INPUT fd: long--the file descriptor for the file to count
* OUTPUT charcount, linecount, totalchars, totallines updated
* NOTES
*******************************************************************
SEG 'CountFile'
CountFile PROC
WITH globals
CLR.L linecount
Move.L (SP)+,A1 ; save the return address
Move.L (SP),D0 ; and the file descriptor
Move.L A1,(SP) ; return the return address
MoveM.L D4-D7,-(SP)
Move.L D0,D4 ; save the fd for the getchar routine
MoveQ #0,D7 ; initialize our counter registers
MoveQ #0,D6
ReadLoop
JSR getchar
BEQ.S fileEnd ; zero means no more bytes to read
AddQ.L #1,D7 ; otherwise bump the char counter
Move.B D0,D5 ; save the char in a permanent register
CMP.B #EOLChar,D5 ; bump linecount?
BNE.S ReadLoop
AddQ.L #1,D6 ; yes
Move.L D6,-(SP)
JSR (RotateCursor).L ; spin the ball
Tst.B Interrupted ; user break yet?
BEQ.S ReadLoop ; no--continue
JMP (Stop).L ; abort mission
fileEnd
CMP.B #EOLChar,D5 ; was the last character read a line end?
BEQ.S @0
TST.L D7 ; have we counted any characters
BEQ.S @0 ; no--don't increment line count
AddQ.L #1,D6
@0 Move.L D6,lineCount ; update globals and leave
Move.L D7,charCount
Add.L D6,totallines
Add.L D7,totalchars
MoveM.L (SP)+,D4-D7
RTS
ENDPROC
*******************************************************************
* ROUTINE Count
* FUNCTION the MAIN proc--calls Init, then processes the files
* INPUT
* OUTPUT
* NOTES
*******************************************************************
SEG 'MAIN'
Count MAIN
IMPORT c2pstr,p2cstr
WITH Globals
JSR (Init).L
Move.L ArgV,A2
ADDQ #4,A2 ; skip the program name
Move.L (A2)+,D7 ; set the cc's
BNE.S @0 ; otherwise count stdin
* CountStdIn
Clr.L -(SP) ; we don't need to open standard input
JSR (CountFile).L
JSR (PrintCount).L
JMP (Stop).L
@1 Move.L (A2)+,D7 ; set the cc's
BEQ.S ShowTotals ; ArgV is NIL terminated
@0 Move.L D7,A0
Move.B (A0)+,D0 ; pick up the length byte
BEQ.S @1 ; zero length--next, please
Move.B (A0)+,D1 ; now the first charcter
Cmp.B #'-',D1 ; an option--already handled by Init
BEQ.S @1
* otherwise we have a file to process
Move.L D7,-(SP) ; convert the filename to a C string
JSR (p2cstr).L
PEA O_RDONLY
Move.L D7,-(SP)
JSR (open).L ; open the file
Move.L D0,D6 ; save the result--fd or error
JSR (c2pstr).L ; love those length bytes
LEA 12(SP),SP ; throw away the arguments
Move.L D6,-(SP) ; push the fd
BMI.S BailOut ; an error if negative
JSR (CountFile).L
JSR (PrintCount).L
BRA.S @1
ShowTotals
JSR (PrintTotals).L
JMP (Stop).L
BailOut CLR.L (SP) ; space came from move D6 above
PEA CRStr
Move.L D7,-(SP)
PEA #' - could not open file '
Move.L progName,-(SP)
PEA #'### '
PEA DiagnosticFD ; optimized Move.L #DiagnosticFD,-(SP)
JSR (WriteStrings).L
CLR.L -(SP)
PEA CRStr
PEA #' [-l] [-c] [files…].'
Move.L progName,-(SP)
PEA #'# Usage - '
PEA DiagnosticFD ; optimized Move.L #DiagnosticFD,-(SP)
JSR (WriteStrings).L
Move.B #RC_ParmErrs,RetCode
JMP (Stop).L
ENDWITH
ENDPROC
END

View File

@ -0,0 +1 @@
TEXTMPS

View File

@ -0,0 +1,18 @@
data 'MPSR' (1005) {
$"0009 4D6F 6E61 636F 0000 0000 0000 0000" /* ..Monaco........ */
$"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */
$"0000 0006 0004 002A 0003 0142 01E3 002A" /* .......*...B...* */
$"0003 0142 01E3 A42B A620 0000 0000 0000" /* ...B...+. ...... */
$"0000 0000 0000 0100" /* ........ */
};
data 'MPSR' (1008) {
$"002A 0003 0142 01E3 002A 0003 0142 01E3" /* .*...B...*...B.. */
$"0000 0000 0000 0000 0000 0000 0000" /* .............. */
};
data 'vers' (2, purgeable) {
$"0320 8000 0000 0333 2E32 074D 5057 2033" /* . .....3.2.MPW 3 */
$"2E32" /* .2 */
};

View File

@ -0,0 +1,78 @@
/*
Count.r - commando resource file
Copyright Apple Computer, Inc. 1987
All rights reserved.
Count [-l] [-c] [file] < file > counts
-l # write only line counts
-c # write only character counts
*/
#include "Cmdo.r"
resource 'cmdo' (128) {
{
245, /* Height of dialog */
"Counts the lines and characters in its input, and writes the results to standard output.",
{
notDependent {}, RadioButtons {
{
{25, 250, 40, 410},
"Lines and characters",
"",
Set,
"Count the number of lines and characters in the input file(s) (or standard input).",
{40, 250, 55, 340},
"Lines",
"-l",
NotSet,
"Only count the number of lines in the input file(s) (or standard input).",
{55, 250, 70, 340},
"Characters",
"-c",
NotSet,
"Only count the number of characters in the input file(s) (or standard input).",
}
},
notDependent {}, TextBox {
gray,
{17, 240, 75, 450},
"Count"
},
Or {{-4}}, MultiFiles {
"Files to count…",
"Select the files to count. If no files are specified Count reads "
"from standard input.",
{36, 35, 56, 200},
"Files to count:",
"",
MultiInputFiles {
{TEXT},
FilterTypes,
"Only text files",
"All files",
}
},
Or {{-3}}, Redirection {
StandardInput,
{85, 30}
},
notDependent {}, Redirection {
StandardOutput,
{85, 180}
},
notDependent {}, Redirection {
DiagnosticOutput,
{85, 330}
},
notDependent {}, TextBox {
gray,
{80, 25, 125, 450},
"Redirection"
},
}
}
};

View File

@ -0,0 +1 @@
TEXTMPS

View File

@ -0,0 +1,18 @@
data 'MPSR' (1005) {
$"0009 4D6F 6E61 636F 001F 0228 001F 0229" /* ..Monaco...(...) */
$"01BF 0009 01BF 000A 01C0 000A 01C0 0229" /* ...............) */
$"0000 0006 0004 002A 0003 0142 01E3 002A" /* .......*...B...* */
$"0003 0142 01E3 A42B A620 0000 0000 0000" /* ...B...+. ...... */
$"0000 0000 0000 0100" /* ........ */
};
data 'MPSR' (1008) {
$"002A 0003 0142 01E3 002A 0003 0142 01E3" /* .*...B...*...B.. */
$"0000 0000 0000 0000 0000 0000 0000" /* .............. */
};
data 'vers' (2, purgeable) {
$"0320 8000 0000 0333 2E32 074D 5057 2033" /* . .....3.2.MPW 3 */
$"2E32" /* .2 */
};

View File

@ -0,0 +1,23 @@
*******************************************************************************
*
* File FStubs.a - Stubs for floating point runtime library routines
* not used by MPW tools.
*
* Copyright Apple Computer, Inc. 1986-1987
* All rights reserved.
*
*******************************************************************************
CASE ON
* Floating Point Conversion Routines
*
* These routines, called by printf, are only necessary if floating point
* formatting is used.
ecvt PROC EXPORT
RTS
fcvt PROC EXPORT
RTS
END

View File

@ -0,0 +1 @@
TEXTMPS

View File

@ -0,0 +1,18 @@
data 'MPSR' (1005) {
$"0009 4D6F 6E61 636F 0000 000C 0001 EDF4" /* ..Monaco........ */
$"000A 8001 0000 0068 7FFF 6E64 0000 0060" /* .......h..nd...` */
$"4431 0006 0004 002A 0003 0142 01E3 002A" /* D1.....*...B...* */
$"0003 0142 01E3 A42B A620 0000 0000 0000" /* ...B...+. ...... */
$"0000 0000 0000 0100" /* ........ */
};
data 'MPSR' (1008) {
$"002A 0003 0142 01E3 002A 0003 0142 01E3" /* .*...B...*...B.. */
$"0000 0000 0000 0000 0000 0000 0000" /* .............. */
};
data 'vers' (2, purgeable) {
$"0320 8000 0000 0333 2E32 074D 5057 2033" /* . .....3.2.MPW 3 */
$"2E32" /* .2 */
};

View File

@ -0,0 +1,25 @@
# MakeFile - Make instructions for assembly language examples.
#
# Copyright Apple Computer, Inc. 1986-1990
# All rights reserved.
#
# This makefile builds a '32-bit everything' Assembler version of
# the MPW Tool 'count'.
# The sample MPW Tool: Count
Count ƒƒ Count.r
Rez Count.r -o Count -append
Count ƒƒ Count.a.o FStubs.a.o
Link -w -model far -c 'MPS ' -t MPST Count.a.o FStubs.a.o ∂
-sn INTENV=Main ∂
-sn %A5Init=Main ∂
"{Libraries}"Stubs.o ∂
"{Libraries}"Runtime.o ∂
"{Libraries}"ToolLibs.o ∂
"{Libraries}"Interface.o ∂
-o Count
Count.a.o ƒ Count.a
Asm -model far Count.a
FStubs.a.o ƒ FStubs.a
Asm FStubs.a

View File

@ -0,0 +1 @@
TEXTMPS

View File

@ -0,0 +1,18 @@
data 'MPSR' (1005) {
$"0009 4D6F 6E61 636F 0000 0034 0001 E9CC" /* ..Monaco...4.... */
$"002C FC18 FC18 0197 01C6 FC18 FC18 FC19" /* .,.............. */
$"7FFF 0006 0004 002A 0003 0142 01E3 002A" /* .......*...B...* */
$"0003 0142 01E3 A42B A620 0000 0000 0000" /* ...B...+. ...... */
$"0000 0000 0000 0100" /* ........ */
};
data 'MPSR' (1008) {
$"002A 0003 0142 01E3 002A 0003 0142 01E3" /* .*...B...*...B.. */
$"0000 0000 0000 0000 0000 0000 0000" /* .............. */
};
data 'vers' (2, purgeable) {
$"0320 8000 0000 0333 2E32 074D 5057 2033" /* . .....3.2.MPW 3 */
$"2E32" /* .2 */
};

View File

@ -0,0 +1,567 @@
*-------------------------------------------------------------------------------------------
*
* NAME
* Count.a -- count lines and characters
*
* SYNOPSIS
* Count [-l] [-c] [file…]
*
* DESCRIPTION
* "Count" counts the lines and characters in its input, and writes the
* counts to standard output. If no files are specified standard input is
* read. If more than one file is specified, separate counts are written
* for each file, one per line, preceeded by the file name. A total is also
* written following the list of files.
*
* COPYRIGHT
* Copyright Apple Computer, Inc. 1985-1987
* All rights reserved.
*
* MODIFICATION HISTORY
* 10/15/90 JAK No options and both options produce
* char and line output.
*-------------------------------------------------------------------------------------------
CASE OBJ
INCLUDE 'traps.a' ; for Pack7
INCLUDE 'packmacs.a' ; for NumToStr, which calls Pack7
INCLUDE 'intenv.a' ; so we can get our args, open files, etc.
INCLUDE 'signal.a' ; so we can handle 'Command-.'
IMPORT INITCURSORCTL ; to init the spinning beach ball
IMPORT ROTATECURSOR ; for the spinning beach ball
RC_Normal EQU 0
RC_ParmErrs EQU 1
RC_Abort EQU 2 ; Return codes
;SIGINT EQU 2
EOLChar EQU $0D ; the Return character marks the end of line
STRING Pascal ; length byte strings
BufSize EQU 1024 ; size of input buffer
* global data--these declarations outside of any module are allocated and accessed
* relative to register A5
Globals RECORD
ArgV DS.L 1 ; the address of our arguments
ArgC DS.L 1 ; the number of our arguments
RetCode DC.B RC_Normal ; set to RC_ …
CRStr DC.W $010D ; a 'string' that is a return character
Interrupted DC.B 0 ; not interrupted yet
progname DS.L 1 ; the address of our name
NumFiles DC.W 0 ; the number of files to process
WriteChars DC.B 0 ; TRUE if the user wants line count
WriteLines DC.B 0 ; TRUE if the user wants char count
Opts DC.B 0 ; TRUE if user has selected either line or char
LineCount DC.L 0
CharCount DC.L 0
TotalLines DC.L 0
TotalChars DC.L 0
Max DC.B 5 ; length of 'Total' string, or the longest filename
myBuf DS.B BufSize ; for reading from the file
curByte DC.W -1 ; the current offset in myBuf
lastByte DS.W 1 ; last valid byte in myBuf
ENDR
*******************************************************************
* ROUTINE WriteStrings
* FUNCTION calls write for an arbitrary number of strings
* INPUT a NIL pointer on stack, followed by arbitrary number of string pointers,
* and the file descriptor
* OUTPUT none
* NOTES PROCEDURE WriteStrings (NIL, Str^ …,FD);
*******************************************************************
WriteStrings PROC
Link A6,#0 ; set up a stack frame
Move.L A2,-(SP) ; and save one permanent register
LEA 8(A6),A2 ; point A2 at first (last) parameter
* next, create a call block for the write routine on the stack
Clr.L -(SP) ; set the length to zero
SubQ #8,SP ; make room for the buffer and fd
Move.L (A2)+,(SP) ; put the file descriptor in its place
* now pull the arguments off the stack and write them out
@1 Move.L (A2)+,D0 ; get the string pointer
BEQ.S @0 ; the list of strings is NIL terminated
Move.L D0,A0 ; move the pointer so we can use it
Move.B (A0)+,11(SP) ; to move the length byte into the length arg
Move.L A0,4(SP) ; move the pointer into the buffer arg
JSR write ; write it--CASE is significant
BRA.S @1 ; and try again
* done writing. Clean up the stack and return
@0 Move.L A2,A1 ; we still need this
Move.L -4(A6),A2 ; restore A2
UNLK A6 ; throw away the scratch stack stuff
Move.L (SP),A0 ; get the return address
Move.L A1,SP ; throw away the parameters
JMP (A0) ; and bail out
ENDPROC
*******************************************************************
* ROUTINE Stop
* FUNCTION terminates execution
* INPUT Message(A6)--error message to display on exit
* OUTPUT Tool execution is terminated--return to MPW shell
* NOTES call with a JMP, not a JSR--it doesn't return to caller anyway
*******************************************************************
Stop PROC
* don't bother to save permanent registers--we're never going back to the caller
WITH Globals
MoveQ #0,D0
Move.B RetCode,D0 ; we'll return this status
TST.B Interrupted
BEQ.S @1
Move.B #RC_Abort,D0 ; unless we were interrupted
@1 Move.L D0,-(SP)
JSR exit ; (does not return)
ENDWITH
ENDPROC
*******************************************************************
* ROUTINE Intr
* FUNCTION sets the global Interrupted to TRUE--passed to the Runtime routine
* INPUT
* OUTPUT Interrupted is set TRUE
* NOTES
*******************************************************************
Intr PROC
ST Globals.Interrupted
RTS
ENDPROC
*******************************************************************
* ROUTINE SyntaxError
* FUNCTION Report a syntax error for the command line
* INPUT above(A7)--pointers to strings to append to the error message
* OUTPUT displays error message and calls Stop to terminate program execution
* NOTES call with a JMP, not a JSR--it doesn't return anyway
*******************************************************************
SyntaxError PROC
WITH Globals
PEA #' - '
Move.L progName,-(SP)
PEA #'### '
PEA DiagnosticFD
JSR WriteStrings ; finish writing the error line
CLR.L -(SP)
PEA CrStr
PEA #' [-l] [-c] [files…].'
Move.L progName,-(SP)
PEA #'# Usage - '
PEA DiagnosticFD
JSR WriteStrings ; and write the 'usage' line
JMP Stop
ENDWITH
ENDPROC
*******************************************************************
* ROUTINE LetterOpt
* FUNCTION Set a letter option
* INPUT D0--char
* D4--ArgVIndex
* A1--address of current option
* OUTPUT if char = valid option, set option flag, else syntaxerror
* NOTES PROCEDURE LetterOpt(Opt: Char; VAR ArgVIndex: Integer);
* ArgVIndex can be updated by this routine to skip arguments to options
*******************************************************************
LetterOpt PROC
Cmp.B #'l',D0
BEQ.S @0
Cmp.B #'L',D0 ; -l?
BNE.S @1
@0 ST Globals.WriteLines ; means only lines
ADDQ #1,Globals.Opts ; yes, an option has been selected
RTS
@1 Cmp.B #'c',D0 ; -c?
BEQ.S @2
Cmp.B #'C',D0
BNE.S @3
@2 ST Globals.WriteChars ; means only characters
ADDQ #1,Globals.Opts ; yes, an option has been selected
RTS
@3 Clr.L -(SP) ; otherwise its a bad option
PEA Globals.CRStr
PEA #'" is not an option.'
Move.L A1,-(SP) ; pointer to current option
PEA #'"' ; the leading quote around the option
JMP SyntaxError
* SyntaxError never returns
ENDPROC
*******************************************************************
* ROUTINE Init
* FUNCTION Tool initalization
* INPUT
* OUTPUT
* NOTES PROCEDURE Init;
*******************************************************************
Init PROC
ForPascal EQU 1
InitSF RECORD {OldA6},DECREMENT
ShellRet DS.L 1
RetAddress DS.L 1
OldA6 DS.L 1
EnvP DS.L 1
Size EQU *
ENDR
WITH Globals
Link A6,#InitSF.Size
PEA ForPascal ; optimized Move.L #1,-(SP)
PEA InitSF.EnvP(A6)
PEA ArgV
PEA ArgC
Move.L InitSF.ShellRet(A6),-(SP)
JSR _RTInit ; get things set up
LEA InitSF.Size(A6),SP ; throw away the arguments
PEA Intr ; our interrupt handler
Move.L #SIGINT,-(SP)
JSR signal ; so we can handle user interrupts
* D0 has handle to prevSig, which we will ignore
LEA InitSF.Size(A6),SP ; throw away the arguments
MoveM.L A2/D3-D4,-(SP) ; let's do some ArgV processing
Move.L ArgV,A2
Move.L ArgC,D3
Move.L (A2)+,progName ; we now have a global that points to our name
Move.B #RC_ParmErrs,RetCode
MoveQ #0,D4 ; ArgVIndex := 0;
@0 AddQ #1,D4
Cmp.L D4,D3
BLE.S DoneArgOptions
Move.L (A2)+,A0 ; get the next arg
Move.L A0,A1 ; keep a pointer to the start of the string
Move.B (A0)+,D1 ; get the len
BEQ.S @0 ; arg := ''; get the next one
Move.B (A0)+,D0
Cmp.B #'-',D0 ; is it an option?
BNE.S @1
Move.B (A0)+,D0
JSR LetterOpt
* caller to LetterOpt can check if ArgIndex changed--if so, skip the increment of ArgIndex
BRA.S @0 ; go again
@1 AddQ #1,NumFiles ; bump the file count
Cmp.B Max,D1 ; a new longest name?
BLE.S @0
Move.B D1,Max ; a new max
BRA.S @0
DoneArgOptions
Move.B #RC_Normal,RetCode ; parameters ok so far
Clr.L -(SP)
JSR InitCursorCtl ; initialize the spinning cursor
Tst.B Interrupted ; user break yet?
BEQ.S @3
JMP Stop
@3 MoveM.L (SP)+,A2/D3-D4
UNLK A6
RTS
ENDWITH
ENDPROC
*******************************************************************
* ROUTINE PrintCount
* FUNCTION writes the filename (if needed), linecount and/or charcount to standard output
* INPUT pointer to the filename in A2 (if counting multiple files)
* OUTPUT
* NOTES
*******************************************************************
PrintCount PROC
PrintSF RECORD 0,DECREMENT
LineBuf DS.B 256
tempStr DS.B 10
MaxBlanks DS.B 1
ALIGN
Size EQU *
ENDR
LINK A6,#PrintSF.Size
MoveM.L D6/A3,-(SP)
Move.W #(256/4)-1,D0 ; fill LineBuf with blanks
Move.L #' ',D1
LEA PrintSF.LineBuf(A6),A0
@0 Move.L D1,(A0)+
DBRA D0,@0
WITH Globals
MoveQ #3,D6 ; skip first three blanks
LEA 4+PrintSF.LineBuf(A6),A3 ; A3 is the current offset into lineBuf
Cmp.W #1,NumFiles ; >1 if more than one file
BLE.S noName
Move.L D7,A0 ; D7 points to the current filename
MoveQ #0,D1
Move.B (A0)+,D1 ; get the length byte
Add.B D1,D6 ; update the new length
MoveQ #0,D0
Move.B Max,D0 ; Max is the longest name
Sub.B D1,D0 ; D0 is how much shorter current is than max
AddQ #3,D0
Add.B D0,D6 ; update the counter
BRA.S @2 ; zero base the length
@1 Move.B (A0)+,(A3)+
@2 DBRA D1,@1 ; move in the filename
Add.W D0,A3 ; and update our roving pointer
noName
ENTRY DoLines,DoChars,WriteBuf
; if no options selected, print both lines and chars.
TST.B Opts
BNE.S @0
JSR DoLines ; insert lines into buffer
JSR DoChars ; insert chars into buffer
BRA.S @Exit
@0 TST.B WriteLines ; do we want to print the line count?
BEQ.S @1
JSR DoLines ; insert lines into buffer
@1 TST.B WriteChars
BEQ.S @Exit
JSR DoChars ; insert chars into buffer
@Exit
Move.B D6,PrintSF.lineBuf(A6) ; set the length byte
CLR.L -(SP) ; set up the stack for WriteStrings
PEA CRStr
PEA PrintSF.linebuf(A6)
PEA OutputFD
JSR WriteStrings
MoveM.L (SP)+,D6/A3
UNLK A6
RTS
DoLines
Move.L lineCount,D0
add.w #10,D6 ; update counter
JMP WriteBuf
DoChars
MOVE.L charcount,D0
add.w #13,D6 ; add field length and 3 blanks to counter
JMP WriteBuf
WriteBuf
LEA PrintSF.tempStr(A6),A0
_NumToString
MoveQ #0,D1
Move.B (A0)+,D1
MoveQ #10,D0 ; we'll say this field is 10 long
Sub.B D1,D0 ; D0 := field length-length of numstring
Add.W D0,A3 ; skip the extra padding
BRA.S @2 ; zero base by doing the DBCC first
@1 Move.B (A0)+,(A3)+
@2 DBRA D1,@1 ; move in the number
RTS
ENDWITH
ENDPROC
*******************************************************************
* ROUTINE PrintTotals
* FUNCTION writes the summary line to standard output
* INPUT
* OUTPUT
* NOTES calls PrintCount to print the totals if appropriate
*******************************************************************
PrintTotals PROC
Cmp.W #1,Globals.numFiles
BGT.S @0
RTS ; do nothing if only one file
@0 LEA #'Total',A0
Move.L A0,D7 ; our new 'filename'
Move.L Globals.totallines,Globals.linecount
Move.L Globals.totalchars,Globals.charcount
JSR PrintCount ; recycled code
RTS
ENDPROC
*******************************************************************
* ROUTINE GetChar
* FUNCTION reads from the file in hunks, and hands out a character at a time
* INPUT fd: long in D4--the file descriptor for the file to read
* OUTPUT the next character in D0--zero = TRUE means end of file
* NOTES
*******************************************************************
GetChar PROC
WITH Globals
Move.W curByte,D1 ; get the current offset
BPL.S @0 ; we have a valid block currently
@1 PEA BufSize ; Move.L #BufSize,-(SP)--count
PEA mybuf ; where
Move.L D4,-(SP) ; the file descriptor
JSR read ; read the next block
LEA 12(SP),SP ; clean up the stack
MoveQ #0,D1 ; start at the beginning again
Move.W D0,lastByte
BNE.S @2 ; end of file?
RTS ; pass the zero flag back to the caller
@0 Move.W lastByte,D0 ; get the last valid byte
@2 Cmp.W D0,D1
BGE.S @1
LEA mybuf,A0
Move.B 0(A0,D1),D0 ; read the next character
AddQ.W #1,D1
Move.W D1,curByte ; update curByte
RTS
ENDWITH
ENDPROC
*******************************************************************
* ROUTINE CountFile (fd:filedescriptor)
* FUNCTION counts the lines and characters in fd
* INPUT fd: long--the file descriptor for the file to count
* OUTPUT charcount, linecount, totalchars, totallines updated
* NOTES
*******************************************************************
CountFile PROC
WITH globals
CLR.L linecount
Move.L (SP)+,A1 ; save the return address
Move.L (SP),D0 ; and the file descriptor
Move.L A1,(SP) ; return the return address
MoveM.L D4-D7,-(SP)
Move.L D0,D4 ; save the fd for the getchar routine
MoveQ #0,D7 ; initialize our counter registers
MoveQ #0,D6
ReadLoop JSR getchar
BEQ.S fileEnd ; zero means no more bytes to read
AddQ.L #1,D7 ; otherwise bump the char counter
Move.B D0,D5 ; save the char in a permanent register
CMP.B #EOLChar,D5 ; bump linecount?
BNE.S ReadLoop
AddQ.L #1,D6 ; yes
Move.L D6,-(SP)
JSR RotateCursor ; spin the ball
Tst.B Interrupted ; user break yet?
BEQ.S ReadLoop ; no--continue
JMP Stop ; abort mission
fileEnd CMP.B #EOLChar,D5 ; was the last character read a line end?
BEQ.S @0
TST.L D7 ; have we counted any characters
BEQ.S @0 ; no--don't increment line count
AddQ.L #1,D6
@0 Move.L D6,lineCount ; update globals and leave
Move.L D7,charCount
Add.L D6,totallines
Add.L D7,totalchars
MoveM.L (SP)+,D4-D7
RTS
ENDPROC
*******************************************************************
* ROUTINE Count
* FUNCTION the MAIN proc--calls Init, then processes the files
* INPUT
* OUTPUT
* NOTES
*******************************************************************
Count MAIN
IMPORT c2pstr,p2cstr
WITH Globals
JSR Init
Move.L ArgV,A2
ADDQ #4,A2 ; skip the program name
Move.L (A2)+,D7 ; set the cc's
BNE.S @0 ; otherwise count stdin
* CountStdIn
Clr.L -(SP) ; we don't need to open standard input
JSR CountFile
JSR PrintCount
JMP Stop
@1 Move.L (A2)+,D7 ; set the cc's
BEQ.S ShowTotals ; ArgV is NIL terminated
@0 Move.L D7,A0
Move.B (A0)+,D0 ; pick up the length byte
BEQ.S @1 ; zero length--next, please
Move.B (A0)+,D1 ; now the first charcter
Cmp.B #'-',D1 ; an option--already handled by Init
BEQ.S @1
* otherwise we have a file to process
Move.L D7,-(SP) ; convert the filename to a C string
JSR p2cstr
PEA O_RDONLY
Move.L D7,-(SP)
JSR open ; open the file
Move.L D0,D6 ; save the result--fd or error
JSR c2pstr ; love those length bytes
LEA 12(SP),SP ; throw away the arguments
Move.L D6,-(SP) ; push the fd
BMI.S BailOut ; an error if negative
JSR CountFile
JSR PrintCount
BRA.S @1
ShowTotals
JSR PrintTotals
JMP Stop
BailOut CLR.L (SP) ; space came from move D6 above
PEA CRStr
Move.L D7,-(SP)
PEA #' - could not open file '
Move.L progName,-(SP)
PEA #'### '
PEA DiagnosticFD ; optimized Move.L #DiagnosticFD,-(SP)
JSR WriteStrings
CLR.L -(SP)
PEA CRStr
PEA #' [-l] [-c] [files…].'
Move.L progName,-(SP)
PEA #'# Usage - '
PEA DiagnosticFD ; optimized Move.L #DiagnosticFD,-(SP)
JSR WriteStrings
Move.B #RC_ParmErrs,RetCode
JMP Stop
ENDWITH
ENDPROC
END

View File

@ -0,0 +1 @@
TEXTMPS

View File

@ -0,0 +1,18 @@
data 'MPSR' (1005) {
$"0009 4D6F 6E61 636F 006C 6573 3A41 4578" /* ..Monaco.les:AEx */
$"616D 706C 6573 3A43 6F75 6E74 2E61 0022" /* amples:Count.a." */
$"0000 0006 0004 002A 0003 0142 01E3 002A" /* .......*...B...* */
$"0003 0142 01E3 A42B A620 0000 0000 0000" /* ...B...+. ...... */
$"0000 0000 0000 0100" /* ........ */
};
data 'MPSR' (1008) {
$"002A 0003 0142 01E3 002A 0003 0142 01E3" /* .*...B...*...B.. */
$"0000 0000 0000 0000 0000 0000 0000" /* .............. */
};
data 'vers' (2, purgeable) {
$"0320 8000 0000 0333 2E32 074D 5057 2033" /* . .....3.2.MPW 3 */
$"2E32" /* .2 */
};

View File

@ -0,0 +1,78 @@
/*
Count.r - commando resource file
Copyright Apple Computer, Inc. 1987
All rights reserved.
Count [-l] [-c] [file] < file > counts
-l # write only line counts
-c # write only character counts
*/
#include "Cmdo.r"
resource 'cmdo' (128) {
{
245, /* Height of dialog */
"Counts the lines and characters in its input, and writes the results to standard output.",
{
notDependent {}, RadioButtons {
{
{25, 250, 40, 410},
"Lines and characters",
"",
Set,
"Count the number of lines and characters in the input file(s) (or standard input).",
{40, 250, 55, 340},
"Lines",
"-l",
NotSet,
"Only count the number of lines in the input file(s) (or standard input).",
{55, 250, 70, 340},
"Characters",
"-c",
NotSet,
"Only count the number of characters in the input file(s) (or standard input).",
}
},
notDependent {}, TextBox {
gray,
{17, 240, 75, 450},
"Count"
},
Or {{-4}}, MultiFiles {
"Files to count…",
"Select the files to count. If no files are specified Count reads "
"from standard input.",
{36, 35, 56, 200},
"Files to count:",
"",
MultiInputFiles {
{TEXT},
FilterTypes,
"Only text files",
"All files",
}
},
Or {{-3}}, Redirection {
StandardInput,
{85, 30}
},
notDependent {}, Redirection {
StandardOutput,
{85, 180}
},
notDependent {}, Redirection {
DiagnosticOutput,
{85, 330}
},
notDependent {}, TextBox {
gray,
{80, 25, 125, 450},
"Redirection"
},
}
}
};

View File

@ -0,0 +1 @@
TEXTMPS

View File

@ -0,0 +1,18 @@
data 'MPSR' (1005) {
$"0009 4D6F 6E61 636F 006F 756E 742E 7200" /* ..Monaco.ount.r. */
$"2200 0000 0000 00B0 0078 00C0 00DA 8800" /* "........x...... */
$"0000 0006 0004 002A 0003 0142 01E3 002A" /* .......*...B...* */
$"0003 0142 01E3 A42B A620 0000 0000 0000" /* ...B...+. ...... */
$"0000 0000 0000 0100" /* ........ */
};
data 'MPSR' (1008) {
$"002A 0003 0142 01E3 002A 0003 0142 01E3" /* .*...B...*...B.. */
$"0000 0000 0000 0000 0000 0000 0000" /* .............. */
};
data 'vers' (2, purgeable) {
$"0320 8000 0000 0333 2E32 074D 5057 2033" /* . .....3.2.MPW 3 */
$"2E32" /* .2 */
};

View File

@ -0,0 +1,23 @@
*******************************************************************************
*
* File FStubs.a - Stubs for floating point runtime library routines
* not used by MPW tools.
*
* Copyright Apple Computer, Inc. 1986-1987
* All rights reserved.
*
*******************************************************************************
CASE ON
* Floating Point Conversion Routines
*
* These routines, called by printf, are only necessary if floating point
* formatting is used.
ecvt PROC EXPORT
RTS
fcvt PROC EXPORT
RTS
END

View File

@ -0,0 +1 @@
TEXTMPS

View File

@ -0,0 +1,18 @@
data 'MPSR' (1005) {
$"0009 4D6F 6E61 636F 0053 7475 6273 2E61" /* ..Monaco.Stubs.a */
$"0022 0000 0000 01D7 7FFF 01B4 0000 022B" /* .".............+ */
$"7FFF 0006 0004 002A 0003 0142 01E3 002A" /* .......*...B...* */
$"0003 0142 01E3 A42B A620 0000 0000 0000" /* ...B...+. ...... */
$"0000 0000 0000 0100" /* ........ */
};
data 'MPSR' (1008) {
$"002A 0003 0142 01E3 002A 0003 0142 01E3" /* .*...B...*...B.. */
$"0000 0000 0000 0000 0000 0000 0000" /* .............. */
};
data 'vers' (2, purgeable) {
$"0320 8000 0000 0333 2E32 074D 5057 2033" /* . .....3.2.MPW 3 */
$"2E32" /* .2 */
};

View File

@ -0,0 +1,159 @@
Instructions - The Assembly Language Examples
Copyright Apple Computer, Inc. 1987-1990
All rights reserved.
About the Examples
Three sample assembly language programs are included with MPW:
an application, a tool, and a desk accessory:
Sample - a simple MultiFinder-Aware Sample application
Count - an MPW tool
Memory - a sample desk accessory
The source files for each of these examples are in the
"Examples:AExamples:" folder. In addition, a makefiles
that contains the commands needed to build each of the
examples is provided in the same folder.
Building the Examples
You can easily build each of the sample programs using the Directory
and Build menus. (See Chapter 2 of the MPW Reference.)
Set the default directory to "AExamples:"
The simplest way to do this is to select from the Directory menu
the menu item that ends in "AExamples:". You can also set the
default directory by using the Directory and SetDirectory commands.
Build the program
You can use any of the four Build items at the bottom of the Build
menu to build the program you have selected. Each of these menu
items displays a dialog box that asks for the name of the program
you want to build. When this dialog box appears, type the name of
one of the sample programs (Sample, Count, or Memory).
Each of the Build menu items behaves slightly differently:
Build… - The program is automatically built. The commands
used, and any error messages, are displayed in the Worksheet.
Only files that have been changed since you last built the
program are compiled, saving considerable time.
Full Build… - The program is completely rebuilt, ignoring
any object files or intermediate files that may already exist
from a previous build. The commands used, and any errors, are
displayed in the Worksheet.
Show Build Commands… - The commands needed to build the program
are written to the Worksheet, but not executed. You can then
select any or all of the commands and execute them yourself.
(To execute the commands select them and press Enter.)
Show Full Build Commands… - The commands needed to completely
rebuild the program are written to the Worksheet. This is a
convenient way to see all of the commands used in building
the program you have selected.
Note: For more information about building the sample programs, see
Chapter 2 of the MPW Reference.
Sample - A Simple MultiFinder-Aware Sample Application
Sample is an example application that demonstrates how to initialize
the commonly used toolbox managers, operate successfully under
MultiFinder, handle desk accessories and create windows.
The source for Sample provides an excellent framework for basing
new applications. The source is contained in the files Sample.a
and SampleMisc.a and Sample.inc1.a, resource descriptions are
contained in the files Sample.h and Sample.r. The make dependency
file is named Sample.make.
To build Sample, simply select the line below and press Enter.
BuildProgram Sample ∑∑ {Worksheet}
To execute Sample, select the line below and press Enter.
Sample
Count - A Sample MPW Tool
Count, a tool that runs in the MPW environment, counts characters and
lines in files. A version of Count is included with MPW, and is
documented in the MPW Reference, Part II. The source for Count is in
the files Count.a, FStubs.a, and Count.r. MakeFile contains the
commands for building Count.
To build Count, simply select the line below and press Enter.
BuildProgram Count ∑∑ {Worksheet}
To test Count, try counting the characters in file Count.a.
Count -c Count.a
Memory - A Sample Desk Accessory
Memory is a sample desk accessory written in assembly language. It
displays the memory available in the application and system heaps,
and on the boot disk. MakeFile contains the commands for building
Memory.
To build Memory, simply select the line below and press Enter.
BuildProgram Memory ∑∑ {Worksheet}
The build process puts the desk accessory into a Font/DA Mover file.
To install the Memory desk accessory, use the Font/DA Mover to copy
resource Memory from the file Memory into the System file.
After quitting the Font/DA Mover and returning to the MPW Shell, select
"Memory" from the Apple menu.
Writing Your Own Programs
After building (and perhaps modifying) the sample programs, you will
undoubtedly want to write a program of your own. Use the New… item in
the File menu, to create the source files. Remember that assembly
language source filenames should end in .a.
Create Build Commands… - The Create Build Commands… item in the
Build menu runs a script that creates a makefile containing the
commands for building programs written in C, Assembly Language, Pascal,
and/or Rez. Selecting Create Build Commands… displays a dialog box that
allows you to enter information about your program. Type the program's
name, select its source files by clicking the Files… button, and click
one of the radio buttons to indicate your choice of an application, tool,
or desk accessory.
Create Build Commands… puts the makefile for your program in the file
<program>.make. Now you can use the Build menu to build and rebuild
your program, just as with the examples.
Larger Programs - If you add source files as your program grows,
use Create Build Commands… again to add the new source files to the build
instructions. If you out-grow the capabilities of the simple Create
Build Commands… script (perhaps by using tools other than Asm, C, Pascal,
Rez, and Link in your builds) you can modify the makefile yourself.
Modifying the Directory and Build Menus - The Directory and Build
menus are both implemented using scripts written in the MPW Shell
command language. This has the big advantage that you can modify
or customize them to match the way you work.

View File

@ -0,0 +1 @@
TEXTMPS

View File

@ -0,0 +1,18 @@
data 'MPSR' (1005) {
$"0009 4D6F 6E61 636F 006E 7374 7275 6374" /* ..Monaco.nstruct */
$"696F 6E73 0022 0000 6374 696F 6E73 00FF" /* ions."..ctions.. */
$"FFFB 0006 0004 002A 0003 0142 01E3 002A" /* .......*...B...* */
$"0003 0142 01E3 A42B A620 0000 0000 0000" /* ...B...+. ...... */
$"0000 0000 0000 0100" /* ........ */
};
data 'MPSR' (1008) {
$"002A 0003 0142 01E3 002A 0003 0142 01E3" /* .*...B...*...B.. */
$"0000 0000 0000 0000 0000 0000 0000" /* .............. */
};
data 'vers' (2, purgeable) {
$"0320 8000 0000 0333 2E32 074D 5057 2033" /* . .....3.2.MPW 3 */
$"2E32" /* .2 */
};

View File

@ -0,0 +1,32 @@
# MakeFile - Make instructions for assembly language examples.
#
# Copyright Apple Computer, Inc. 1986-1987
# All rights reserved.
#
# This makefile builds:
# The sample MPW Tool: Count
# The sample desk accessory: Memory
#
Count ƒƒ Count.r
Rez Count.r -o Count -append
Count ƒƒ Count.a.o FStubs.a.o
Link -w -c 'MPS ' -t MPST Count.a.o FStubs.a.o ∂
-sn INTENV=Main ∂
-sn %A5Init=Main ∂
"{Libraries}"Stubs.o ∂
"{Libraries}"Runtime.o ∂
"{Libraries}"ToolLibs.o ∂
"{Libraries}"Interface.o ∂
-o Count
Count.a.o ƒ Count.a
Asm Count.a
FStubs.a.o ƒ FStubs.a
Asm FStubs.a
Memory ƒ Memory.a.o
Link -da -t DFIL -c DMOV -rt DRVR=12 -sg Memory ∂
Memory.a.o -o Memory
Memory.a.o ƒ Memory.a
Asm Memory.a

View File

@ -0,0 +1 @@
TEXTMPS

View File

@ -0,0 +1,18 @@
data 'MPSR' (1005) {
$"0009 4D6F 6E61 636F 0061 6B65 4669 6C65" /* ..Monaco.akeFile */
$"0022 0000 6B65 4669 6C65 0020 6F66 2049" /* ."..keFile. of I */
$"0000 0006 0004 002A 0003 0142 01E3 002A" /* .......*...B...* */
$"0003 0142 01E3 A42B A620 0000 0000 0000" /* ...B...+. ...... */
$"0000 0000 0000 0100" /* ........ */
};
data 'MPSR' (1008) {
$"002A 0003 0142 01E3 002A 0003 0142 01E3" /* .*...B...*...B.. */
$"0000 0000 0000 0000 0000 0000 0000" /* .............. */
};
data 'vers' (2, purgeable) {
$"0320 8000 0000 0333 2E32 074D 5057 2033" /* . .....3.2.MPW 3 */
$"2E32" /* .2 */
};

View File

@ -0,0 +1,270 @@
***************************************************************************
****
**** MEMORY DESK ACCESSORY - A sample DA written in MPW 68000 Assembly
****
**** Copyright Apple Computer, Inc. 1985-1987
**** All rights reserved.
****
***************************************************************************
STRING PASCAL
MAIN
INCLUDE 'QuickEqu.a'
INCLUDE 'ToolEqu.a'
INCLUDE 'SysEqu.a'
INCLUDE 'Traps.a'
; Desk accessories (drivers) cannot use global variables in the normal sense.
; Usually, a handle is allocated and stuffed into dCtlStorage and global
; variables are stored in this handle. However, in this example, the globals
; are allocated at the end of the desk accessory's window record. Since the
; window record is always nonrelocatable storage, the variables will never move.
; This record structure below defines the layout of our "global variables."
GlobalVars RECORD windowSize ; Put variables at end of window rec
aString DS.B 28 ; vol names must be < 28 char
aNumStr DS.B 10 ; sufficient for 10 GB of space
GlobalSize EQU *-GlobalVars ; size of my globals
ENDR
WITH GlobalVars
aPBPtr EQU D7
**************************** DESK ACCESSORY ENTRY **************************
DAEntry ; See Device Manager IM:2
DC.B (1<<dCtlEnable) + (1<<dNeedTime) ; periodic,control flags set
DC.B 0 ; Lower byte is unused
DC.W 5*60 ; 5 sec periodic update
DC.W (1<<updatEvt) ; Handle only update events
DC.W 0 ; No menu for this accessory
DC.W DAOpen-DAEntry ; Open routine
DC.W DADone-DAEntry ; Prime - unused
DC.W DACtl-DAEntry ; Control
DC.W DADone-DAEntry ; Status - unused
DC.W DAClose-DAEntry ; Close
DATitle
DC.B 'Free Mem (#Bytes)' ; DA Name (& Window Title)
ALIGN 2 ; Word align
************************ DESK ACCESSORY OPEN ROUTINE ***********************
DAOpen
MOVEM.L A1-A4,-(SP) ; preserve A1-A4
MOVE.L A1,A4 ; MOVE DCE pointer to a reg
SUBQ.L #4,SP ; FUNCTION = GrafPtr
MOVE.L SP,-(SP) ; push a pointer to it
_GetPort ; push it on top of stack
TST.L DCtlWindow(A4) ; do we have a window?
BNE.S StdReturn ; If so, return, Else…
******************************* NEW WINDOW ROUTINE *************************
MOVE.L #windowSize+GlobalSize,D0
_NewPtr ; allocate space for record
SUBQ #4,SP ; FUNCTION = windowPtr
MOVE.L A0,-(SP) ; address of storage
PEA theWindow ; boundsRect
PEA DATitle ; title
CLR.W -(SP) ; visible flag FALSE
MOVE.W #noGrowDocProc,-(SP) ; window proc
MOVE.L #-1,-(SP) ; window in front
MOVE.B #1,-(SP) ; goAway box TRUE
CLR.L -(SP) ; refCon is 0
_NewWindow
MOVE.L (SP)+,A0
MOVE.L A0,DCtlWindow(A4) ; save windowPtr
MOVE.W DCtlRefNum(A4),WindowKind(A0) ; system window
_MaxMem
StdReturn
_SetPort ; old port on stack
MOVEM.L (SP)+,A1-A4 ; restore regs
************************ DESK ACCESSORY DONE ROUTINE ***********************
DADone
MOVEQ #0,D0 ; return no error
RTS ; all done, exit
************************ DESK ACCESSORY CLOSE ROUTINE **********************
DAClose
MOVEM.L A1-A4,-(SP) ; preserve A1-A4
MOVE.L A1,A4 ; MOVE DCE ptr to A4
SUBQ.L #4,SP ; FUNCTION = GrafPtr
MOVE.L SP,-(SP) ; push a pointer to it
_GetPort ; get it, now it's on TOS
MOVE.L DCtlWindow(A4),-(SP) ; push the window
_DisposWindow ; dispose of the window
CLR.L DCtlWindow(A4) ; mark DCE properly
BRA.S StdReturn ; all done with close, exit
********************** DESK ACCESSORY CONTROL ROUTINE **********************
DACtl
MOVE.L A4,-(SP) ; preserve reg
MOVE.L A1,A4 ; move DCE ptr to A4
MOVE.W CSCode(A0),D0 ; get the control opCode
SUB.W #accEvent,D0 ; = 64? (event)
BEQ.S DoCtlEvent
SUB.W #1,D0 ; = 65? (periodic)
BEQ.S DoPeriodic
CtlDone
MOVE.L A4,A1 ; put DCE ptr back in A1
MOVE.L (SP)+,A4 ; restore reg
MOVEQ #0,D0 ; return no error
MOVE.L JIODone,-(SP) ; jump to IODone
RTS
************************** EVENT HANDLING ROUTINE **************************
DoCtlEvent
MOVE.L A3,-(SP) ; save reg
MOVE.L CSParam(A0),A3 ; get the event pointer
MOVE.W EvtNum(A3),D0 ; get the event number
SUBQ #updatEvt,D0 ; is it an update?
BNE.S CtlEvtDone ; If not, exit
MOVE.L EvtMessage(A3),-(SP) ; push windowPtr
_BeginUpdate ; begin the update operation
MOVE.L EvtMessage(A3),-(SP) ; push windowPtr again
_SetPort
BSR.S DrawWindow ; draw our items
MOVE.L EvtMessage(A3),-(SP) ; one more time
_EndUpdate ; end of update
CtlEvtDone
MOVE.L (SP)+,A3 ; restore reg
BRA.S CtlDone ; exit
**************************** PERIODIC ROUTINE *****************************
DoPeriodic
MOVE.L DCtlWindow(A4),-(SP) ; set the port
_SetPort
BSR.S DrawWindow ; draw our window every 5s
BRA.S CtlDone
****************************** FONT METRICS *******************************
DrawWindow
MOVE.W #SrcCopy,-(SP) ; source mode
_TextMode
MOVE.W #Monaco,-(SP) ; Monaco
_TextFont
MOVE.W #9,-(SP) ; 9 point
_TextSize
MOVE.W #1,-(SP) ; bold
_TextFace
********************** WRITE APPLICATION HEAP FREEMEM *********************
MOVE.W #6,-(SP)
MOVE.W #10,-(SP)
_MoveTo
PEA #'AppHeap: '
_DrawString
_FreeMem ; free memory -> D0
JSR PrintNum ; draw our free mem
************************* WRITE SYSTEM HEAP FREEMEM ***********************
PEA #' SysHeap: '
_DrawString
_FreeMem SYS ; free memory -> D0
JSR PrintNum ; draw our free sys mem
***************************** WRITELN VOL INFO ****************************
PEA #' Disk: '
_DrawString
MOVE.L #ioHVQElSize,D0 ; size of HFS ParamBlock
_NewPtr CLEAR ; NewPtr -> A0
BNE.S Exit ; IF Error THEN Exit
MOVE.L A0,aPBPtr ; save PBPtr in D7
MOVE.L DCtlWindow(A4),A1 ; get window rec pointer
LEA aString(A1),A1 ; address of string buffer
MOVE.L A1,ioVNPtr(A0) ; ioVNPtr = Volume Name
_HGetVInfo ; _GetVolInfo info -> A0^
MOVE.L aPBPtr,A0
MOVE.L ioVAlBlkSiz(A0),D1 ; block size in D1
MOVE.W ioVFrBlk(A0),D2 ; free blocks in D2
MOVE.W D1,D0 ; 32 bit * 16 bit multiply
MULU.W D2,D0 ; right half of size
SWAP D1
MOVE.W D1,D3
MULU.W D2,D3 ; left half of size
SWAP D3
ADD.L D3,D0 ; total bytes free on vol
JSR PrintNum ; write # bytes free
PEA #' free on '
_DrawString
MOVE.W #4,-(SP) ; underlined
_TextFace
MOVE.L aPBPtr,A0
MOVE.L ioVNPtr(A0),-(SP) ; offset for volName
_DrawString
MOVE.L aPBPtr,A0 ; free the memory
_DisposPtr
Exit
RTS
***************************** SUBROUTINES ****************************
PrintNum
; Binary integer to be drawn at CurPenPos in D0 on entry
; number drawn in plain text, bolding restored afterwords
MOVE.L D0,D6 ; for safe keeping
CLR.W -(SP) ; plain text
_TextFace
MOVE.L D6,D0 ; and back again
MOVE.L DCtlWindow(A4),A0 ; get window rec pointer
LEA aNumStr(A0),A0 ; get buffer address
CLR.W -(SP) ; selector for NumToString
_Pack7 ; Binary-Decimal Package
MOVE.L A0,-(SP) ; push the pointer to the str
_DrawString
MOVE.W #1,-(SP) ; bold text restored
_TextFace
RTS
******************************* DATA AREA **********************************
theWindow DC.W 322,10,338,500 ; window top,left,bottom,right
ENDWITH
END

View File

@ -0,0 +1 @@
TEXTMPS

View File

@ -0,0 +1,18 @@
data 'MPSR' (1005) {
$"0009 4D6F 6E61 636F 0065 6D6F 7279 2E61" /* ..Monaco.emory.a */
$"0022 0000 0045 1C84 0080 000E 0094 0056" /* ."...E.........V */
$"FF00 0006 0004 002A 0003 0142 01E3 002A" /* .......*...B...* */
$"0003 0142 01E3 A42B A620 0000 0000 0000" /* ...B...+. ...... */
$"0000 0000 0000 0100" /* ........ */
};
data 'MPSR' (1008) {
$"002A 0003 0142 01E3 002A 0003 0142 01E3" /* .*...B...*...B.. */
$"0000 0000 0000 0000 0000 0000 0000" /* .............. */
};
data 'vers' (2, purgeable) {
$"0320 8000 0000 0333 2E32 074D 5057 2033" /* . .....3.2.MPW 3 */
$"2E32" /* .2 */
};

View File

@ -0,0 +1,987 @@
*
* Apple Macintosh Developer Technical Support
*
* MultiFinder-Aware Simple Sample Application
*
* Sample
*
* Sample.a - Assembler Source
*
* Copyright © Apple Computer, Inc. 1989-1990
* All rights reserved.
*
* Versions:
* 1.00 08/88
* 1.01 11/88
* 1.02 04/89 MPW 3.1
* 1.03 02/90 MPW 3.2
*
* Components:
* Sample.a Feb. 1, 1990
* Sample.inc1.a Feb. 1, 1990
* SampleMisc.a Feb. 1, 1990
* Sample.r Feb. 1, 1990
* Sample.h Feb. 1, 1990
* Sample.make Feb. 1, 1990
*
* Sample is an example application that demonstrates how to
* initialize the commonly used toolbox managers, operate
* successfully under MultiFinder, handle desk accessories,
* and create, grow, and zoom windows.
*
* It does not by any means demonstrate all the techniques
* you need for a large application. In particular, Sample
* does not cover exception handling, multiple windows/documents,
* sophisticated memory management, printing, or undo. All of
* these are vital parts of a normal full-sized application.
*
* This application is an example of the form of a Macintosh
* application; it is NOT a template. It is NOT intended to be
* used as a foundation for the next world-class, best-selling,
* 600K application. A stick figure drawing of the human body may
* be a good example of the form for a painting, but that does not
* mean it should be used as the basis for the next Mona Lisa.
*
* We recommend that you review this program or TESample before
* beginning a new application.
* This example program is to be considered an introduction to coding in the
* MPW Assembly language. This sample program demonstrates the use of RECORD,
* PROC, WITH, MACROs, IMPORT, and other coding practices used by MPW. Although
* this code will not be compatible with other assemblers, there is enough code
* contained within the procedures that demonstrate 68000 programming on the Mac.
* The main purpose of this example is to have an easy to understand sample
* assembly program that follows very closely the same sample program available
* in Pascal and C. Programmers not familiar with assembly code should refer to
* these high level versions and follow the procedures while examining the assembly
* code. This is a great way to learn how to read assembly listings, and that is
* the first step in using a debugger.
* Stack frame strategy:
* -----------------------------------------------
* Here is an example of a typical stack frame. An example of the stack frame
* RECORD is shown. Using this strategy for procedures makes life much easier
* while writing assembly code. The procedure outlined in Pascal here is
* followed by the same outline in assembly.
* PROCEDURE MyProcedure (Param1: type, Param2: type, ParamN: type) Result1: type;
* VAR Local1: type;
* Local2: type;
* LocalN: type;
* MyProcedure PROC EXPORT ; any source file can use this routine
* define registors that need to be saved as EQUATES (typically A3-A7 and D4-D7)
* StackFrame RECORD {A6Link},DECR ; build a stack frame record
* Result1 DS.{size} ; function's result returned to caller
* ParamBegin EQU * ; start parameters after this point
* Param1 DS.{size} ; the first parameter on the stack
* Param2 DS.{size} ; rest of the parameters passed by caller
* ParamN DS.{size} ; the last parameter 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
* Local1 DS.{size} ; a local variable for this procedure only
* Local2 DS.{size} ; other local variables for this procedure
* LocalN DS.{size} ; the last local variable
* LocalSize EQU * ; size of all the local variables
* ENDR
* WITH StackFrame ; cover our local stack frame
* LINK A6,#LocalSize ; allocate our local stack frame
* save registors trashed by this routine
* # # INSERT YOUR CODE HERE # #
* Exit restore registors trashed by this routine
* 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 MyProcedure ; this name will appear in the debugger
* ENDP
* The Macro DbgInfo is optional. I prefer to use it, since it aids in
* debugging. There are more macros in the "AStructMacs" folder of MPW. Put on
* a pot of coffee and take a look at them and the Sample program that uses these
* macros. There is one macro in particular that builds the entire stack frame
* structure as outlined above, including the debug info.
* Segmentation strategy:
* -----------------------------------------------
* This program consists of three segments. Main contains most of the code.
* Initialize contains code that is only used once, during startup, and can be
* unloaded after the program starts. %A5Init is automatically created by the
* Linker to initialize globals and constants, and is unloaded right away.
* SetPort strategy:
* -----------------------------------------------
* Tool box routines do not change the current port. In spite of this, in this
* program we use a strategy of calling SetPort whenever we want to draw or
* make calls which depend on the current port. This makes us less vulnerable
* to bugs in other software which might alter the current port (such as the
* bug (feature?) in many desk accessories which change the port on OpenDeskAcc).
* Hopefully, this also makes the routines from this program more self-contained,
* since they don't depend on the current port setting.
* ================================================
* -------------- 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 'Sample.inc1.a' ; all our macros and data templates
PRINT POP ; restore the PRINT options
* ================================================
* --------- DATA STORAGE ALLOCATION ------------
* ================================================
* Global data storage. All global memory is allocated here. The
* Linker will load all global data offset from A5, and the Asm knows this.
* Therefore, no reference to (A5) is required in the code. Hooray!
* Here we declare two data structures using our templates defined previously.
* They must be EXPORTed here for other files that need to IMPORT them.
EXPORT (QD,G):DATA
QD DS MyQDGlobals ; QuickDraw's globals
G DS AppGlobals ; application's globals
* ================================================
* PROCEDURE Initialize;
* ================================================
* Set up the whole world, including global variables, Toolbox managers, and menus.
* Check to see if a given trap is implemented. The recommended approach to see if
* a trap is implemented is to see if the address of the trap routine is the same
* as the address of the Unimplemented trap. We also create our one application
* window at this time. Since window storage is non-relocateable, how and when to
* allocate space for windows is very important so that heap fragmentation does not
* occur. Because Sample has only one window and it is only disposed when the
* application quits, we will allocate its space here, before anything that might
* be a locked relocatable object gets into the heap. This way, we can force its
* storage to be in the lowest memory available in the heap. Window storage can
* differ widely amongst applications depending on how many windows are created
* and disposed. If a failure occurs here, we will consider that the application
* is in such bad shape that we should just exit. Your error handling may differ,
* but the checks should still be made.
* If an error is detected, instead of merely doing an ExitToShell, which leaves
* the user without much to go on, we call AlertUser, which puts up a simple alert
* that just says an error occurred and then calls ExitToShell. In the interests
* of keeping things simple, the alert does not state the specific cause of the error,
* but a more informative alert would be appropriate for more sophisticated applications.
* Since there is no other cleanup needed at this point if an error is detected, this
* form of error- handling is acceptable. If more sophisticated error recovery is needed,
* a signal mechanism, such as is provided by Signals, can be used.
* Something worth noting here. Since the AlertUser routine is in a different segment,
* we have to use a Jump instruction to get there. In other words, we must go through the
* jump table. This causes extra test and branch instructions to get over the JMP AlertUser.
SEG 'Initialize' ; case sensitive
Initialize PROC ; Initialize everything
CountReg EQU D4 ; temporary registor to count loops
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
CurMBar DS.L 1 ; local handle to our menubar
TheEvent DS EventRecord ; local copy of the event record
LocalSize EQU * ; size of all the local variables
ENDR
IMPORT GoGetRect,AlertUser,SysEnvirons, \
TrapAvailable ; linked in with Interface.o
WITH StackFrame ; cover our local stack frame
LINK A6,#LocalSize ; allocate our local stack frame
MOVEM.L CountReg,-(SP) ; save the current registor values
MOVE.W #False,G.InBackground ; we start out in the foreground
MOVE.W #True,G.Stopped ; we'll start with the red light on
* ------------- INITIALIZE MANAGERS -------------
@1 PEA QD.GrafPort ; initialize all of the Managers
_InitGraf ; please don't flush my events
_InitFonts
_InitWindows
_InitMenus
_TEInit
CLR.L -(SP)
_InitDialogs
_InitCursor
* Call MPPOpen and ATPLoad at this point to initialize AppleTalk, if you are using it.
* NOTE -- It is no longer necessary, and actually unhealthy, to check PortBUse and
* SPConfig before opening AppleTalk. The drivers are capable of checking for port
* availability themselves. This next bit of code is necessary to allow the default
* button of our alert be outlined.
* ------------- WASTE THREE EVENTS -------------
MOVE.W #2,CountReg ; set register value to loop 3 times
Loop CLR.W -(SP) ; space for result
MOVE.W #EveryEvent,-(SP) ; the events we want
PEA TheEvent(A6) ; pass a pointer to our event
_EventAvail
MOVE.W (SP)+,D0 ; result code
DBF CountReg,Loop ; decrement count, if count < 0 then continue
* ------------- GET THE ENVIRONMENT -------------
CLR.W -(SP) ; create space for result
MOVE.W #EnvironsVersion,-(SP) ; version of SysEnvirons we want
PEA G.Mac ; the global environment record
JSR SysEnvirons ; we can ignore any errors here,
MOVE.W (SP)+,D0 ; SysEnvirons will fill in regardless
MOVE.W G.Mac.MachineType,D0 ; negitive value means old ROMs
BPL.S @2 ; 128k ROMs or better, continue on
JMP AlertUser ; we don't want to run on 64k ROMs
* ------------- TEST FOR WAITNEXTEVENT -------------
* 1.02 - Move TrapAvailable call to after SysEnvirons so that
* we can tell in TrapAvailable if a tool trap value is out of range.
@2 CLR.W -(SP) ; space for result of trap test
MOVE.W #WaitNextEvent,-(SP) ; pass the trap number of WaitNextEvent trap
BSR TrapAvailable ; test for this trap
MOVE.W (SP)+,G.HasWNEvent ; put the result in our global flag
* ------------- CHECK FOR ENOUGH MEMORY -------------
* It is better to first check the size of the application heap against a value
* that you have determined is the smallest heap the application can reasonably
* work in. This number should be derived by examining the size of the heap that
* is actually provided by MultiFinder when the minimum size requested is used.
* The derivation of the minimum size requested from MultiFinder is described
* in ASample.r. The check should be made because the preferred size can end up
* being set smaller than the minimum size by the user. This extra check acts to
* insure that your application is starting from a solid memory foundation.
* IF applLimit - applZone < MinHeap THEN AlertUser
* Next, make sure that enough memory is free for your application to run. It
* is possible for a situation to arise where the heap may have been of required
* size, but a large scrap was loaded which left too little memory. To check for
* this, call PurgeSpace and compare the result with a value that you have determined
* is the minimum amount of free memory your application needs at initialization.
* This number can be derived several different ways. One way that is fairly
* straightforward is to run the application in the minimum size configuration
* as described previously. Call PurgeSpace at initialization and examine the value
* returned. However, you should make sure that this result is not being modified
* by the scrap's presence. You can do that by calling ZeroScrap before calling
* PurgeSpace. Make sure to remove that call before shipping, though.
* The extra benefit to waiting until after the Toolbox Managers have been initialized
* before checking memory is that we can now give the user an alert to tell him what
* happened. Although it is possible that the memory situation could be worsened by
* displaying an alert, MultiFinder would gracefully exit the application with
* an informative alert if memory became critical. Here we are acting more
* in a preventative manner to avoid future disaster from low-memory problems.
MOVE.L applLimit,D1 ; get pointer to ApplLimit
MOVE.L applZone,D0 ; get pointer to ApplicZone
SUB.L D0,D1 ; subtract the ApplicZone from ApplLimit
CMPI.L #MinHeap,D1 ; do we have enough memory?
BPL.S @3 ; yes we do, continue on
JMP AlertUser ; no, report the error
@3 _PurgeSpace ; results will be in A0 and D0
CMPI.L #MinSpace,D0 ; do we have enough purgeable space?
BPL.S @4
JMP AlertUser ; no, report the error
* ------------- SET UP THE TRAFFIC LIGHT WINDOW -------------
* We will allocate our own window storage instead of letting the Window Manager
* for two reasons. One, GetNewWindow locks the 'WIND' resource handle before calling
* NewWindow and this can lead to heap fragmentation. Two, it takes just as much time
* for NewWindow to get the memory as it does for us to get it.
@4 MOVE.L #windowSize,D0
_NewPtr ,Clear ; create a pointer in A0 and clear memory
CMPA.L #NIL,A0 ; check for NIL pointer (result in D0)
BNE.S @5 ; must have been a valid pointer
JMP AlertUser ; couldn't get memory, report error
@5 CLR.L -(SP) ; create space for result
MOVE.W #rWindow,-(SP) ; out window resource definition
MOVE.L A0,-(SP) ; our window record storage
MOVE.L #-1,-(SP) ; make it on top
_GetNewWindow ; create the window
MOVE.L (SP)+,D0 ; we're not saving our window pointer
* ------------- SET UP THE MENUS -------------
CLR.L -(SP) ; space for MenuBar handle
MOVE.W #rMenuBar,-(SP) ; our MenuBar resource
_GetNewMBar ; the modern way, get a MenuBar
MOVE.L (SP),CurMBar(A6)
_SetMenuBar
MOVEA.L CurMBar(A6),A0 ; we're done with that handle
_DisposHandle ; there is a result in D0
CLR.L -(SP)
MOVE.W #AppleMenu,-(SP)
_GetMHandle ; put Apple menu handle on stack
MOVE.L #'DRVR',-(SP) ; get all the DAs
_AddResMenu
_DrawMenuBar
* ------------- SET UP RECTS FOR THE LIGHTS -------------
CLR.W -(SP) ; space for result of GoGetRect
MOVE.W #rStopRect,-(SP) ; pass the stop light's rect
PEA G.StopRect ; pass the stop light's rect pointer
BSR GoGetRect ; go get the stop light rect
MOVE.W (SP)+,D0 ; get the result of GoGetRect
CMPI.W #True,D0 ; did we get the RECT resource?
BEQ.S @6 ; yes, then continue
JMP AlertUser ; otherwise, we're having some trouble
@6 CLR.W -(SP) ; space for result of GoGetRect
MOVE.W #rGoRect,-(SP) ; pass the go light's rect
PEA G.GoRect ; pass the go light's rect pointer
BSR GoGetRect ; go get the go light rect
MOVE.W (SP)+,D0 ; get the result of GoGetRect
CMPI.W #True,D0 ; did we get the RECT resource?
BEQ.S Exit ; yes, then continue
JMP AlertUser ; otherwise, we're having some trouble
Exit MOVEM.L (SP)+,CountReg ; restore the registors
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 Initialz ; this name will appear in the debugger
ENDP
* ================================================
* PROCEDURE DoContentClick(window: WindowPtr; event: EventRecord);
* ================================================
* This is called when a mouse-down event occurs in the content of a window.
* Other applications might want to call FindControl, TEClick, etc., to
* further process the click.
SEG 'Main' ; case sensitive
DoContentClick PROC
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
LocalSize EQU * ; size of all the local variables
ENDR
IMPORT SetLight
WITH StackFrame ; cover our local stack frame
LINK A6,#LocalSize ; allocate our local stack frame
MOVE.L WindowPtr(A6),-(SP) ; pass the window pointer
MOVE.W G.Stopped,D0 ; get current state of the light
EORI.W #True,D0 ; exclusive OR the current state
MOVE.W D0,-(SP) ; pass new state to switch light
BSR SetLight ; set the traffic light
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 DoContnt ; this name will appear in the debugger
ENDP
* ================================================
* PROCEDURE DoUpdate(window: WindowPtr);
* ================================================
* This is called when an update event is received for a window.
* It calls DrawWindow to draw the contents of an application window.
* As an efficiency measure that does not have to be followed, it
* calls the drawing routine only if the visRgn is non-empty. This
* will handle situations where calculations for drawing or drawing
* itself is very time-consuming.
SEG 'Main' ; case sensitive
DoUpdate PROC
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
LocalSize EQU * ; size of all the local variables
ENDR
IMPORT IsAppWindow,DrawWindow
WITH StackFrame ; cover our local stack frame
LINK A6,#LocalSize ; allocate our local stack frame
CLR.W -(SP) ; space for result of IsAppWindow
MOVE.L WindowPtr(A6),-(SP) ; pass the window pointer
BSR IsAppWindow ; test if this window was ours
MOVE.W (SP)+,D0
CMPI.W #True,D0 ; it must be our window
BNE.S Exit ; it wasn't our window
MOVE.L WindowPtr(A6),-(SP) ; update only the visible region
_BeginUpDate ; region of the window
CLR.W -(SP) ; space for result
MOVEA.L WindowPtr(A6),A0 ; the window pointer
MOVE.L visRgn(A0),-(SP) ; the window's visRgn handle
_EmptyRgn
MOVE.W (SP)+,D0 ; result of EmptyRgn
CMPI.W #True,D0 ; was the visRgn empty?
BEQ.S @1 ; yes, then no update is needed
MOVE.L WindowPtr(A6),-(SP)
BSR DrawWindow ; draw the traffic lights
@1 MOVE.L WindowPtr(A6),-(SP) ; get pointer to window
_EndUpdate
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 DoUpdate ; this name will appear in the debugger
ENDP
* ================================================
* PROCEDURE DoActivate(window: WindowPtr; becomingActive: BOOLEAN);
* ================================================
* In this sample there is no other processing necessary other than what
* the Window Manager has already done for us. This would be the place to
* perform an activate on TextEdit records, controls, lists, update GrowIcon, etc.
SEG 'Main' ; case sensitive
DoActivate PROC
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
Active DS.W 1 ; modifiers from 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
LocalSize EQU * ; size of all the local variables
ENDR
IMPORT IsAppWindow
WITH StackFrame ; cover our local stack frame
LINK A6,#LocalSize ; allocate our local stack frame
CLR.W -(SP) ; space for result of IsAppWindow
MOVE.L WindowPtr(A6),-(SP) ; pass the window pointer
BSR IsAppWindow ; test if this window was ours
MOVE.W (SP)+,D0 ; get the result
CMPI.W #True,D0 ; it must be our window
BNE.S Exit ; it wasn't our window
CMPI.W #True,Active(A6) ; was it an Activate?
BNE.S DeActivate ; no, perform a Deactivate
* do the activate event processing here, then "BRA.S Exit"
DeActivate ; do the deactivate event
* do the deactivate event processing here, then fall through to Exit
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 Activate ; this name will appear in the debugger
ENDP
* ================================================
* PROCEDURE DoMenuCommand(menuResult: LONGINT);
* ================================================
* This is called when an item is chosen from the menu bar (after calling
* MenuSelect or MenuKey). It performs the right operation for each command.
* It is good to have both the result of MenuSelect and MenuKey go to
* one routine like this to keep everything organized.
SEG 'Main' ; case sensitive
DoMenuCommand PROC
StackFrame RECORD {A6Link},DECR ; build a stack frame record
ParamBegin EQU * ; start parameters after this point
MenuItem DS.W 1 ; result from _MenuKey or _MenuSelect
MenuID DS.W 1 ; caller passed a long word, ID + Item
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
Deskname DS.B 256 ; local storage for Desk Accs name
TempPort DS.L 1 ; local storage for the current port
LocalSize EQU * ; size of all the local variables
ENDR
IMPORT SetLight,DoCloseWindow,Terminate
WITH StackFrame ; cover our local stack frame
LINK A6,#LocalSize ; allocate our local stack frame
MOVE.W MenuID(A6),D0 ; a nifty Pascal case-like macro
CASE#.W (D0,IF), \
(AppleMenu, DoAppleMenu), \
(FileMenu, DoFileMenu), \
(EditMenu, DoEditMenu), \
(LightMenu, DoLightMenu)
; add additional Menus would go here
BRA.W Exit ; otherwise we will exit this procedure
* ------------- THE APPLE MENU ROUTINES -------------
DoAppleMenu
CMPI.W #AboutItem,MenuItem(A6) ; was it the about item?
BNE.S @1 ; no, must be a Desk Acc
CLR.W -(SP) ; show the About dialog
MOVE.W #rAboutAlert,-(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
BRA.W Exit ; all done with with Apple menu
@1 PEA TempPort(A6) ; open a desk accessory
_GetPort ; save the current port
CLR.L -(SP) ; space for result of GetMHandle
MOVE.W #AppleMenu,-(SP)
_GetMHandle ; put Apple menu on stack
MOVE.W MenuItem(A6),-(SP) ; and here's the MenuItem
PEA DeskName(A6) ; now tell me the DA's name
_GetItem
CLR.W -(SP) ; space for OpenDeskAcc result
PEA DeskName(A6)
_OpenDeskAcc ; open that puppy
MOVE.W (SP)+,D0 ; result
MOVE.L TempPort(A6),-(SP) ; restore the port
_SetPort
BRA.S Exit
* ------------- THE FILE MENU ROUTINES -------------
DoFileMenu
MOVE.W MenuItem(A6),D0 ; test the MenuItem
Case#.W (D0,IF), \
(CloseItem, FileClose), \
(QuitItem, FileQuit)
BRA.S Exit ; add additional menus here
FileClose
CLR.L -(SP) ; bug fix, didn't clear space for result -JDR 2/27/89
_FrontWindow
BSR DoCloseWindow ; close the window
BRA.S Exit
FileQuit BSR Terminate ; let's get out of here
BRA.S Exit ; Terminate may return if user cancels
* ------------- THE EDIT MENU ROUTINES -------------
DoEditMenu
CLR.W -(SP) ; system will handle editing of desk accs.
MOVE.W MenuItem(A6),-(SP) ; get the MenuItem
SUBQ.W #1,(SP) ; SystemEdit is off by one
_SysEdit
MOVE.B (SP)+,D0 ; drop result from SystemEdit
BRA.S Exit ; we don't have anything to edit
* ------------- THE LIGHT MENU ROUTINES -------------
DoLightMenu
MOVE.W MenuItem(A6),D0 ; test the MenuItem
Case#.W (D0,IF), \
(StopItem, StopSelect), \
(GoItem, GoSelect)
BRA.S Exit ; add additional menus here
StopSelect CLR.L -(SP) ; bug fix, didn't clear space for result -JDR 2/27/89
_FrontWindow ; pass our window, we only have one
MOVE.W #TRUE,-(SP) ; pass true to set stop light on
BSR SetLight ; switch the traffic light
BRA.S Exit
GoSelect CLR.L -(SP) ; bug fix, didn't clear space for result -JDR 2/27/89
_FrontWindow ; pass our window, we only have one
MOVE.W #FALSE,-(SP) ; pass false to set stop light off
BSR SetLight ; switch the traffic light
Exit CLR.W -(SP)
_HiLiteMenu ; unhilite all Menus
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 DoMenuCm ; this name will appear in the debugger
ENDP
* ================================================
* PROCEDURE DoMouseDown(Event: EventRecord);
* ================================================
* Handle all of the MouseDown events.
SEG 'Main' ; case sensitive
DoMouseDown PROC
StackFrame RECORD {A6Link},DECR ; build a stack frame record
ParamBegin EQU * ; start parameters after this point
EventPtr DS.L 1 ; pointer to current event
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 Window pointer variable
Where DS.L 1 ; local variable where the click was
NewGrowRect DS Rect ; local rect variable for SizeWindow
LocalSize EQU * ; size of all the local variables
ENDR
IMPORT AdjustMenus,DoContentClick
WITH StackFrame ; cover our local stack frame
LINK A6,#LocalSize ; allocate our local stack frame
MOVEA.L EventPtr(A6),A0 ; event record only needed by SystemClick
MOVE.L evtMouse(A0),Where(A6) ; make a local copy of the mouse location
CLR.W -(SP) ; space for FindWindow result
MOVE.L Where(A6),-(SP) ; the mouse point
PEA WindowPtr(A6) ; a local variable
_FindWindow ; put the result in a register
MOVE.W (SP)+,D0 ; a nifty Pascal case-like macro
Case#.W (D0,IF), \
(InMenuBar, MenuEvent), \
(InSysWindow, SystemEvent), \
(InContent, Content), \
(InDrag, Drag)
; add additional routines here
BRA.S Exit ; otherwise we will exit this procedure
* ------------- THE DESK ACCS EVENT -------------
MenuEvent
BSR.W AdjustMenus
CLR.L -(SP) ; space for MenuSelect
MOVE.L Where(A6),-(SP) ; Mouse coordinates
_MenuSelect ; pass MenuSelect's result
BSR DoMenuCommand ; go do the menu and return
BRA.S Exit
* ------------- THE DESK ACCS EVENT -------------
SystemEvent
MOVE.L EventPtr(A6),-(SP) ; get EventRecord and WindowPtr
MOVE.L WindowPtr(A6),-(SP) ; pass the window pointer and...
_SystemClick ; let the system handle it
BRA.S Exit
* ------------- THE CONTENT EVENT -------------
Content
CLR.L -(SP) ; was our window in front?
_FrontWindow ; get front window's pointer
MOVE.L (SP)+,D0
CMP.L WindowPtr(A6),D0 ; was it in the front window?
BNE.S @1 ; no, then just select window
MOVE.L WindowPtr(A6),-(SP) ; pass the window pointer
MOVE.L EventPtr(A6),-(SP) ; pass a pointer to the event
BSR DoContentClick ; do a click in content region
BRA.S Exit
@1 MOVE.L WindowPtr(A6),-(SP) ; only select this window
_SelectWindow ; and take no further action
BRA.S Exit
* ------------- THE DRAG A WINDOW EVENT -------------
Drag
MOVE.L WindowPtr(A6),-(SP) ; pass Window Pointer
MOVE.L Where(A6),-(SP) ; Mouse coordinates and boundary
PEA QD.Screenbits.bounds
_DragWindow ; drag it the screen's boundary
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 MouseDwn ; this name will appear in the debugger
ENDP
* ================================================
* PROCEDURE DoEvent(event: EventRecord);
* ================================================
* Do the right thing for an event. Determine what kind of event it is,
* and call the appropriate routines.
SEG 'Main' ; case sensitive
DoEvent PROC
ModifyReg EQU D4 ; we'll use this register locally
StackFrame RECORD {A6Link},DECR ; build a stack frame record
ParamBegin EQU * ; start listing parameters here
EventPtr DS.L 1 ; pointer to current event
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
IMPORT DoMouseDown,DrawWindow, \
AdjustMenus,IsAppWindow,\
DoUpdate,DoActivate
WITH StackFrame,TheEvent ; cover our local stack frame
LINK A6,#LocalSize ; allocate our local stack frame
MOVEM.L ModifyReg,-(SP) ; save this register before using it
MOVEA.L EventPtr(A6),A0 ; pointer of event passed by caller
LEA TheEvent(A6),A1 ; pointer to local variable TheEvent
MOVE.L #evtBlkSize,D0 ; size of an event record
_BlockMove ; we now have a local copy of the event
MOVE.W Modify(A6),ModifyReg ; a nifty Pascal case-like macro
MOVE.W What(A6),D0 ; get the event number
Case# (D0,Exit), \ ; if not an event we support, then exit
, \ ; 0 Null (not used)
MouseDown, \ ; 1 Mouse down
, \ ; 2 Mouse up (not used)
KeyDown, \ ; 3 Key down
, \ ; 4 Key up (not used)
KeyDown, \ ; 5 Auto key
Update, \ ; 6 Update
Disk, \ ; 7 Disk inserted
Activate, \ ; 8 Activate/Deactivate
, \ ; 9 (not used)
, \ ; 10 Network (not used)
, \ ; 11 I/O Driver (not used)
, \ ; 12 App1 (not used)
, \ ; 13 App2 (not used)
, \ ; 14 App3 (not used)
OSEvent, ; 15 OS Event or Suspend/Resume
* ------------- THE MOUSEDOWN EVENT -------------
MouseDown
PEA TheEvent(A6) ; pass Event pointer in case of SystemClick
BSR DoMouseDown
BRA Exit
* ------------- THE KEYDOWN EVENT -------------
KeyDown
BTST #CmdKey,ModifyReg ; command key?
BEQ Exit ; no, then we're done
BSR.W AdjustMenus ; first, adjust the menus
CLR.L -(SP) ; space for MenuKey
MOVE.W 2+Message(A6),-(SP) ; get the character
_MenuKey ; is it a command?
BSR DoMenuCommand ; handle the command and return
BRA.S Exit
* ------------- THE UPDATE EVENT -------------
Update
MOVE.L Message(A6),-(SP) ; pass the window pointer
BSR DoUpdate ; do the update
BRA.S Exit
* ------------- THE DISK EVENT -------------
Disk
TST.W Message(A6) ; check for error
BEQ.S @1 ; if none, skip
CLR.W -(SP)
MOVE.L #DITopLeft,-(SP)
MOVE.L Message(A6),-(SP)
MOVE.W #diBadMount,-(SP)
_Pack2 ; go through disk init package
ADDQ #2,SP ; throw away result
@1 BRA.S Exit
* ------------- THE ACTIVATE/DEACTIVATE EVENT -------------
Activate
BTST #ActiveFlag,ModifyReg ; was it an Activate?
BEQ.S @1 ; no, perform a Deactivate
MOVE.L Message(A6),-(SP) ; pass the current window pointer
MOVE.W #True,-(SP) ; set up for an Activate event
BSR DoActivate ; do the activate routine
BRA.S Exit ; we're done
@1 MOVE.L Message(A6),-(SP) ; pass current window pointer
MOVE.W #False,-(SP) ; set up for an Deactivate event
BSR DoActivate ; go do the activate routine
BRA.S Exit ; we're done
* ------------- THE SUSPEND/RESUME EVENT -------------
* OSEvent is the event number of the suspend/resume and mouse-moved events sent
* by MultiFinder. Once we determine that an event is an osEvent, we look at the
* high byte of the message sent to determine which kind it is. To differentiate
* suspend and resume events we check the resumeMask bit.
OSEvent MOVE.B Message(A6),D1 ; get high byte of Message in reg
CMPI.B #SuspendResume,D1 ; test for message event type
BNE.S Exit ; not a suspend/resume event
BTST #0,3+Message(A6) ; test bit zero in low byte of Message
BNE.S @1 ; this is a resume event
MOVE.W #True,G.InBackground ; a suspend event
CLR.L -(SP) ; bug fix, was passing Message to DoActivate -JDR 2/27/89
_FrontWindow ; pass the front window to DoActivate -JDR 2/27/89
MOVE.W #False,-(SP) ; pass false to cause deactivate
BSR DoActivate ; go do the activate routine
BRA.S Exit
@1 MOVE.W #False,G.InBackground ; a resume event
CLR.L -(SP) ; bug fix, was passing Message to DoActivate -JDR 2/27/89
_FrontWindow ; pass the front window to DoActivate -JDR 2/27/89
MOVE.W #True,-(SP) ; pass false to cause activate
BSR DoActivate ; go do the activate routine
Exit
MOVEM.L (SP)+,ModifyReg ; restore this register after use
UNLK A6
MOVEA.L (SP)+,A0 ; save the caller's address
ADDA.L #ParamSize,SP ; strip the caller's parameters
JMP (A0)
DbgInfo DoEvent ; this name will appear in the debugger
ENDP
* ================================================
* PROCEDURE EventLoop;
* ================================================
* Get the events by calling WaitNextEvent, if it's available, otherwise
* by calling GetNextEvent. Also call AdjustCursor before doing the event.
* After returning from handling the event, we have to make sure the cursor
* is still adjusted proper ONLY because this application can "sleep" forever.
* An event record is allocated on the stack. A pointer to this event is
* passed to "DoEvent". We loop until the user has selects "Quit" in the
* file menu. This program will exit through the DoMenuCommand routine.
* 1.02 made adjustments to the event loop logic. There was a bug in calling
* AdjustCursor at the wrong time. (it crashed under _GetNextEvent too!)
* If you are using modeless dialogs that have editText items,
* you will want to call IsDialogEvent to give the caret a chance
* to blink, even if WNE/GNE returned FALSE. However, check FrontWindow
* for a non-NIL value before calling IsDialogEvent.
SEG 'Main' ; case sensitive
EventLoop PROC ; any source file can use this routine
StackFrame RECORD {A6Link},DECR ; build a stack frame record
ParamBegin EQU * ; start listing parameters here
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
MouseMvdRgn DS.L 1 ; local region for MouseMoved events
MousePos DS.L 1 ; local point for mouse position
LocalSize EQU * ; size of all the local variables
ENDR
IMPORT AdjustCursor,GetGlobalMouse
WITH StackFrame ; cover our local stack frame
LINK A6,#LocalSize ; allocate our local stack frame
CLR.L -(SP)
_NewRgn ; create region for AdjustCursor
MOVE.L (SP)+,MouseMvdRgn(A6) ; save the handle to this region
* ------------- GET NEXT EVENT LOOP -------------
NextEvent
CMPI.W #True,G.HasWNEvent ; see if we can call WaitNextEvent
BNE.S @1 ; nope, old time events
PEA MousePos(A6) ; here's the mouse
BSR GetGlobalMouse ; get global coordinate
MOVE.L MousePos(A6),-(SP) ; here's the mouse
MOVE.L MouseMvdRgn(A6),-(SP) ; the region to change
BSR AdjustCursor ; adjust the cursor and region
CLR.W -(SP) ; space for result
MOVE.W #EveryEvent,-(SP) ; the events we want
PEA TheEvent(A6) ; pointer to the event record
MOVE.L #SleepValue,-(SP) ; the sleeping time value
MOVE.L MouseMvdRgn(A6),-(SP) ; the current MouseRgn
_WaitNextEvent
BRA.S @2 ; got an event to handle?
; no WaitNextEvent trap available
@1 _SystemTask ; call SystemTask for drivers and DAs
CLR.W -(SP) ; space for result
MOVE.W #EveryEvent,-(SP) ; the events we want
PEA TheEvent(A6) ; pass a pointer to our event
_GetNextEvent
@2 MOVE.W (SP)+,D0 ; result code
BEQ.S NextEvent ; no event, get another one
GotEvent MOVE.L TheEvent.where(A6),-(SP); the mouse location
MOVE.L MouseMvdRgn(A6),-(SP) ; the region to change
BSR AdjustCursor ; adjust cursor BEFORE doing event
PEA TheEvent(A6) ; pass the pointer to our event
BSR DoEvent ; do the event and return
BRA.S NextEvent ; done with that event, get the next
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 EvntLoop ; this name will appear in the debugger
ENDP
* ================================================
* --------------- MAIN ENTRY POINT ---------------
* ================================================
* This is the entry point of the program. We start with data initializing
* and then to get the System environment (SysEnvirons). We unload the
* initialization code segment and finally get started with the EventLoop.
SEG 'Main' ; case sensitive
StartUp MAIN ; entry point of the program
IMPORT _DataInit,Initialize, \
ForceEnvirons,EventLoop
JSR _DataInit ; initialize those constants
PEA _DataInit ; get rid of that segment
_UnloadSeg
* If you have stack requirements that differ from the default, then you could
* use SetApplLimit to increase StackSpace at this point, before calling MaxApplZone.
_MaxApplZone ; result in D0
JSR Initialize ; get things the program set up
PEA Initialize
_UnloadSeg ; we're done this that segment too
LEA EventLoop,A0 ; on your mark, get set,...
JMP (A0) ; go into the event loop
ENDP
END ; end of this source file

View File

@ -0,0 +1 @@
TEXTMPS

View File

@ -0,0 +1,18 @@
data 'MPSR' (1005) {
$"0009 4D6F 6E61 636F 0061 6D70 6C65 2E61" /* ..Monaco.ample.a */
$"0022 0000 0000 0000 0000 0009 8400 000C" /* .".............. */
$"0001 0006 0004 002A 0003 0142 01E3 002A" /* .......*...B...* */
$"0003 0142 01E3 A42B A620 0000 0000 0000" /* ...B...+. ...... */
$"0000 0000 0000 0100" /* ........ */
};
data 'MPSR' (1008) {
$"002A 0003 0142 01E3 002A 0003 0142 01E3" /* .*...B...*...B.. */
$"0000 0000 0000 0000 0000 0000 0000" /* .............. */
};
data 'vers' (2, purgeable) {
$"0320 8000 0000 0333 2E32 074D 5057 2033" /* . .....3.2.MPW 3 */
$"2E32" /* .2 */
};

View File

@ -0,0 +1,198 @@
/*------------------------------------------------------------------------------
#
# Apple Macintosh Developer Technical Support
#
# MultiFinder-Aware Simple Sample Application
#
# Sample
#
# Sample.h - Rez and C Include Source
#
# Copyright © Apple Computer, Inc. 1989-1990
# All rights reserved.
#
# Versions:
# 1.00 08/88
# 1.01 11/88
# 1.02 04/89 MPW 3.1
# 1.03 02/90 MPW 3.2
#
# Components:
# Sample.a Feb. 1, 1990
# Sample.inc1.a Feb. 1, 1990
# SampleMisc.a Feb. 1, 1990
# Sample.r Feb. 1, 1990
# Sample.h Feb. 1, 1990
# Sample.make Feb. 1, 1990
#
# Sample is an example application that demonstrates how to
# initialize the commonly used toolbox managers, operate
# successfully under MultiFinder, handle desk accessories,
# and create, grow, and zoom windows.
#
# It does not by any means demonstrate all the techniques
# you need for a large application. In particular, Sample
# does not cover exception handling, multiple windows/documents,
# sophisticated memory management, printing, or undo. All of
# these are vital parts of a normal full-sized application.
#
# This application is an example of the form of a Macintosh
# application; it is NOT a template. It is NOT intended to be
# used as a foundation for the next world-class, best-selling,
# 600K application. A stick figure drawing of the human body may
# be a good example of the form for a painting, but that does not
# mean it should be used as the basis for the next Mona Lisa.
#
# We recommend that you review this program or TESample before
# beginning a new application.
------------------------------------------------------------------------------*/
/* These #defines correspond to values defined in the Pascal source code.
Sample.c and Sample.r include this file. */
/* Determining an application's minimum size to request from MultiFinder depends
on many things, each of which can be unique to an application's function,
the anticipated environment, the developer's attitude of what constitutes
reasonable functionality and performance, etc. Here is a list of some things to
consider when determining the minimum size (and preferred size) for your
application. The list is pretty much in order of importance, but by no means
complete.
1. What is the minimum size needed to give almost 100 percent assurance
that the application won't crash because it ran out of memory? This
includes not only things that you do have direct control over such as
checking for NIL handles and pointers, but also things that some
feel are not so much under their control such as QuickDraw and the
Segment Loader.
2. What kind of performance can a user expect from the application when
it is running in the minimum memory configuration? Performance includes
not only speed in handling data, but also things like how many documents
can be opened, etc.
3. What are the typical sizes of scraps [is a boy dog] that a user might
wish to work with when lauching or switching to your application? If
the amount of memory is too small, the scrap may get lost [will have
to be shot]. This can be quite frustrating to the user.
4. The previous items have concentrated on topics that tend to cause an
increase in the minimum size to request from MultiFinder. On the flip
side, however, should be the consideration of what environments the
application may be running in. There may be a high probability that
many users with relatively small memory configurations will want to
avail themselves of your application. Or, many users might want to use it
while several other, possibly related/complementary applications are
running. If that is the case, it would be helpful to have a fairly
small minimum size.
So, what did we decide on Sample? First, Sample has little risk of
running out of memory once it starts. Second, performance isn't much
of an issue since it doesn't do much and multiple windows are not
allowed. Third, there are no edit operations in Sample itself, so we
just want to provide enough space for a reasonable scrap to survive
between desk accessory launches. Lastly, Sample should intrude as little
as possible, so the effort should be towards making it as small as possible.
We looked at some heap dumps while the application was running under
various partition sizes. With a size of 23K, there was approximately
8-9K free, which is a good 'slop' factor in an application like this
which doesn't do much, but where we'd still like the scrap to survive
most of the time. */
#define kMinSize 23 /* application's minimum size (in K) */
/* We made the preferred size bigger than the minimum size by 12K, so that
there would be even more room for the scrap, FKEYs, etc. */
#define kPrefSize 35 /* application's preferred size (in K) */
#define rMenuBar 128 /* application's menu bar */
#define rAboutAlert 128 /* about alert */
#define rUserAlert 129 /* error user alert */
#define rWindow 128 /* application's window */
#define rStopRect 128 /* rectangle for Stop light */
#define rGoRect 129 /* rectangle for Go light */
/* kSysEnvironsVersion is passed to SysEnvirons to tell it which version of the
SysEnvRec we understand. */
#define kSysEnvironsVersion 1
/* kOSEvent is the event number of the suspend/resume and mouse-moved events sent
by MultiFinder. Once we determine that an event is an osEvent, we look at the
high byte of the message sent to determine which kind it is. To differentiate
suspend and resume events we check the resumeMask bit. */
#define kOSEvent app4Evt /* event used by MultiFinder */
#define kSuspendResumeMessage 1 /* high byte of suspend/resume event message */
#define kResumeMask 1 /* bit of message field for resume vs. suspend */
#define kMouseMovedMessage 0xFA /* high byte of mouse-moved event message */
/* The following constants are used to identify menus and their items. The menu IDs
have an "m" prefix and the item numbers within each menu have an "i" prefix. */
#define mApple 128 /* Apple menu */
#define iAbout 1
#define mFile 129 /* File menu */
#define iNew 1
#define iClose 4
#define iQuit 12
#define mEdit 130 /* Edit menu */
#define iUndo 1
#define iCut 3
#define iCopy 4
#define iPaste 5
#define iClear 6
#define mLight 131 /* Light menu */
#define iStop 1
#define iGo 2
/* 1.01 - kTopLeft - This is for positioning the Disk Initialization dialogs. */
#define kDITop 0x0050
#define kDILeft 0x0070
/* 1.01 - kMinHeap - This is the minimum result from the following
equation:
ORD(GetApplLimit) - ORD(ApplicZone)
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. */
#define kMinHeap 21 * 1024
/* 1.01 - kMinSpace - This is the minimum 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. */
#define kMinSpace 8 * 1024
/* kExtremeNeg and kExtremePos are used to set up wide open rectangles and regions. */
#define kExtremeNeg -32768
#define kExtremePos 32767 - 1 /* required to address an old region bug */
/* these #defines are used to set enable/disable flags of a menu */
#define AllItems 0b1111111111111111111111111111111 /* 31 flags */
#define NoItems 0b0000000000000000000000000000000
#define MenuItem1 0b0000000000000000000000000000001
#define MenuItem2 0b0000000000000000000000000000010
#define MenuItem3 0b0000000000000000000000000000100
#define MenuItem4 0b0000000000000000000000000001000
#define MenuItem5 0b0000000000000000000000000010000
#define MenuItem6 0b0000000000000000000000000100000
#define MenuItem7 0b0000000000000000000000001000000
#define MenuItem8 0b0000000000000000000000010000000
#define MenuItem9 0b0000000000000000000000100000000
#define MenuItem10 0b0000000000000000000001000000000
#define MenuItem11 0b0000000000000000000010000000000
#define MenuItem12 0b0000000000000000000100000000000

View File

@ -0,0 +1 @@
TEXTMPS

View File

@ -0,0 +1,18 @@
data 'MPSR' (1005) {
$"0009 4D6F 6E61 636F 0061 6D70 6C65 2E68" /* ..Monaco.ample.h */
$"0022 0000 6D70 6C65 2E68 0061 7475 7320" /* ."..mple.h.atus */
$"0000 0006 0004 002A 0003 0142 01E3 002A" /* .......*...B...* */
$"0003 0142 01E3 A42B A620 0000 0000 0000" /* ...B...+. ...... */
$"0000 0000 0000 0100" /* ........ */
};
data 'MPSR' (1008) {
$"002A 0003 0142 01E3 002A 0003 0142 01E3" /* .*...B...*...B.. */
$"0000 0000 0000 0000 0000 0000 0000" /* .............. */
};
data 'vers' (2, purgeable) {
$"0320 8000 0000 0333 2E32 074D 5057 2033" /* . .....3.2.MPW 3 */
$"2E32" /* .2 */
};

View File

@ -0,0 +1,370 @@
*
* Apple Macintosh Developer Technical Support
*
* MultiFinder-Aware Simple Sample Application
*
* Sample
*
* Sample.inc1.a - Assembler Source
*
* Copyright © Apple Computer, Inc. 1989-1990
* All rights reserved.
*
* Versions:
* 1.00 08/88
* 1.01 11/88
* 1.02 04/89 MPW 3.1
* 1.03 02/90 MPW 3.2
*
* Components:
* Sample.a Feb. 1, 1990
* Sample.inc1.a Feb. 1, 1990
* SampleMisc.a Feb. 1, 1990
* Sample.r Feb. 1, 1990
* Sample.h Feb. 1, 1990
* Sample.make Feb. 1, 1990
*
* Sample is an example application that demonstrates how to
* initialize the commonly used toolbox managers, operate
* successfully under MultiFinder, handle desk accessories,
* and create, grow, and zoom windows.
*
* It does not by any means demonstrate all the techniques
* you need for a large application. In particular, Sample
* does not cover exception handling, multiple windows/documents,
* sophisticated memory management, printing, or undo. All of
* these are vital parts of a normal full-sized application.
*
* This application is an example of the form of a Macintosh
* application; it is NOT a template. It is NOT intended to be
* used as a foundation for the next world-class, best-selling,
* 600K application. A stick figure drawing of the human body may
* be a good example of the form for a painting, but that does not
* mean it should be used as the basis for the next Mona Lisa.
*
* We recommend that you review this program or TESample before
* beginning a new application.
* ----------- 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
rStopRect EQU 128 ; rectangle for Stop light
rGoRect EQU 129 ; rectangle for Go light
* The following equates are for menu definitions, obviously.
* -----------------------------------------------
AppleMenu EQU 128 ; Apple menu
AboutItem EQU 1
FileMenu EQU 129 ; File menu
NewItem EQU 1
OpenItem EQU 2
CloseItem EQU 4
SaveItem EQU 5
SaveAsItem EQU 6
RevertItem EQU 7
PageSetupItem EQU 9
PrintItem EQU 10
QuitItem EQU 12
EditMenu EQU 130 ; Edit menu
UndoItem EQU 1
CutItem EQU 3
CopyItem EQU 4
PasteItem EQU 5
ClearItem EQU 6
LightMenu EQU 131 ; Light menu
StopItem EQU 1
GoItem EQU 2
* -----------------------------------------------
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
GrafPort 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

View File

@ -0,0 +1 @@
TEXTMPS

View File

@ -0,0 +1,18 @@
data 'MPSR' (1005) {
$"0009 4D6F 6E61 636F 004E 6577 5072 6F67" /* ..Monaco.NewProg */
$"7261 6D20 2260 5265 7175 6573 7420 2250" /* ram "`Request "P */
$"726F 0006 0004 002A 0003 0142 01E3 002A" /* ro.....*...B...* */
$"0003 0142 01E3 A42B A620 0000 0000 0000" /* ...B...+. ...... */
$"0000 0000 0000 0100" /* ........ */
};
data 'MPSR' (1008) {
$"002A 0003 0142 01E3 002A 0003 0142 01E3" /* .*...B...*...B.. */
$"0000 0000 0000 0000 0000 0000 0000" /* .............. */
};
data 'vers' (2, purgeable) {
$"0320 8000 0000 0333 2E32 074D 5057 2033" /* . .....3.2.MPW 3 */
$"2E32" /* .2 */
};

View File

@ -0,0 +1,74 @@
#
# Apple Macintosh Developer Technical Support
#
# MultiFinder-Aware Simple Sample Application
#
# Sample
#
# [A]Sample.make - Make Source
#
# Copyright © Apple Computer, Inc. 1989-1990
# All rights reserved.
#
# Versions:
# 1.00 08/88
# 1.01 11/88
# 1.02 04/89 MPW 3.1
# 1.03 02/90 MPW 3.2
#
# Components:
# Sample.a Feb. 1, 1990
# Sample.inc1.a Feb. 1, 1990
# SampleMisc.a Feb. 1, 1990
# Sample.r Feb. 1, 1990
# Sample.h Feb. 1, 1990
# Sample.make Feb. 1, 1990
#
# Sample is an example application that demonstrates how to
# initialize the commonly used toolbox managers, operate
# successfully under MultiFinder, handle desk accessories,
# and create, grow, and zoom windows.
#
# It does not by any means demonstrate all the techniques
# you need for a large application. In particular, Sample
# does not cover exception handling, multiple windows/documents,
# sophisticated memory management, printing, or undo. All of
# these are vital parts of a normal full-sized application.
#
# This application is an example of the form of a Macintosh
# application; it is NOT a template. It is NOT intended to be
# used as a foundation for the next world-class, best-selling,
# 600K application. A stick figure drawing of the human body may
# be a good example of the form for a painting, but that does not
# mean it should be used as the basis for the next Mona Lisa.
#
# We recommend that you review this program or TESample before
# beginning a new application.
# NOTE: The Asm has warnings turned off here. This is because the
# Macro "Case#" builds a list of BEQ instructions that could be
# optimized into BEQ.S. Everyone of these causes a warning
# message to appear while building this sample. With warnings
# turned off, they don't appear. Code generation is NOT effected.
# If ANY changes are made to the include file, you MUST perform
# a full build of ALL source files. The dependencies below will
# cause all source file to be assembled if the Sample.inc1.a is updated.
AOptions = -w
AObjs = Sample.a.o ∂
SampleMisc.a.o ∂
"{Libraries}"Runtime.o ∂
"{Libraries}"Interface.o
Sample.a.o ƒƒ Sample.make Sample.inc1.a
SampleMisc.a.o ƒƒ Sample.make Sample.inc1.a
Sample ƒƒ {AObjs} Sample.make
Link -o {Targ} {AObjs}
SetFile {Targ} -t APPL -c 'MOOS' -a B
Sample ƒƒ Sample.r Sample.h Sample.make
Rez -rd -o {Targ} Sample.r -append

View File

@ -0,0 +1 @@
TEXTMPS

View File

@ -0,0 +1,18 @@
data 'MPSR' (1005) {
$"0009 4D6F 6E61 636F 0061 6D70 6C65 2E6D" /* ..Monaco.ample.m */
$"616B 6500 2200 0016 0009 0021 000A 0000" /* ake."......!.... */
$"0000 0006 0004 002A 0003 0142 01E3 002A" /* .......*...B...* */
$"0003 0142 01E3 A42B A620 0000 0000 0000" /* ...B...+. ...... */
$"0000 0000 0000 0100" /* ........ */
};
data 'MPSR' (1008) {
$"002A 0003 0142 01E3 002A 0003 0142 01E3" /* .*...B...*...B.. */
$"0000 0000 0000 0000 0000 0000 0000" /* .............. */
};
data 'vers' (2, purgeable) {
$"0320 8000 0000 0333 2E32 074D 5057 2033" /* . .....3.2.MPW 3 */
$"2E32" /* .2 */
};

View File

@ -0,0 +1,286 @@
/*------------------------------------------------------------------------------
#
# Apple Macintosh Developer Technical Support
#
# MultiFinder-Aware Simple Sample Application
#
# Sample
#
# Sample.r - Rez Source
#
# Copyright © Apple Computer, Inc. 1989-1990
# All rights reserved.
#
# Versions:
# 1.00 08/88
# 1.01 11/88
# 1.02 04/89 MPW 3.1
# 1.03 02/90 MPW 3.2
#
# Components:
# Sample.a Feb. 1, 1990
# Sample.inc1.a Feb. 1, 1990
# SampleMisc.a Feb. 1, 1990
# Sample.r Feb. 1, 1990
# Sample.h Feb. 1, 1990
# Sample.make Feb. 1, 1990
#
# Sample is an example application that demonstrates how to
# initialize the commonly used toolbox managers, operate
# successfully under MultiFinder, handle desk accessories,
# and create, grow, and zoom windows.
#
# It does not by any means demonstrate all the techniques
# you need for a large application. In particular, Sample
# does not cover exception handling, multiple windows/documents,
# sophisticated memory management, printing, or undo. All of
# these are vital parts of a normal full-sized application.
#
# This application is an example of the form of a Macintosh
# application; it is NOT a template. It is NOT intended to be
# used as a foundation for the next world-class, best-selling,
# 600K application. A stick figure drawing of the human body may
# be a good example of the form for a painting, but that does not
# mean it should be used as the basis for the next Mona Lisa.
#
# We recommend that you review this program or TESample before
# beginning a new application.
------------------------------------------------------------------------------*/
#include "SysTypes.r"
#include "Types.r"
#include "Sample.h"
resource 'vers' (1) {
0x02, 0x00, release, 0x00,
verUS,
"1.03",
"1.03, Copyright \251 Apple Computer, Inc. 1989-1990"
};
/* this is a definition for a resource which contains only a rectangle */
type 'RECT' {
rect;
};
/* we use an MBAR resource to conveniently load all the menus */
resource 'MBAR' (rMenuBar, preload) {
{ mApple, mFile, mEdit, mLight }; /* four menus */
};
resource 'MENU' (mApple, preload) {
mApple, textMenuProc,
AllItems & ~MenuItem2, /* Disable dashed line, enable About and DAs */
enabled, apple,
{
"About Sample…",
noicon, nokey, nomark, plain;
"-",
noicon, nokey, nomark, plain
}
};
resource 'MENU' (mFile, preload) {
mFile, textMenuProc,
MenuItem12, /* enable Quit only, program enables others */
enabled, "File",
{
"New",
noicon, "N", nomark, plain;
"Open",
noicon, "O", nomark, plain;
"-",
noicon, nokey, nomark, plain;
"Close",
noicon, "W", nomark, plain;
"Save",
noicon, "S", nomark, plain;
"Save As…",
noicon, nokey, nomark, plain;
"Revert",
noicon, nokey, nomark, plain;
"-",
noicon, nokey, nomark, plain;
"Page Setup…",
noicon, nokey, nomark, plain;
"Print…",
noicon, nokey, nomark, plain;
"-",
noicon, nokey, nomark, plain;
"Quit",
noicon, "Q", nomark, plain
}
};
resource 'MENU' (mEdit, preload) {
mEdit, textMenuProc,
NoItems, /* disable everything, program does the enabling */
enabled, "Edit",
{
"Undo",
noicon, "Z", nomark, plain;
"-",
noicon, nokey, nomark, plain;
"Cut",
noicon, "X", nomark, plain;
"Copy",
noicon, "C", nomark, plain;
"Paste",
noicon, "V", nomark, plain;
"Clear",
noicon, nokey, nomark, plain
}
};
resource 'MENU' (mLight, preload) {
mLight, textMenuProc,
NoItems, /* disable everything, program does the enabling */
enabled, "Traffic",
{
"Red Light",
noicon, nokey, nomark, plain;
"Green Light",
noicon, nokey, nomark, plain
}
};
/* this ALRT and DITL are used as an About screen */
resource 'ALRT' (rAboutAlert, purgeable) {
{40, 20, 160, 297},
rAboutAlert,
{ /* array: 4 elements */
/* [1] */
OK, visible, silent,
/* [2] */
OK, visible, silent,
/* [3] */
OK, visible, silent,
/* [4] */
OK, visible, silent
}
};
resource 'DITL' (rAboutAlert, purgeable) {
{ /* array DITLarray: 5 elements */
/* [1] */
{88, 185, 108, 265},
Button {
enabled,
"OK"
},
/* [2] */
{8, 8, 24, 214},
StaticText {
disabled,
"Simple Sample (Traffic Light)"
},
/* [3] */
{32, 8, 48, 296},
StaticText {
disabled,
"Copyright © Apple Computer 1989-1990"
},
/* [4] */
{56, 8, 72, 136},
StaticText {
disabled,
"Brought to you by:"
},
/* [5] */
{80, 24, 112, 167},
StaticText {
disabled,
"Macintosh Developer  Technical Support"
}
}
};
/* this ALRT and DITL are used as an error screen */
resource 'ALRT' (rUserAlert, purgeable) {
{40, 20, 120, 260},
rUserAlert,
{ /* array: 4 elements */
/* [1] */
OK, visible, silent,
/* [2] */
OK, visible, silent,
/* [3] */
OK, visible, silent,
/* [4] */
OK, visible, silent
}
};
resource 'DITL' (rUserAlert, purgeable) {
{ /* array DITLarray: 3 elements */
/* [1] */
{50, 150, 70, 230},
Button {
enabled,
"OK"
},
/* [2] */
{10, 60, 30, 230},
StaticText {
disabled,
"Sample - Error occurred!"
},
/* [3] */
{8, 8, 40, 40},
Icon {
disabled,
2
}
}
};
resource 'WIND' (rWindow, preload, purgeable) {
{60, 40, 290, 160},
noGrowDocProc, visible, noGoAway, 0x0, "Traffic"
};
resource 'RECT' (rStopRect, preload, purgeable) {
{10, 10, 110, 110}
};
resource 'RECT' (rGoRect, preload, purgeable) {
{120, 10, 220, 110}
};
/* here is the quintessential MultiFinder friendliness device, the SIZE resource */
resource 'SIZE' (-1) {
dontSaveScreen,
acceptSuspendResumeEvents,
enableOptionSwitch,
canBackground, /* we can background; we don't currently, but our sleep value */
/* guarantees we don't hog the Mac while we are in the background */
multiFinderAware, /* this says we do our own activate/deactivate; don't fake us out */
backgroundAndForeground, /* this is definitely not a background-only application! */
dontGetFrontClicks, /* change this is if you want "do first click" behavior like the Finder */
ignoreChildDiedEvents, /* essentially, I'm not a debugger (sub-launching) */
not32BitCompatible, /* this app should not be run in 32-bit address space */
reserved,
reserved,
reserved,
reserved,
reserved,
reserved,
reserved,
kPrefSize * 1024,
kMinSize * 1024
};

View File

@ -0,0 +1 @@
TEXTMPS

View File

@ -0,0 +1,18 @@
data 'MPSR' (1005) {
$"0009 4D6F 6E61 636F 0000 0000 0000 0000" /* ..Monaco........ */
$"0000 0000 0000 0000 0000 0000 0000 00A4" /* ................ */
$"0000 0006 0004 002A 0003 0142 01E3 002A" /* .......*...B...* */
$"0003 0142 01E3 A42B A620 0000 0000 0000" /* ...B...+. ...... */
$"0000 0000 0000 0100" /* ........ */
};
data 'MPSR' (1008) {
$"002A 0003 0142 01E3 002A 0003 0142 01E3" /* .*...B...*...B.. */
$"0000 0000 0000 0000 0000 0000 0000" /* .............. */
};
data 'vers' (2, purgeable) {
$"0320 8000 0000 0333 2E32 074D 5057 2033" /* . .....3.2.MPW 3 */
$"2E32" /* .2 */
};

View File

@ -0,0 +1,899 @@
*
* Apple Macintosh Developer Technical Support
*
* MultiFinder-Aware Simple Sample Application
*
* Sample
*
* SampleMisc.a - Assembler Source
*
* Copyright © Apple Computer, Inc. 1989-1990
* All rights reserved.
*
* Versions:
* 1.00 08/88
* 1.01 11/88
* 1.02 04/89 MPW 3.1
* 1.03 02/90 MPW 3.2
*
* Components:
* Sample.a Feb. 1, 1990
* Sample.inc1.a Feb. 1, 1990
* SampleMisc.a Feb. 1, 1990
* Sample.r Feb. 1, 1990
* Sample.h Feb. 1, 1990
* Sample.make Feb. 1, 1990
*
* Sample is an example application that demonstrates how to
* initialize the commonly used toolbox managers, operate
* successfully under MultiFinder, handle desk accessories,
* and create, grow, and zoom windows.
*
* It does not by any means demonstrate all the techniques
* you need for a large application. In particular, Sample
* does not cover exception handling, multiple windows/documents,
* sophisticated memory management, printing, or undo. All of
* these are vital parts of a normal full-sized application.
*
* This application is an example of the form of a Macintosh
* application; it is NOT a template. It is NOT intended to be
* used as a foundation for the next world-class, best-selling,
* 600K application. A stick figure drawing of the human body may
* be a good example of the form for a painting, but that does not
* mean it should be used as the basis for the next Mona Lisa.
*
* We recommend that you review this program or TESample before
* beginning a new application.
* ================================================
* -------------- 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 'Sample.inc1.a' ; all our macros and data templates
PRINT POP ; restore the PRINT options
* ================================================
* ----------- DATA STORAGE USAGE ---------------
* ================================================
* Here we will IMPORT the data that is being from the
* DATA STORAGE ALLOCATION section of ASample.a. By IMPORTing them
* at this point, they will be accessible by this entire source file.
* The symbol is IMPORTed and associated with the original template
* as defined in the ASample.inc1.a file. This allows us to use
* the identifiers in the template.
IMPORT QD:QDGlobals
IMPORT G:AppGlobals
* ================================================
* FUNCTION TrapAvailable(tNumber: INTEGER): BOOLEAN;
* ================================================
* Check to see if a given trap is implemented. This is only used by the
* Initialize routine in this program, so we put it in the Initialize segment.
* The recommended approach to see if a trap is implemented is to see if
* the address of the trap routine is the same as the address of the
* Unimplemented trap. Needs to be called after call to _SysEnvirons so that it can
* check if a ToolTrap is out of range of a pre-Mac II ROM. This routine
* assumes we're running on 128k ROMs. It also requires the entire trap
* word so that it knows if it is a ToolTrap or an OSTrap.
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 SetLight(window: WindowPtr; newStopped: BOOLEAN);
* ================================================
* Change the setting of the light and force an update event.
* newStopped is the state of the stop light the user is requesting.
SEG 'Main' ; case sensitive
SetLight 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
newStopped DS.W 1 ; test value 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 G.Stopped,D0 ; get state of stop light
CMP.W newStopped(A6),D0 ; compare to the new state
BEQ.S Exit ; they're the same, stupid user!
MOVE.W newStopped(A6),G.Stopped ; set global to the new state
MOVE.L WindowPtr(A6),-(SP)
_SetPort ; set the port to us
MOVEA.L WindowPtr(A6),A0 ; force update event for window
PEA portRect(A0) ; invalidate entire window
_InvalRect
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 SetLight ; 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
* ------------- ADJUST THE FILE MENU -------------
AdjustFile
CLR.L -(SP) ; space for result
MOVE.W #FileMenu,-(SP) ; get the File menu handle
_GetMHandle
MOVE.L (SP)+,Menu(A6) ; save the menu handle
CLR.W -(SP) ; space for result
MOVE.L FrontMost(A6),-(SP)
BSR IsDAWindow
MOVE.W (SP)+,D0 ; get the result of the function
CMPI.W #True,D0 ; was it the DA window?
BNE.S @1 ; no, then disable the close item
MOVE.L Menu(A6),-(SP) ; it was an application window
MOVE.W #CloseItem,-(SP)
_EnableItem ; enable the close for DAs only
BRA.S AdjustEdit
@1 MOVE.L Menu(A6),-(SP) ; it was not a DA window
MOVE.W #CloseItem,-(SP)
_DisableItem ; disable close for all others
* ------------- ADJUST THE EDIT MENU -------------
AdjustEdit
CLR.L -(SP) ; space for result
MOVE.W #EditMenu,-(SP) ; get the Edit menu handle
_GetMHandle
MOVE.L (SP)+,Menu(A6) ; save the menu handle
CLR.W -(SP) ; space for result
MOVE.L FrontMost(A6),-(SP)
BSR IsDAWindow
MOVE.W (SP)+,D0 ; get the result of the function
CMPI.W #True,D0 ; was it the DA window?
BNE.S @2 ; no, disable the edit menu
MOVE.L Menu(A6),-(SP) ; it was for a DA window
MOVE.W #CutItem,-(SP)
_EnableItem ; enable the Cut
MOVE.L Menu(A6),-(SP)
MOVE.W #CopyItem,-(SP)
_EnableItem ; enable the Copy
MOVE.L Menu(A6),-(SP)
MOVE.W #PasteItem,-(SP)
_EnableItem ; enable the Paste
MOVE.L Menu(A6),-(SP)
MOVE.W #ClearItem,-(SP)
_EnableItem ; enable the Clear
BRA.S AdjustLight ; done with the edit menu
@2 MOVE.L Menu(A6),-(SP) ; disable the edit menu
MOVE.W #UndoItem,-(SP)
_DisableItem ; disable the Undo
MOVE.L Menu(A6),-(SP)
MOVE.W #CutItem,-(SP)
_DisableItem ; disable the Cut
MOVE.L Menu(A6),-(SP)
MOVE.W #CopyItem,-(SP)
_DisableItem ; disable the Copy
MOVE.L Menu(A6),-(SP)
MOVE.W #PasteItem,-(SP)
_DisableItem ; disable the Paste
MOVE.L Menu(A6),-(SP)
MOVE.W #ClearItem,-(SP)
_DisableItem ; disable the Clear
* ------------- ADJUST THE LIGHT MENU -------------
AdjustLight
CLR.L -(SP) ; space for result
MOVE.W #LightMenu,-(SP) ; get the Edit menu handle
_GetMHandle
MOVE.L (SP)+,Menu(A6) ; save the menu handle
CLR.W -(SP) ; space for result
MOVE.L FrontMost(A6),-(SP) ; the front window
BSR IsAppWindow
MOVE.W (SP)+,D3 ; save the result of the function
CMPI.W #True,D3 ; was our window in front?
BNE.S @3 ; no, disable the menu items
MOVE.L Menu(A6),-(SP) ; enable the light menu
MOVE.W #StopItem,-(SP)
_EnableItem ; enable the stop
MOVE.L Menu(A6),-(SP)
MOVE.W #GoItem,-(SP)
_EnableItem ; enable the go for our window
BRA.S @4 ; now check the menu items
@3 MOVE.L Menu(A6),-(SP) ; disable the light menu
MOVE.W #StopItem,-(SP)
_DisableItem ; disable the stop
MOVE.L Menu(A6),-(SP)
MOVE.W #GoItem,-(SP)
_DisableItem ; disable the go
BRA.S Exit ; nothing to check, get out of here
@4 MOVE.W G.Stopped,D0 ; get the current state of the light
CMPI.W #True,D0 ; is the stop light on?
BNE.S @5 ; no, the green light is on
MOVE.L Menu(A6),-(SP) ; set menu to red light = on
MOVE.W #StopItem,-(SP)
MOVE.W #True,-(SP)
_CheckItem ; check the StopItem in the menu
MOVE.L Menu(A6),-(SP)
MOVE.W #GoItem,-(SP)
MOVE.W #False,-(SP)
_CheckItem ; un-check the GoItem in the menu
BRA.S Exit ; now we're done, get out of here
@5 MOVE.L Menu(A6),-(SP) ; set menu to green light = on
MOVE.W #StopItem,-(SP)
MOVE.W #False,-(SP)
_CheckItem ; un-check the StopItem in the menu
MOVE.L Menu(A6),-(SP)
MOVE.W #GoItem,-(SP)
MOVE.W #True,-(SP)
_CheckItem ; check the GoItem in the menu
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 DrawWindow(window: WindowPtr);
* ================================================
* Draw the contents of the application's window. We do some drawing in color,
* using Classic QuickDraw's color capabilities. This will be black and white on
* old machines, but color on color machines. The window's visRgn has been set by
* the Update routine to cause drawing only where it needs to be done.
SEG 'Main' ; case sensitive
DrawWindow 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
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.L WindowPtr(A6),-(SP)
_SetPort ; set the current port to us
MOVEA.L WindowPtr(A6),A0 ; erase the entire window
PEA portRect(A0) ; the window's rect
_EraseRect ; clear out anything remaining
MOVE.W G.Stopped,D0 ; find the state of the lights
CMPI.W #True,D0
BNE.S @1 ; red light should be off
* ------------- RED LIGHT -------------
MOVE.L #redColor,-(SP) ; make the red light go on
_ForeColor
PEA G.StopRect
_PaintOval
MOVE.L #whiteColor,-(SP) ; make the green light go off
_ForeColor
PEA G.GoRect
_PaintOval
BRA.S @2
* ------------- GREEN LIGHT -------------
@1 MOVE.L #greenColor,-(SP) ; make the green light go on
_ForeColor
PEA G.GoRect
_PaintOval
MOVE.L #whiteColor,-(SP) ; make the red light go off
_ForeColor
PEA G.StopRect
_PaintOval
* ------------- FRAME THE LIGHTS -------------
@2 MOVE.L #blackColor,-(SP)
_ForeColor
PEA G.StopRect
_FrameOval ; draw black line around light
PEA G.GoRect
_FrameOval ; draw black line around light
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 DrawWind ; 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 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

View File

@ -0,0 +1 @@
TEXTMPS

View File

@ -0,0 +1,18 @@
data 'MPSR' (1005) {
$"0009 4D6F 6E61 636F 0061 6D70 6C65 4D69" /* ..Monaco.ampleMi */
$"7363 2E61 0022 0000 4D69 7363 2E61 0045" /* sc.a."..Misc.a.E */
$"16DC 0006 0004 002A 0003 0142 01E3 002A" /* .......*...B...* */
$"0003 0142 01E3 A42B A620 0000 0000 0000" /* ...B...+. ...... */
$"0000 0000 0000 0100" /* ........ */
};
data 'MPSR' (1008) {
$"002A 0003 0142 01E3 002A 0003 0142 01E3" /* .*...B...*...B.. */
$"0000 0000 0000 0000 0000 0000 0000" /* .............. */
};
data 'vers' (2, purgeable) {
$"0320 8000 0000 0333 2E32 074D 5057 2033" /* . .....3.2.MPW 3 */
$"2E32" /* .2 */
};

View File

@ -0,0 +1,156 @@
/*------------------------------------------------------------------------------
NAME
Count -- count lines and characters
SYNOPSIS
Count [-l] [-c] [file]
DESCRIPTION
"Count" counts the lines and characters in its input, and writes the
counts to standard output. If no files are specified standard input is
read. If more than one file is specified, separate counts are written
for each file, one per line, preceeded by the file name. A total is also
written following the list of files.
COPYRIGHT
Copyright Apple Computer, Inc. 1985-1988
All rights reserved.
------------------------------------------------------------------------------*/
#include <Types.h>
#include <ctype.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <ErrMgr.h>
#include <CursorCtl.h>
#include <Errors.h>
#define InputSize (1024*8)
/* Variables local to this file */
static char inputBuffer[InputSize + 1];
static char errorBuffer[256];
static char *usage = "# Usage - %s [-l] [-c] [file…].\n";
static long optionsSpecified;
static long lineOption;
static long charOption;
struct counts {
long lines;
long characters;
};
struct counts count(long input)
{
char c;
char *ptr;
long lines = 0;
long characters = 0;
long charsRead;
struct counts cnts;
while ((charsRead = read(input, inputBuffer, InputSize)) > 0) {
ptr = inputBuffer;
inputBuffer[charsRead] = 0;
characters += charsRead;
while ((c = *ptr++) != 0 || ptr <= &inputBuffer[charsRead]) {
if (c == '\n') {
lines++;
if ((lines & 0x0F) == 0)
SpinCursor(1);
}
}
}
if (characters > 0 && *(ptr-2) != '\n')
lines++;
cnts.lines = lines;
cnts.characters = characters;
return cnts;
}
void print(long files, long max, char *name, struct counts cnts)
{
long space;
space = 0;
if (files > 1) {
fprintf(stdout,"%s ", name);
space = max - strlen(name);
}
if (optionsSpecified == false || lineOption == true) {
fprintf(stdout, "%*d ", space + 5, cnts.lines);
space = 0;
}
if (optionsSpecified == false || charOption == true) {
fprintf(stdout, "%*d ", space + 7, cnts.characters);
}
fprintf(stdout, "\n");
fflush(stdout);
}
main(int argc, char *argv[])
{
long status;
long parms;
long files;
long done;
long length;
long max;
long input;
struct counts cnts;
struct counts total;
status = files = 0;
max = strlen("Total");
optionsSpecified = lineOption = charOption = false;
InitCursorCtl(nil);
for (parms = 1; parms < argc; parms++) {
length = strlen(argv[parms]);
if (*argv[parms] != '-') {
argv[++files] = argv[parms];
if (max < length)
max = length;
} else if (tolower(*(argv[parms]+1)) == 'c' && length == 2) {
optionsSpecified = charOption = true;
} else if (tolower(*(argv[parms]+1)) == 'l' && length == 2) {
optionsSpecified = lineOption = true;
} else {
fprintf(stderr,"### %s - \"%s\" is not an option.\n", argv[0], argv[parms]);
fprintf(stderr, usage, argv[0]);
return 1;
}
}
if (files == 0) {
cnts = count(fileno(stdin));
print(files, max, NULL, cnts);
} else {
total.lines = total.characters = done = 0;
for (parms = 1; parms <= files; parms++) {
if ((input = open(argv[parms], O_RDONLY)) >= 0) {
cnts = count(input);
close(input);
total.lines += cnts.lines;
total.characters += cnts.characters;
print(files, max, argv[parms], cnts);
done++;
} else {
fprintf(stderr,"### %s - Unable to open file %s.\n", argv[0], argv[parms]);
fprintf(stderr,"# %s\n", GetSysErrText(MacOSErr, errorBuffer));
status = 2;
}
}
if (done > 1) {
print(files,max,"Total",total);
}
}
return status;
}

View File

@ -0,0 +1 @@
TEXTMPS

View File

@ -0,0 +1,18 @@
data 'MPSR' (1005) {
$"0009 4D6F 6E61 636F 006F 756E 742E 6300" /* ..Monaco.ount.c. */
$"2200 006F 756E 742E 6300 0050 0000 004C" /* "..ount.c..P...L */
$"0004 0006 0004 002A 0003 0142 01E3 002A" /* .......*...B...* */
$"0003 0142 01E3 A42B A620 0000 0000 0000" /* ...B...+. ...... */
$"0000 0000 0000 0100" /* ........ */
};
data 'MPSR' (1008) {
$"002A 0003 0142 01E3 002A 0003 0142 01E3" /* .*...B...*...B.. */
$"0000 0000 0000 0000 0000 0000 0000" /* .............. */
};
data 'vers' (2, purgeable) {
$"0320 8000 0000 0333 2E32 074D 5057 2033" /* . .....3.2.MPW 3 */
$"2E32" /* .2 */
};

View File

@ -0,0 +1,78 @@
/*
Count.r - commando resource file
Copyright Apple Computer, Inc. 1985-1987
All rights reserved.
Count [-l] [-c] [file] < file > counts
-l # write only line counts
-c # write only character counts
*/
#include "Cmdo.r"
resource 'cmdo' (128) {
{
245, /* Height of dialog */
"Counts the lines and characters in its input, and writes the results to standard output.",
{
notDependent {}, RadioButtons {
{
{25, 250, 40, 410},
"Lines and characters",
"",
Set,
"Count the number of lines and characters in the input file(s) (or standard input).",
{40, 250, 55, 340},
"Lines",
"-l",
NotSet,
"Only count the number of lines in the input file(s) (or standard input).",
{55, 250, 70, 340},
"Characters",
"-c",
NotSet,
"Only count the number of characters in the input file(s) (or standard input).",
}
},
notDependent {}, TextBox {
gray,
{17, 240, 75, 450},
"Count"
},
Or {{-4}}, MultiFiles {
"Files to count…",
"Select the files to count. If no files are specified Count reads "
"from standard input.",
{36, 35, 56, 200},
"Files to count:",
"",
MultiInputFiles {
{TEXT},
FilterTypes,
"Only text files",
"All files",
}
},
Or {{-3}}, Redirection {
StandardInput,
{85, 30}
},
notDependent {}, Redirection {
StandardOutput,
{85, 180}
},
notDependent {}, Redirection {
DiagnosticOutput,
{85, 330}
},
notDependent {}, TextBox {
gray,
{80, 25, 125, 450},
"Redirection"
},
}
}
};

View File

@ -0,0 +1 @@
TEXTMPS

View File

@ -0,0 +1,18 @@
data 'MPSR' (1005) {
$"0009 4D6F 6E61 636F 006F 756E 742E 7200" /* ..Monaco.ount.r. */
$"2200 0000 0000 0000 0000 0000 0000 0000" /* "............... */
$"0000 0006 0004 002A 0003 0142 01E3 002A" /* .......*...B...* */
$"0003 0142 01E3 A42B A620 0000 0000 0000" /* ...B...+. ...... */
$"0000 0000 0000 0100" /* ........ */
};
data 'MPSR' (1008) {
$"002A 0003 0142 01E3 002A 0003 0142 01E3" /* .*...B...*...B.. */
$"0000 0000 0000 0000 0000 0000 0000" /* .............. */
};
data 'vers' (2, purgeable) {
$"0320 8000 0000 0333 2E32 074D 5057 2033" /* . .....3.2.MPW 3 */
$"2E32" /* .2 */
};

View File

@ -0,0 +1,65 @@
***************************************************************************
****
**** DESK ACCESSORY and DEVICE DRIVER Entry Code/Data
****
***************************************************************************
STRING PASCAL
INCLUDE 'ToolEqu.a'
INCLUDE 'SysEqu.a'
CASE OBJ
**************************** DESK ACCESSORY ENTRY **************************
IMPORT %DRVRMain
DAEntry Proc Export ; See Device Manager IM:2
;
; First we need to set the drvrFlags (IM II-188), choose from
;
; dReadEnable enable driver for read operations (drivers only)
; dWritEnable enable driver for writing (drivers only)
; dCtlEnable enable driver/da for control operations
; dStatEnable enable driver/da for status operations (drivers only)
; dNeedGoodBye driver/da needs a "goodbye kiss"
; dNeedTime driver/da needs "main thread" time
; dNeedLock driver will be accessed at interrupt level (drivers only)
;
DC.B (1<<dCtlEnable) + (1<<dNeedTime) ; periodic, control flags set
DC.B 0 ; Lower byte is unused
;
; Next is the the drvrDelay (IM II-188), set only if dNeedTime flag set above
;
DC.W 5*60 ; 5 sec periodic update
;
; Next is the the drvrEMask (IM I-444), which events DA can respond to...
; Must be NIL for drivers, for DA's choose from
; mButDwnEvt mouse button down is event 1
; keyDwnEvt key down is event 3
; keyUpEvt key up is event 4
; autoKeyEvt auto-repeated key is event 5
; updatEvt update event
; activateEvt activate/deactive event
;
DC.W (1<<updatEvt) ; Handle activate, update events
;
; Next is the the drvrMenu (IM I-444), Menu ID of DA's menu, or NIL
;
DC.W 0 ; No associated menu
;
; Next are the offsets to the main routines of the driver/DA
;
DC.W %DRVRMain - DAEntry ; Open routine
DC.W %DRVRMain - DAEntry +4 ; Prime - unused for DA's
DC.W %DRVRMain - DAEntry +8 ; Control
DC.W %DRVRMain - DAEntry +12 ; Status - unused for DA's
DC.W %DRVRMain - DAEntry +16 ; Close
;
; Next are the offsets to the main routines of the driver/DA
;
DAName
DC.B 'Memory' ; DA/DRVR Name
ORG DAName+32 ; Pad string out to 32 bytes
END

View File

@ -0,0 +1 @@
TEXTMPS

View File

@ -0,0 +1,18 @@
data 'MPSR' (1005) {
$"0009 4D6F 6E61 636F 0041 456E 7472 792E" /* ..Monaco.AEntry. */
$"6100 2200 006E 7472 792E 6100 0000 0013" /* a."..ntry.a..... */
$"0000 0006 0004 002A 0003 0142 01E3 002A" /* .......*...B...* */
$"0003 0142 01E3 A42B A620 0000 0000 0000" /* ...B...+. ...... */
$"0000 0000 0000 0100" /* ........ */
};
data 'MPSR' (1008) {
$"002A 0003 0142 01E3 002A 0003 0142 01E3" /* .*...B...*...B.. */
$"0000 0000 0000 0000 0000 0000 0000" /* .............. */
};
data 'vers' (2, purgeable) {
$"0320 8000 0000 0333 2E32 074D 5057 2033" /* . .....3.2.MPW 3 */
$"2E32" /* .2 */
};

View File

@ -0,0 +1,44 @@
#
# Macintosh Developer Technical Support
#
# EditText Sample Control Panel Device
#
# EditCdev
#
# EditCdev.make - Make Source
#
# Copyright © Apple Computer, Inc. 1988-1990
# All rights reserved.
#
# Versions: 1.1 7/88
# 1.0 6/88
#
# Components: EditCdev.c Feb. 1, 1990
# EditCdev.r Feb. 1, 1990
# EditCdev.make Feb. 1, 1990
#
# EditCdev demonstrates how to implement an editText item
# in a Control Panel Device. It utilizes the new undo, cut, copy,
# paste, and delete messages that are sent to cdevs in
# response to user menu selections. How to handle private
# storage is also covered.
#
# Enforce strict ptotype checking in ≥MPW 3.0 C
COptions = -r
SrcName = EditCdev
Lang = C
CdevName = {SrcName}
Objs = {SrcName}.{Lang}.o ∂
"{Libraries}"Interface.o
{SrcName}.rsrc ƒ {SrcName}.r {CdevName}.make
Rez -o {Targ} {SrcName}.r -t cdev -c hack
{CdevName} ƒ {SrcName}.rsrc {Objs} {CdevName}.make
Duplicate -y {SrcName}.rsrc {Targ}
Link -o {Targ} -rt cdev=-4064 -m TEXTCDEV {Objs} && ∂
Setfile {CdevName} -a B && ∂
Duplicate -y {CdevName} "{SystemFolder}"

View File

@ -0,0 +1 @@
TEXTMPS

View File

@ -0,0 +1,18 @@
data 'MPSR' (1005) {
$"0009 4D6F 6E61 636F 0064 6974 4344 6576" /* ..Monaco.ditCDev */
$"2E6D 616B 6500 2200 0076 2E6D 616B 6500" /* .make."..v.make. */
$"6972 0006 0004 002A 0003 0142 01E3 002A" /* ir.....*...B...* */
$"0003 0142 01E3 A42B A620 0000 0000 0000" /* ...B...+. ...... */
$"0000 0000 0000 0100" /* ........ */
};
data 'MPSR' (1008) {
$"002A 0003 0142 01E3 002A 0003 0142 01E3" /* .*...B...*...B.. */
$"0000 0000 0000 0000 0000 0000 0000" /* .............. */
};
data 'vers' (2, purgeable) {
$"0320 8000 0000 0333 2E32 074D 5057 2033" /* . .....3.2.MPW 3 */
$"2E32" /* .2 */
};

View File

@ -0,0 +1,164 @@
/*------------------------------------------------------------------------------
#
# Macintosh Developer Technical Support
#
# EditText Sample Control Panel Device
#
# EditCdev
#
# EditCdev.c - C Source
#
# Copyright © Apple Computer, Inc. 1988-1990
# All rights reserved.
#
# Versions: 1.1 7/88
# 1.0 6/88
#
# Components: EditCdev.c Feb. 1, 1990
# EditCdev.r Feb. 1, 1990
# EditCdev.make Feb. 1, 1990
#
# EditCdev demonstrates how to implement an editText item
# in a Control Panel Device. It utilizes the new undo, cut, copy,
# paste, and delete messages that are sent to cdevs in
# response to user menu selections. How to handle private
# storage is also covered.
#
------------------------------------------------------------------------------*/
#include <Types.h>
#include <Memory.h>
#include <Quickdraw.h>
#include <TextEdit.h>
#include <Dialogs.h>
#include <Devices.h>
#include <Scrap.h>
/* Constants */
#define textItm 1 /* first editTExt item in cdev */
/* Types */
typedef struct CDEVRec {
TEHandle myTE;
} CDEVRec, *CDEVPtr, **CDEVHnd;
/* Prototypes */
void DoEditCommand (short message, DialogPtr CPDialog);
/* This is the main dispatcher. It must be the first code in the cdev.
EditCdev's dispatcher responds only to the following messages from
the Control Panel:
macDev - To indicate what machines it is available on.
initDev - To set up some temporary storage and get the caret started.
keyEvtDev - To check for an edit command and do the appropriate action.
cutDev - To cut the current selection.
copyDev - To copy the current selection.
pasteDev - To paste the contents of the clipboard.
clearDev - To delete the current selection.
The Dialog Manager's services are used to handle entry of text, selection
of text, editing of text, and moving between the editText items via the
tab key. Since the Dialog Manager handles the selection of text, we do not
have to be concerned with hitDev messages for the editText items. The only
things we have to take care of are calling the Dialog Manager editing
routines in response to an edit command, and getting the caret to show up
at the beginning. In response to an edit command that was the result of
a command-key equivalent, we must also eliminate the event so that it does
not get processed as a keyDown by the Dialog Manager. Otherwise, an 'x'
would show up in the editText item when the user did a command-x to cut
the text.*/
pascal Handle
TextCDEV(short message, short item, short numItems, short CPanelID,
EventRecord *theEvent, Handle cdevStorage, DialogPtr CPDialog)
{
#pragma unused (item, CPanelID) /* unused formal parameters */
char tempChar;
if (message == macDev) return((Handle) 1); /* we work on every machine */
else if (cdevStorage != nil) {
switch (message) {
case initDev: /* initialize cdev */
cdevStorage = NewHandle(sizeof(CDEVRec)); /* create provate storage */
SelIText(CPDialog, numItems + textItm, 0, 999); /* make caret show up */
break;
case hitDev: /* handle hit on item */
case closeDev: /* clean up and dispose */
case nulDev:
case updateDev: /* handle any update drawing */
case activDev: /* activate any needed items */
case deactivDev: /* deactivate any needed items */
break;
case keyEvtDev: /* respond to keydown */
tempChar = theEvent->message & charCodeMask;/* get the character, and check */
if (theEvent->modifiers & cmdKey) { /* status of command key */
message = nulDev; /* start with no message */
theEvent->what = nullEvent; /* and empty event type */
switch (tempChar) { /* set appropriate message */
case 'X':
case 'x':
message = cutDev;
break;
case 'C':
case 'c':
message = copyDev;
break;
case 'V':
case 'v':
message = pasteDev;
break;
}
DoEditCommand(message, CPDialog); /* Let edit command handler take it */
}
break;
case macDev:
case undoDev:
break;
case cutDev:
case copyDev:
case pasteDev:
case clearDev:
DoEditCommand(message, CPDialog); /* respond to edit command */
break;
}
return (cdevStorage);
} /* cdevStorage != nil */
/*
** if cdevStorage = NIL then ControlPanel
** will put up memory error
*/
return (nil);
}
/* Call the appropriate Dialog Manager routine to handle an edit command for
an editText item. It will do all the work regarding the TEScrap. */
void
DoEditCommand (short message, DialogPtr CPDialog)
{
switch (message) {
case cutDev:
DlgCut(CPDialog);
break;
case copyDev:
DlgCopy(CPDialog);
break;
case pasteDev:
DlgPaste(CPDialog);
break;
case clearDev:
DlgDelete(CPDialog);
break;
}
}

View File

@ -0,0 +1 @@
TEXTMPS

View File

@ -0,0 +1,18 @@
data 'MPSR' (1005) {
$"0009 4D6F 6E61 636F 0064 6974 4364 6576" /* ..Monaco.ditCdev */
$"2E63 0022 0000 0014 0001 E78C 4275 696C" /* .c."........Buil */
$"64C9 0006 0004 002A 0003 0142 01E3 002A" /* d......*...B...* */
$"0003 0142 01E3 A42B A620 0000 0000 0000" /* ...B...+. ...... */
$"0000 0000 0000 0100" /* ........ */
};
data 'MPSR' (1008) {
$"002A 0003 0142 01E3 002A 0003 0142 01E3" /* .*...B...*...B.. */
$"0000 0000 0000 0000 0000 0000 0000" /* .............. */
};
data 'vers' (2, purgeable) {
$"0320 8000 0000 0333 2E32 074D 5057 2033" /* . .....3.2.MPW 3 */
$"2E32" /* .2 */
};

View File

@ -0,0 +1,112 @@
/*------------------------------------------------------------------------------
#
# Macintosh Developer Technical Support
#
# EditText Sample Control Panel Device
#
# EditCdev
#
# EditCdev.r - Rez Source
#
# Copyright © Apple Computer, Inc. 1988-1990
# All rights reserved.
#
# Versions: 1.1 7/88
# 1.0 6/88
#
# Components: EditCdev.c Feb. 1, 1990
# EditCdev.r Feb. 1, 1990
# EditCdev.make Feb. 1, 1990
#
# EditCdev demonstrates how to implement an editText item
# in a Control Panel Device. It utilizes the new undo, cut, copy,
# paste, and delete messages that are sent to cdevs in
# response to user menu selections. How to handle private
# storage is also covered.
#
------------------------------------------------------------------------------*/
#include "Types.r"
#include "SysTypes.r"
type 'hack' as 'STR ';
resource 'vers' (1) {
0x01, 0x00, release, 0x00,
verUS,
"1.1",
"1.1, Copyright © Apple Computer, Inc. 1988-1990"
};
resource 'hack' (0, purgeable) {
"Control Panel Device, INIT and CODE by Macintosh Developer Technical Support"
};
resource 'BNDL' (-4064, purgeable) {
'hack', 0,
{ 'ICN#', {0, -4064},
'FREF', {0, -4064}
}
};
resource 'ICN#' (-4064, purgeable) {
{ /* array: 2 elements */
/* [1] */
$"00 00 00 00 00 00 3F E0 00 00 48 10 00 00 44 10"
$"00 01 83 10 00 02 01 90 00 04 01 90 00 04 01 90"
$"00 04 01 90 00 04 03 90 00 04 02 90 00 04 02 90"
$"00 08 02 90 00 08 02 90 00 10 06 90 00 20 0C 90"
$"03 C0 18 90 04 00 3F 10 0F FF C0 10 08 00 00 10"
$"08 00 00 10 08 00 00 10 08 00 FF 10 08 00 00 10"
$"08 00 00 10 08 00 00 10 08 00 00 10 07 FF FF E0"
$"04 00 00 20 04 00 00 20 04 00 00 20 07 FF FF E0",
/* [2] */
$"00 00 00 00 00 00 3F E0 00 00 7F F0 00 00 7F F0"
$"00 01 FF F0 00 03 FF F0 00 07 FF F0 00 07 FF F0"
$"00 07 FF F0 00 07 FF F0 00 07 FF F0 00 07 FF F0"
$"00 0F FF F0 00 0F FF F0 00 1F FF F0 00 3F FF F0"
$"03 FF FF F0 07 FF FF F0 0F FF FF F0 0F FF FF F0"
$"0F FF FF F0 0F FF FF F0 0F FF FF F0 0F FF FF F0"
$"0F FF FF F0 0F FF FF F0 0F FF FF F0 07 FF FF E0"
$"07 FF FF E0 07 FF FF E0 07 FF FF E0 07 FF FF E0"
}
};
resource 'DITL' (-4064) {
{ /* array DITLarray: 1 elements */
/* [1] */
{60, 110, 76, 280},
EditText {
enabled, ""
};
/* [2] */
{85, 110, 101, 280},
EditText {
enabled, ""
};
/* [3] */
{15, 110, 50, 380},
StaticText {
disabled, "Apple Macintosh Developer Technical Support"
"\nTextEdit Control Panel Device Example"
"\n© Apple Computer, Inc. 1988-1990"
}
}
};
resource 'FREF' (-4064, purgeable) {
'cdev', 0, ""
};
resource 'nrct' (-4064, purgeable) {
{ /* array RectArray: 1 elements */
/* [1] */
{-1, 87, 130, 322}
}
};
resource 'mach' (-4064, purgeable) {
0xFFFF,
0
};

View File

@ -0,0 +1 @@
TEXTMPS

View File

@ -0,0 +1,18 @@
data 'MPSR' (1005) {
$"0009 4D6F 6E61 636F 0064 6974 4364 6576" /* ..Monaco.ditCdev */
$"2E72 0022 0000 0064 6669 6E64 00A5 0048" /* .r."...dfind...H */
$"443A 0006 0004 002A 0003 0142 01E3 002A" /* D:.....*...B...* */
$"0003 0142 01E3 A42B A620 0000 0000 0000" /* ...B...+. ...... */
$"0000 0000 0000 0100" /* ........ */
};
data 'MPSR' (1008) {
$"002A 0003 0142 01E3 002A 0003 0142 01E3" /* .*...B...*...B.. */
$"0000 0000 0000 0000 0000 0000 0000" /* .............. */
};
data 'vers' (2, purgeable) {
$"0320 8000 0000 0333 2E32 074D 5057 2033" /* . .....3.2.MPW 3 */
$"2E32" /* .2 */
};

View File

@ -0,0 +1,33 @@
/*------------------------------------------------------------------------------
FILE
FStubs.c - Stubs for floating point runtime library routines not
used by MPW tools
DESCRIPTION
This file provides additional stubs for several routines defined
in the runtine library that aren't necessary in MPW tools. These
routines are referenced by the Standard C Library I/O functions,
but are never called. Because they are referenced, the linker
can't remove them. The stubs in this file provide dummy routines
which are never called, but reduce the size of the tool. The file
{Libraries}Stubs.o contains most of the stub routines. This
file only contains routines not found in {Libraries}Stubs.o.
COPYRIGHT
Copyright Apple Computer, Inc. 1986-1987
All rights reserved.
------------------------------------------------------------------------------*/
/* Floating Point Conversion Routines
These routines, called by printf, are only necessary if floating point
formatting is used.
*/
ecvt() {}
fcvt() {}

View File

@ -0,0 +1 @@
TEXTMPS

View File

@ -0,0 +1,18 @@
data 'MPSR' (1005) {
$"0009 4D6F 6E61 636F 0053 7475 6273 2E63" /* ..Monaco.Stubs.c */
$"0022 0000 7475 6273 2E63 0004 556E 646F" /* ."..tubs.c..Undo */
$"0000 0006 0004 002A 0003 0142 01E3 002A" /* .......*...B...* */
$"0003 0142 01E3 A42B A620 0000 0000 0000" /* ...B...+. ...... */
$"0000 0000 0000 0100" /* ........ */
};
data 'MPSR' (1008) {
$"002A 0003 0142 01E3 002A 0003 0142 01E3" /* .*...B...*...B.. */
$"0000 0000 0000 0000 0000 0000 0000" /* .............. */
};
data 'vers' (2, purgeable) {
$"0320 8000 0000 0333 2E32 074D 5057 2033" /* . .....3.2.MPW 3 */
$"2E32" /* .2 */
};

View File

@ -0,0 +1,305 @@
Instructions - The C Examples
Copyright Apple Computer, Inc. 1987-1990
All rights reserved.
About the Examples
Eight sample C programs are included with MPW C: an application,
a tool, a desk accessory, and a program that demonstrates the
use of performance tools:
Sample - a simple MultiFinder-Aware Sample application
TESample - a simple MultiFinder-Aware TextEdit application
SillyBalls - a simple Color Quickdraw sample application
(Requires Color Quickdraw, e.g. MacII)
TubeTest - a simple Color Quickdraw & Palette Manager
Sample application
(Requires Color Quickdraw, e.g. MacII)
Count - an MPW tool
Memory - a sample desk accessory
EditCdev - a sample Control Panel Device with a TextEdit item
TestPerf - a performance demonstration tool
The source files for each of these examples are in the
"Examples:CExamples:" folder. In addition, the makefiles
containing the commands needed to build each of the
examples are provided in the same folder.
Building the Examples
You can easily build each of the sample programs using the Directory
and Build menus. (See Chapter 2 of the MPW Reference.)
Set the default directory to "CExamples:"
The simplest way to do this is to select from the Directory menu
the menu item that ends in "CExamples:". You can also set the
default directory by using the Directory and SetDirectory commands.
Build the program
You can use any of the four Build items at the bottom of the Build
menu to build the program you have selected. Each of these menu
items displays a dialog box that asks for the name of the program
you want to build. When this dialog box appears, type the name of
one of the sample programs (Sample, TESample, SillyBalls,
TubeTest, Count, Memory, EditCdev or TestPerf).
Each of the Build menu items behaves slightly differently:
Build… - The program is automatically built. The commands
used, and any error messages, are displayed in the Worksheet.
Only files that have been changed since you last built the
program are compiled, saving considerable time.
Full Build… - The program is completely rebuilt, ignoring
any object files or intermediate files that may already exist
from a previous build. The commands used, and any errors, are
displayed in the Worksheet.
Show Build Commands… - The commands needed to build the program
are written to the Worksheet, but not executed. You can then
select any or all of the commands and execute them yourself.
(To execute the commands select them and press Enter.)
Show Full Build Commands… - The commands needed to completely
rebuild the program are written to the Worksheet. This is a
convenient way to see all of the commands used in building
the program you have selected.
Note: For more information about building the sample programs, see
Chapter 2 of the MPW Reference.
Sample - A Simple MultiFinder-Aware Sample Application
Sample is an example application that demonstrates how to initialize
the commonly used toolbox managers, operate successfully under
MultiFinder, handle desk accessories and create, grow, and zoom windows.
The source for Sample (or TESample below) provides an excellent
framework for basing new applications.
The source is contained in the files Sample.c and Sample.h, resource
descriptions are contained in the files Sample.h and Sample.r.
The make dependency file is named Sample.make.
To build Sample, simply select the line below and press Enter.
BuildProgram Sample ∑∑ {Worksheet}
To execute Sample, select the line below and press Enter.
Sample
TESample - A Simple MultiFinder-Aware TextEdit Application
TESample is an example application that demonstrates how to initialize
the commonly used toolbox managers, operate successfully under
MultiFinder, handle desk accessories and create, grow, and zoom windows.
The fundamental TextEdit toolbox calls and TextEdit autoscroll are
demonstrated. TESample also shows how to create and maintain scrollbar
controls.
The source for TESample (or Sample above) provides an excellent
framework for basing new applications.
The source is contained in the files TESample.c, TESampleGlue.a and
TESample.h, resource descriptions are contained in the files
TESample.h and TESample.r. The make dependency file is named
TESample.make.
To build TESample, simply select the line below and press Enter.
BuildProgram TESample ∑∑ {Worksheet}
To execute TESample, select the line below and press Enter.
TESample
SillyBalls - A Simple Color Quickdraw Sample Application
(Requires Color Quickdraw, e.g. MacII)
SillyBalls is a very simple sample program that demonstrates
how to use Color QuickDraw. It is about two pages of code, and
does nothing more than open a color window and draw randomly
colored ovals in the window.
The purpose is to show how to get some initial results with Color
QuickDraw. It is a complete program and is very short to be as
clear as possible.
The source is contained in the file SillyBalls.c.
To build SillyBalls, simply select the line below and press Enter.
BuildProgram SillyBalls ∑∑ {Worksheet}
To execute SillyBalls, select the line below and press Enter.
SillyBalls
TubeTest - A Simple Color Quickdraw & Palette Manager Sample Application
(Requires Color Quickdraw, e.g. MacII)
TubeTest is a simple demonstration of how to use
the Palette Manager in a color program. It has a special color
palette that is associated with the main window. The colors are
animated using the Palette Manager to give a flowing tube effect.
The program is very simple, and the Palette Manager and drawing
parts are put in separate subroutines to make it easier to figure
out what is happening.
The source is contained in the files TubeTest.c and TubeTest.r
To build TubeTest, simply select the line below and press Enter.
BuildProgram TubeTest ∑∑ {Worksheet}
To execute TubeTest, select the line below and press Enter.
TubeTest
Count - A Sample MPW Tool
Count, a tool that runs in the MPW environment, counts characters and
lines in files. A version of Count is included with MPW, and is
documented in the MPW Reference, Part II. The source for Count is in
the files Count.c, FStubs.c, and Count.r. MakeFile contains the
commands for building Count.
To build Count, simply select the line below and press Enter.
BuildProgram Count ∑∑ {Worksheet}
To test Count, try counting the characters in file Count.c.
Count -c Count.c
Memory - A Sample Desk Accessory
Memory is a sample desk accessory written in C. It displays the memory
available in the application and system heaps, and on the boot disk.
MakeFile contains the commands for building Memory.
To build Memory, simply select the line below and press Enter.
BuildProgram Memory ∑∑ {Worksheet}
NOTE: If you don't have the MPW Assembler, you'll need to select the
line below and press Enter. You won't be able to use SADE to
debug DA's built without the assembler though...
BuildProgram Memory.NOASM ∑∑ {Worksheet}
The build process puts the desk accessory into a Font/DA Mover file.
To install the Memory desk accessory, use the Font/DA Mover to copy
resource Memory from the file Memory into the System file.
After quitting the Font/DA Mover and returning to the MPW Shell, select
"Memory" from the Apple menu.
EditCdev - A Sample Control Panel Device in C
EditCdev demonstrates how to implement a editText item
in a Control Panel Device. It utilizes the new undo, cut, copy,
paste, and delete messages that are sent to cdevs in
response to user menu selections.
To build EditCdev, simply select the line below and press Enter.
BuildProgram EditCdev ∑∑ {Worksheet}
To execute EditCdev, after building it, simply select the Control
Panel desk accessory from the Apple menu, and click on the EditCdev
icon in the list of Control Panel Devices.
TestPerf - An example of Using Performance Tools in C
TestPerf is an MPW tool that demonstrates the use of the performance
measurement tools. MakeFile contains the commands for building TestPerf.
To build TestPerf, simply select the line below and press Enter.
BuildProgram TestPerf ∑∑ {Worksheet}
To execute TestPerf, select and execute the following command. (This
test will run about 15 to 60 seconds, depending upon the machine, with
only internal computations being performed):
TestPerf
TestPerf's raw performance data is written to the file Perform.out.
In this sample use of the performance measurement tools, the ROM was
measured. So the ROM link map file needs to be combined with the program
link map file. Because there are three different ROM maps, select and
execute the line that corresponds to the machine TestPerf was run on:
# For Macintosh Plus:
Catenate "{MPW}ROM Maps:MacPlusROM.map" >> TestPerf.map
# For Macintosh SE:
Catenate "{MPW}ROM Maps:MacSEROM.map" >> TestPerf.map
# For Macintosh II:
Catenate "{MPW}ROM Maps:MacIIROM.map" >> TestPerf.map
PerformReport is an MPW Tool that combines the output of the performance
tools with the link map file and produces a list of procedures, sorted by
estimated percent of time spent in each procedure. To run PerformReport
execute the following command:
PerformReport -l TestPerf.map -m Perform.Out > Report.Out
The output of PerformReport is written to the file Report.Out. To examine
this output, execute the following command:
Open Report.Out
Writing Your Own Programs
After building (and perhaps modifying) the sample programs, you will
undoubtedly want to write a program of your own. Use the New… item in
the File menu, to create the source files. Remember that C language
source filenames should end in .c.
Create Build Commands… - The Create Build Commands… item in the
Build menu runs a script that creates a makefile containing the
commands for building programs written in C, Assembly Language, Pascal,
and/or Rez. Selecting Create Build Commands… displays a dialog box that
allows you to enter information about your program. Type the program's
name, select its source files by clicking the Files… button, and click
one of the radio buttons to indicate your choice of an application, tool,
or desk accessory.
Create Build Commands… puts the makefile for your program in the file
<program>.make. Now you can use the Build menu to build and rebuild
your program, just as with the examples.
Larger Programs - If you add source files as your program grows,
use Create Build Commands… again to add the new source files to the build
instructions. If you out-grow the capabilities of the simple Create
Build Commands… script (perhaps by using tools other than Asm, C, Pascal,
Rez, and Link in your builds) you can modify the makefile yourself.
Modifying the Directory and Build Menus - The Directory and Build
menus are both implemented using scripts written in the MPW Shell
command language. This has the big advantage that you can modify
or customize them to match the way you work.

View File

@ -0,0 +1 @@
TEXTMPS

View File

@ -0,0 +1,18 @@
data 'MPSR' (1005) {
$"0009 4D6F 6E61 636F 006E 7374 7275 6374" /* ..Monaco.nstruct */
$"696F 6E73 0022 0000 6E73 0000 0000 0000" /* ions."..ns...... */
$"0000 0006 0004 002A 0003 0142 01E3 002A" /* .......*...B...* */
$"0003 0142 01E3 A42B A620 0000 0000 0000" /* ...B...+. ...... */
$"0000 0000 0000 0100" /* ........ */
};
data 'MPSR' (1008) {
$"002A 0003 0142 01E3 002A 0003 0142 01E3" /* .*...B...*...B.. */
$"0000 0000 0000 0000 0000 0000 0000" /* .............. */
};
data 'vers' (2, purgeable) {
$"0320 8000 0000 0333 2E32 074D 5057 2033" /* . .....3.2.MPW 3 */
$"2E32" /* .2 */
};

View File

@ -0,0 +1,64 @@
# File MakeFile - Make instructions for C examples.
#
# Copyright Apple Computer, Inc. 1986-1990
# All rights reserved.
#
# This makefile builds:
# The sample C tool: Count
# The sample desk accessory: Memory
# The sample performance tool: TestPerf
#
# You can define {SymOptions} as "-sym on" or "-sym off" for use with SADE
# We also recommend requiring prototypes for all functions
COptions = -r {SymOptions}
Count ƒƒ Count.r
Rez Count.r -o Count -append
Count ƒƒ Count.c.o FStubs.c.o
Link {SymOptions} -w -c 'MPS ' -t MPST Count.c.o FStubs.c.o ∂
-sn STDIO=Main ∂
-sn INTENV=Main ∂
-sn %A5Init=Main ∂
"{Libraries}"Stubs.o ∂
"{CLibraries}"StdCLib.o ∂
"{Libraries}"Interface.o ∂
"{Libraries}"Runtime.o ∂
"{Libraries}"ToolLibs.o ∂
-o Count
Memory ƒƒ Memory.c.o DAEntry.a.o
Link {SymOptions} -w -da -rt DRVR=12 ∂
-m DAEntry -sg Memory # DAEntry is located in DAEntry.a.o ∂
DAEntry.a.o # This must preceed DRVRRuntime.o ∂
"{Libraries}"DRVRRuntime.o # This must preceed Runtime.o ∂
Memory.c.o ∂
"{Libraries}"Runtime.o ∂
"{Libraries}"Interface.o ∂
-o Memory -c DMOV -t DFIL
Memory ƒƒ Memory.r
Rez -rd -c DMOV -t DFIL Memory.r -a -o Memory
Memory.NOASM ƒ Memory.DRVW Memory.r
Rez -rd -c DMOV -t DFIL -d NOASM_BUILD Memory.r -o Memory.NOASM
Duplicate -y Memory.NOASM Memory
Memory.DRVW ƒ Memory.c.o
Link -w -rt DRVW=0 ∂
-sg Memory ∂
"{Libraries}"DRVRRuntime.o ∂
Memory.c.o ∂
"{Libraries}"Runtime.o ∂
"{Libraries}"Interface.o ∂
-o Memory.DRVW -c "????" -t "????"
TestPerf ƒ TestPerf.c.o
Link -d # suppress duplicate warnings ∂
-o TestPerf -t MPST -c 'MPS ' ∂
-l -la > TestPerf.map # produce link map file ∂
TestPerf.c.o "{Libraries}"PerformLib.o ∂
"{Libraries}"Interface.o ∂
"{Libraries}"Runtime.o ∂
"{CLibraries}"StdCLib.o

View File

@ -0,0 +1 @@
TEXTMPS

View File

@ -0,0 +1,18 @@
data 'MPSR' (1005) {
$"0009 4D6F 6E61 636F 0061 6B65 4669 6C65" /* ..Monaco.akeFile */
$"0022 0000 0000 0000 0000 0000 0000 0000" /* .".............. */
$"0000 0006 0004 002A 0003 0142 01E3 002A" /* .......*...B...* */
$"0003 0142 01E3 A42B A620 0000 0000 0000" /* ...B...+. ...... */
$"0000 0000 0000 0100" /* ........ */
};
data 'MPSR' (1008) {
$"002A 0003 0142 01E3 002A 0003 0142 01E3" /* .*...B...*...B.. */
$"0000 0000 0000 0000 0000 0000 0000" /* .............. */
};
data 'vers' (2, purgeable) {
$"0320 8000 0000 0333 2E32 074D 5057 2033" /* . .....3.2.MPW 3 */
$"2E32" /* .2 */
};

View File

@ -0,0 +1,246 @@
/*
File Memory.c
Copyright Apple Computer, Inc. 1985-1987
All rights reserved.
* Memory - report the amount of free space in the
* application and system heap, and on the boot volume.
*
* This is the sample C desk accessory. The desk accessory does not
* use any global variables. Instead, it allocates a handle to a
* structure that holds some "global" variables. This sample program
* could be written without having to use this structure, but then it
* wouldn't be as informative...
*/
#include <types.h>
#include <osutils.h>
#include <memory.h>
#include <devices.h>
#include <events.h>
#include <quickdraw.h>
#include <fonts.h>
#include <windows.h>
#include <files.h>
#include <errors.h>
#include <toolutils.h>
#include <packages.h>
/*
* Macro to compute owned resource id
*/
#define OWNEDRSRCID(id) (0xC000 | (((-(id)) - 1) << 5))
/*
* String constant indexes for STR# resource
*/
#define APPHEAP 1
#define SYSHEAP 2
#define DISK 3
#define FREEON 4
#define ACCEVENT 64
#define ACCRUN 65
/* This structure type holds the global variables used by this desk accessory */
typedef struct {
int rsrcID; /* Computed rsrc id of STR# and WIND resources */
Str255 strBuf; /* Buffer to read strings into */
} Globals;
pascal short DRVROpen(CntrlParam *ctlPB, DCtlPtr dCtl)
{
#pragma unused (ctlPB)
GrafPtr savePort;
WindowPeek myWindow;
long heapGrow;
/*
* If the windowPtr is non-nil, we already have a window open.
* This desk accessory ignores multiple opens.
*/
if (dCtl->dCtlWindow != nil)
return noErr;
GetPort(&savePort);
/*
* Get a handle to some storage that will hold our pseudo-global
* variables. Save the handle in a location accessible by
* all the driver routines.
*/
dCtl->dCtlStorage = NewHandle(sizeof(Globals));
/*
* Compute the resource id of the owned 'STR#' resource that
* contains all of the program's text strings. The id is saved
* in one place that can be accessed by all the driver routines.
*/
((Globals *)(*dCtl->dCtlStorage))->rsrcID = OWNEDRSRCID(dCtl->dCtlRefNum);
/*
* wStorage = nil (allocate on the heap)
* visible = false, behind = -1, goAway = true, refCon = 0
*/
myWindow = (WindowPeek)GetNewWindow(((Globals *)(*dCtl->dCtlStorage))->rsrcID, nil, (WindowPtr) -1);
/*
* Set windowKind to the DA refNum, which is negative.
*/
myWindow->windowKind = dCtl->dCtlRefNum;
/*
* Store the windowPtr in the Device Control Entry
*/
dCtl->dCtlWindow = (WindowPtr)myWindow;
/*
* Now compact the heap in the most violent way.
* Purge whatever's purgeable.
*/
(void) MaxMem(&heapGrow);
SetPort(savePort);
return noErr;
}
pascal short DRVRPrime(CntrlParam *ctlPB, DCtlPtr dCtl)
{
#pragma unused (ctlPB, dCtl)
return noErr; /* Not used in this desk accessory */
}
pascal short DRVRStatus(CntrlParam *ctlPB, DCtlPtr dCtl)
{
#pragma unused (ctlPB, dCtl)
return noErr; /* Not used in this desk accessory */
}
pascal short DRVRControl(CntrlParam *ctlPB, DCtlPtr dCtl)
{
extern void doCtlEvent();
extern void doPeriodic();
/*
* The current grafPort is saved & restored by the Desk Manager
*/
switch (ctlPB->csCode) {
case ACCEVENT: /* accEvent */
HLock(dCtl->dCtlStorage); /* Lock handle since it will be dereferenced */
doCtlEvent( *((EventRecord **) &ctlPB->csParam[0]),
(Globals *)(*dCtl->dCtlStorage));
HUnlock(dCtl->dCtlStorage);
break;
case ACCRUN: /* periodicEvent */
doPeriodic(dCtl);
break;
default:
break;
}
return 0;
}
static void doCtlEvent(register EventRecord *theEvent, Globals *globals)
{
register WindowPtr myWindow;
extern void drawWindow();
if (theEvent->what == updateEvt) {
myWindow = (WindowPtr) theEvent->message;
SetPort(myWindow);
BeginUpdate(myWindow);
drawWindow(myWindow, globals);
EndUpdate(myWindow);
}
}
static void doPeriodic(DCtlPtr dCtl)
{
extern void drawWindow();
SetPort(dCtl->dCtlWindow);
HLock(dCtl->dCtlStorage); /* Lock handle since it will be dereferenced */
drawWindow(dCtl->dCtlWindow, (Globals *)(*dCtl->dCtlStorage));
HUnlock(dCtl->dCtlStorage);
}
/*
* Display the contents of the window.
* The current port is assumed to be set to the window.
*/
static void drawWindow(WindowPtr window, Globals *globals)
{
THz saveZone;
Str27 volName;
HVolumeParam myParamBlk;
void printNum(unsigned long);
static StringPtr text(int index, Globals *globals);
if (window == nil)
return; /* "can't happen" */
TextMode(srcCopy);
TextFont(monaco);
TextSize(9);
MoveTo(6, 10);
TextFace(bold);
saveZone = GetZone();
DrawString(text(APPHEAP, globals));
SetZone(ApplicZone());
printNum(FreeMem());
DrawString(text(SYSHEAP, globals));
SetZone(SystemZone());
printNum(FreeMem());
SetZone(saveZone);
DrawString(text(DISK, globals));
myParamBlk.ioNamePtr = volName;
myParamBlk.ioVRefNum = 0; /* Boot volume */
myParamBlk.ioVolIndex = 0;
(void) PBHGetVInfo((HParmBlkPtr)&myParamBlk, false);
printNum((unsigned long)myParamBlk.ioVAlBlkSiz * myParamBlk.ioVFrBlk);
DrawString(text(FREEON, globals));
TextFace(underline);
DrawString(volName);
}
static void printNum(unsigned long num)
{
unsigned char numStr[32];
TextFace(normal);
NumToString(num, numStr); /* Its possible that a large unsigned
will come back negative! */
DrawString(numStr);
TextFace(bold);
}
pascal short DRVRClose(char *ctlPB, DCtlPtr dCtl)
{ /* Save & Restore current grafPort? */
#pragma unused (ctlPB)
WindowPtr window;
window = (WindowPtr) dCtl->dCtlWindow;
if ( window != nil) {
dCtl->dCtlWindow = nil;
DisposHandle(dCtl->dCtlStorage);
DisposeWindow(window);
}
return 0;
}
static StringPtr text(int index, Globals *globals)
{
GetIndString(globals->strBuf, globals->rsrcID, index);
return(globals->strBuf);
}

View File

@ -0,0 +1 @@
TEXTMPS

View File

@ -0,0 +1,18 @@
data 'MPSR' (1005) {
$"0009 4D6F 6E61 636F 0065 6D6F 7279 2E63" /* ..Monaco.emory.c */
$"0022 0000 0000 0036 0000 0064 6669 6E64" /* .".....6...dfind */
$"00A5 0006 0004 002A 0003 0142 01E3 002A" /* .......*...B...* */
$"0003 0142 01E3 A42B A620 0000 0000 0000" /* ...B...+. ...... */
$"0000 0000 0000 0100" /* ........ */
};
data 'MPSR' (1008) {
$"002A 0003 0142 01E3 002A 0003 0142 01E3" /* .*...B...*...B.. */
$"0000 0000 0000 0000 0000 0000 0000" /* .............. */
};
data 'vers' (2, purgeable) {
$"0320 8000 0000 0333 2E32 074D 5057 2033" /* . .....3.2.MPW 3 */
$"2E32" /* .2 */
};

View File

@ -0,0 +1,84 @@
/*
* File Memory.r
*
* Copyright Apple Computer, Inc. 1985-1987
* All rights reserved.
*
* Sample desk accessory resource file.
* This incorporates the DRVR header information (defined here)
* with the linked code (stored as a 'DRVW' resource in the link command)
*/
#include "Types.r" /* To get system types */
#include "MPWTypes.r" /* To get 'DRVW' type */
#define DriverID 12
#ifdef NOASM_BUILD
/*
* This will produce a DRVR resource from the special DRVW type.
* (this eliminates the need for using the Assembler to create
* the DA header, but makes it impossible to use SADE, oops!)
*
* Note that the ID 12 is irrelevant, since the Font/DA Mover
* will renumber it to something else when installing it anyway.
*
* The leading NUL in the resource name is required to
* conform to the desk accessory naming convention.
*
* The resource is declared purgeable. If the code were to
* do funky things like SetTrapAddress calls (requiring the code to
* be around at all times), we would have to set it nonpurgeable.
*/
type 'DRVR' as 'DRVW'; /* Map 'DRVW' => 'DRVR' */
resource 'DRVR' (DriverID, "\0x00Memory", purgeable) {
/*
* DRVR flags
*/
dontNeedLock, /* OK to float around, not saving ProcPtrs */
needTime, /* Yes, give us periodic Control calls */
dontNeedGoodbye, /* No special requirements */
noStatusEnable,
ctlEnable, /* Desk accessories only do Control calls */
noWriteEnable,
noReadEnable,
5*60, /* drvrDelay - Wake up every 5 seconds */
updateMask, /* drvrEMask - This DA only handles update events */
0, /* drvrMenu - This DA has no menu */
"Memory", /* drvrName - This isn't used by the DA */
/*
* This directive inserts the contents of the DRVW resource
* produced by linking DRVRRuntime.o with our DA code
*/
$$resource("Memory.DRVW", 'DRVW', 0)
};
#endif
/*
* Since desk accessories cannot use global data (and the C compiler
* considers string constants to be global data) and we really don't
* want to hard-code strings in our source, the strings used by the
* DA are stored in the resource file. Note the expression used to
* figure out the resource id.
*/
resource 'STR#' (0xC000 | (DriverID << 5), "Memory's Strings") {
{
"AppHeap: ";
" SysHeap: ";
" Disk: ";
" free on "
};
};
resource 'WIND' (0xC000 | (DriverID << 5), "Memory's Window") {
{322, 10, 338, 500},
noGrowDocProc,
visible,
goAway,
0x0,
"Free Memory (# Bytes)"
};

View File

@ -0,0 +1 @@
TEXTMPS

View File

@ -0,0 +1,18 @@
data 'MPSR' (1005) {
$"0009 4D6F 6E61 636F 0065 6D6F 7279 2E72" /* ..Monaco.emory.r */
$"0022 0000 6D6F 7279 2E72 00D4 0045 14E0" /* ."..mory.r...E.. */
$"0000 0006 0004 002A 0003 0142 01E3 002A" /* .......*...B...* */
$"0003 0142 01E3 A42B A620 0000 0000 0000" /* ...B...+. ...... */
$"0000 0000 0000 0100" /* ........ */
};
data 'MPSR' (1008) {
$"002A 0003 0142 01E3 002A 0003 0142 01E3" /* .*...B...*...B.. */
$"0000 0000 0000 0000 0000 0000 0000" /* .............. */
};
data 'vers' (2, purgeable) {
$"0320 8000 0000 0333 2E32 074D 5057 2033" /* . .....3.2.MPW 3 */
$"2E32" /* .2 */
};

View File

@ -0,0 +1,878 @@
/*------------------------------------------------------------------------------
#
# Apple Macintosh Developer Technical Support
#
# MultiFinder-Aware Simple Sample Application
#
# Sample
#
# Sample.c - C Source
#
# Copyright © Apple Computer, Inc. 1989-1990
# All rights reserved.
#
# Versions:
# 1.00 08/88
# 1.01 11/88
# 1.02 04/89 MPW 3.1
# 1.03 02/90 MPW 3.2
#
# Components:
# Sample.c Feb. 1, 1990
# Sample.r Feb. 1, 1990
# Sample.h Feb. 1, 1990
# Sample.make Feb. 1, 1990
#
# Sample is an example application that demonstrates how to
# initialize the commonly used toolbox managers, operate
# successfully under MultiFinder, handle desk accessories,
# and create, grow, and zoom windows.
#
# It does not by any means demonstrate all the techniques
# you need for a large application. In particular, Sample
# does not cover exception handling, multiple windows/documents,
# sophisticated memory management, printing, or undo. All of
# these are vital parts of a normal full-sized application.
#
# This application is an example of the form of a Macintosh
# application; it is NOT a template. It is NOT intended to be
# used as a foundation for the next world-class, best-selling,
# 600K application. A stick figure drawing of the human body may
# be a good example of the form for a painting, but that does not
# mean it should be used as the basis for the next Mona Lisa.
#
# We recommend that you review this program or TESample before
# beginning a new application.
#
------------------------------------------------------------------------------*/
/* Segmentation strategy:
This program consists of three segments. Main contains most of the code,
including the MPW libraries, and the main program. Initialize contains
code that is only used once, during startup, and can be unloaded after the
program starts. %A5Init is automatically created by the Linker to initialize
globals for the MPW libraries and is unloaded right away. */
/* SetPort strategy:
Toolbox routines do not change the current port. In spite of this, in this
program we use a strategy of calling SetPort whenever we want to draw or
make calls which depend on the current port. This makes us less vulnerable
to bugs in other software which might alter the current port (such as the
bug (feature?) in many desk accessories which change the port on OpenDeskAcc).
Hopefully, this also makes the routines from this program more self-contained,
since they don't depend on the current port setting. */
#include <Values.h>
#include <Types.h>
#include <Resources.h>
#include <QuickDraw.h>
#include <Fonts.h>
#include <Events.h>
#include <Windows.h>
#include <Menus.h>
#include <TextEdit.h>
#include <Dialogs.h>
#include <Desk.h>
#include <ToolUtils.h>
#include <Memory.h>
#include <SegLoad.h>
#include <Files.h>
#include <OSUtils.h>
#include <OSEvents.h>
#include <DiskInit.h>
#include <Packages.h>
#include <Traps.h>
#include "Sample.h" /* bring in all the #defines for Sample */
/* The "g" prefix is used to emphasize that a variable is global. */
/* GMac is used to hold the result of a SysEnvirons call. This makes
it convenient for any routine to check the environment. */
SysEnvRec gMac; /* set up by Initialize */
/* GHasWaitNextEvent is set at startup, and tells whether the WaitNextEvent
trap is available. If it is false, we know that we must call GetNextEvent. */
Boolean gHasWaitNextEvent; /* set up by Initialize */
/* GInBackground is maintained by our osEvent handling routines. Any part of
the program can check it to find out if it is currently in the background. */
Boolean gInBackground; /* maintained by Initialize and DoEvent */
/* The following globals are the state of the window. If we supported more than
one window, they would be attatched to each document, rather than globals. */
/* GStopped tells whether the stop light is currently on stop or go. */
Boolean gStopped; /* maintained by Initialize and SetLight */
/* GStopRect and gGoRect are the rectangles of the two stop lights in the window. */
Rect gStopRect; /* set up by Initialize */
Rect gGoRect; /* set up by Initialize */
/* Here are declarations for all of the C routines. In MPW 3.0 we can use
actual prototypes for parameter type checking. */
void EventLoop( void );
void DoEvent( EventRecord *event );
void AdjustCursor( Point mouse, RgnHandle region );
void GetGlobalMouse( Point *mouse );
void DoUpdate( WindowPtr window );
void DoActivate( WindowPtr window, Boolean becomingActive );
void DoContentClick( WindowPtr window );
void DrawWindow( WindowPtr window );
void AdjustMenus( void );
void DoMenuCommand( long menuResult );
void SetLight( WindowPtr window, Boolean newStopped );
Boolean DoCloseWindow( WindowPtr window );
void Terminate( void );
void Initialize( void );
Boolean GoGetRect( short rectID, Rect *theRect );
void ForceEnvirons( void );
Boolean IsAppWindow( WindowPtr window );
Boolean IsDAWindow( WindowPtr window );
Boolean TrapAvailable( short tNumber, TrapType tType );
void AlertUser( void );
/* Define HiWrd and LoWrd macros for efficiency. */
#define HiWrd(aLong) (((aLong) >> 16) & 0xFFFF)
#define LoWrd(aLong) ((aLong) & 0xFFFF)
/* Define TopLeft and BotRight macros for convenience. Notice the implicit
dependency on the ordering of fields within a Rect */
#define TopLeft(aRect) (* (Point *) &(aRect).top)
#define BotRight(aRect) (* (Point *) &(aRect).bottom)
extern void _DataInit();
/* This routine is part of the MPW runtime library. This external
reference to it is done so that we can unload its segment, %A5Init. */
#pragma segment Main
main()
{
UnloadSeg((Ptr) _DataInit); /* note that _DataInit must not be in Main! */
/* 1.01 - call to ForceEnvirons removed */
/* If you have stack requirements that differ from the default,
then you could use SetApplLimit to increase StackSpace at
this point, before calling MaxApplZone. */
MaxApplZone(); /* expand the heap so code segments load at the top */
Initialize(); /* initialize the program */
UnloadSeg((Ptr) Initialize); /* note that Initialize must not be in Main! */
EventLoop(); /* call the main event loop */
}
/* Get events forever, and handle them by calling DoEvent.
Get the events by calling WaitNextEvent, if it's available, otherwise
by calling GetNextEvent. Also call AdjustCursor each time through the loop. */
#pragma segment Main
void EventLoop()
{
RgnHandle cursorRgn;
Boolean gotEvent;
EventRecord event;
Point mouse;
cursorRgn = NewRgn(); /* well pass WNE an empty region the 1st time thru */
do {
/* use WNE if it is available */
if ( gHasWaitNextEvent ) {
GetGlobalMouse(&mouse);
AdjustCursor(mouse, cursorRgn);
gotEvent = WaitNextEvent(everyEvent, &event, MAXLONG, cursorRgn);
}
else {
SystemTask();
gotEvent = GetNextEvent(everyEvent, &event);
}
if ( gotEvent ) {
/* make sure we have the right cursor before handling the event */
AdjustCursor(event.where, cursorRgn);
DoEvent(&event);
}
/* If you are using modeless dialogs that have editText items,
you will want to call IsDialogEvent to give the caret a chance
to blink, even if WNE/GNE returned FALSE. However, check FrontWindow
for a non-NIL value before calling IsDialogEvent. */
} while ( true ); /* loop forever; we quit via ExitToShell */
} /*EventLoop*/
/* Do the right thing for an event. Determine what kind of event it is, and call
the appropriate routines. */
#pragma segment Main
void DoEvent(event)
EventRecord *event;
{
short part, err;
WindowPtr window;
Boolean hit;
char key;
Point aPoint;
switch ( event->what ) {
case mouseDown:
part = FindWindow(event->where, &window);
switch ( part ) {
case inMenuBar: /* process a mouse menu command (if any) */
AdjustMenus();
DoMenuCommand(MenuSelect(event->where));
break;
case inSysWindow: /* let the system handle the mouseDown */
SystemClick(event, window);
break;
case inContent:
if ( window != FrontWindow() ) {
SelectWindow(window);
/*DoEvent(event);*/ /* use this line for "do first click" */
} else
DoContentClick(window);
break;
case inDrag: /* pass screenBits.bounds to get all gDevices */
DragWindow(window, event->where, &qd.screenBits.bounds);
break;
case inGrow:
break;
case inZoomIn:
case inZoomOut:
hit = TrackBox(window, event->where, part);
if ( hit ) {
SetPort(window); /* the window must be the current port... */
EraseRect(&window->portRect); /* because of a bug in ZoomWindow */
ZoomWindow(window, part, true); /* note that we invalidate and erase... */
InvalRect(&window->portRect); /* to make things look better on-screen */
}
break;
}
break;
case keyDown:
case autoKey: /* check for menukey equivalents */
key = event->message & charCodeMask;
if ( event->modifiers & cmdKey ) /* Command key down */
if ( event->what == keyDown ) {
AdjustMenus(); /* enable/disable/check menu items properly */
DoMenuCommand(MenuKey(key));
}
break;
case activateEvt:
DoActivate((WindowPtr) event->message, (event->modifiers & activeFlag) != 0);
break;
case updateEvt:
DoUpdate((WindowPtr) event->message);
break;
/* 1.01 - It is not a bad idea to at least call DIBadMount in response
to a diskEvt, so that the user can format a floppy. */
case diskEvt:
if ( HiWord(event->message) != noErr ) {
SetPt(&aPoint, kDILeft, kDITop);
err = DIBadMount(aPoint, event->message);
}
break;
case kOSEvent:
/* 1.02 - must BitAND with 0x0FF to get only low byte */
switch ((event->message >> 24) & 0x0FF) { /* high byte of message */
case kSuspendResumeMessage: /* suspend/resume is also an activate/deactivate */
gInBackground = (event->message & kResumeMask) == 0;
DoActivate(FrontWindow(), !gInBackground);
break;
}
break;
}
} /*DoEvent*/
/* 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. */
#pragma segment Main
void AdjustCursor(mouse,region)
Point mouse;
RgnHandle region;
{
WindowPtr window;
RgnHandle arrowRgn;
RgnHandle plusRgn;
Rect globalPortRect;
window = FrontWindow(); /* we only adjust the cursor when we are in front */
if ( (! gInBackground) && (! IsDAWindow(window)) ) {
/* calculate regions for different cursor shapes */
arrowRgn = NewRgn();
plusRgn = NewRgn();
/* start with a big, big rectangular region */
SetRectRgn(arrowRgn, kExtremeNeg, kExtremeNeg, kExtremePos, kExtremePos);
/* calculate plusRgn */
if ( IsAppWindow(window) ) {
SetPort(window); /* make a global version of the viewRect */
SetOrigin(-window->portBits.bounds.left, -window->portBits.bounds.top);
globalPortRect = window->portRect;
RectRgn(plusRgn, &globalPortRect);
SectRgn(plusRgn, window->visRgn, plusRgn);
SetOrigin(0, 0);
}
/* subtract other regions from arrowRgn */
DiffRgn(arrowRgn, plusRgn, arrowRgn);
/* change the cursor and the region parameter */
if ( PtInRgn(mouse, plusRgn) ) {
SetCursor(*GetCursor(plusCursor));
CopyRgn(plusRgn, region);
} else {
SetCursor(&qd.arrow);
CopyRgn(arrowRgn, region);
}
/* get rid of our local regions */
DisposeRgn(arrowRgn);
DisposeRgn(plusRgn);
}
} /*AdjustCursor*/
/* 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. */
#pragma segment Main
void GetGlobalMouse(mouse)
Point *mouse;
{
EventRecord event;
OSEventAvail(kNoEvents, &event); /* we aren't interested in any events */
*mouse = event.where; /* just the mouse position */
} /*GetGlobalMouse*/
/* This is called when an update event is received for a window.
It calls DrawWindow to draw the contents of an application window.
As an effeciency measure that does not have to be followed, it
calls the drawing routine only if the visRgn is non-empty. This
will handle situations where calculations for drawing or drawing
itself is very time-consuming. */
#pragma segment Main
void DoUpdate(window)
WindowPtr window;
{
if ( IsAppWindow(window) ) {
BeginUpdate(window); /* this sets up the visRgn */
if ( ! EmptyRgn(window->visRgn) ) /* draw if updating needs to be done */
DrawWindow(window);
EndUpdate(window);
}
} /*DoUpdate*/
/* This is called when a window is activated or deactivated.
In Sample, the Window Manager's handling of activate and
deactivate events is sufficient. Other applications may have
TextEdit records, controls, lists, etc., to activate/deactivate. */
#pragma segment Main
void DoActivate(window, becomingActive)
WindowPtr window;
Boolean becomingActive;
{
if ( IsAppWindow(window) ) {
if ( becomingActive )
/* do whatever you need to at activation */ ;
else
/* do whatever you need to at deactivation */ ;
}
} /*DoActivate*/
/* This is called when a mouse-down event occurs in the content of a window.
Other applications might want to call FindControl, TEClick, etc., to
further process the click. */
#pragma segment Main
void DoContentClick(window)
WindowPtr window;
{
SetLight(window, ! gStopped);
} /*DoContentClick*/
/* Draw the contents of the application window. We do some drawing in color, using
Classic QuickDraw's color capabilities. This will be black and white on old
machines, but color on color machines. At this point, the windows visRgn
is set to allow drawing only where it needs to be done. */
#pragma segment Main
void DrawWindow(window)
WindowPtr window;
{
SetPort(window);
EraseRect(&window->portRect); /* clear out any garbage that may linger */
if ( gStopped ) /* draw a red (or white) stop light */
ForeColor(redColor);
else
ForeColor(whiteColor);
PaintOval(&gStopRect);
ForeColor(blackColor);
FrameOval(&gStopRect);
if ( ! gStopped ) /* draw a green (or white) go light */
ForeColor(greenColor);
else
ForeColor(whiteColor);
PaintOval(&gGoRect);
ForeColor(blackColor);
FrameOval(&gGoRect);
} /*DrawWindow*/
/* 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 is just as valid. */
#pragma segment Main
void AdjustMenus()
{
WindowPtr window;
MenuHandle menu;
window = FrontWindow();
menu = GetMHandle(mFile);
if ( IsDAWindow(window) ) /* we can allow desk accessories to be closed from the menu */
EnableItem(menu, iClose);
else
DisableItem(menu, iClose); /* but not our traffic light window */
menu = GetMHandle(mEdit);
if ( IsDAWindow(window) ) { /* a desk accessory might need the edit menu… */
EnableItem(menu, iUndo);
EnableItem(menu, iCut);
EnableItem(menu, iCopy);
EnableItem(menu, iClear);
EnableItem(menu, iPaste);
} else { /* …but we dont use it */
DisableItem(menu, iUndo);
DisableItem(menu, iCut);
DisableItem(menu, iCopy);
DisableItem(menu, iClear);
DisableItem(menu, iPaste);
}
menu = GetMHandle(mLight);
if ( IsAppWindow(window) ) { /* we know that it must be the traffic light */
EnableItem(menu, iStop);
EnableItem(menu, iGo);
} else {
DisableItem(menu, iStop);
DisableItem(menu, iGo);
}
CheckItem(menu, iStop, gStopped); /* we can also determine check/uncheck state, too */
CheckItem(menu, iGo, ! gStopped);
} /*AdjustMenus*/
/* This is called when an item is chosen from the menu bar (after calling
MenuSelect or MenuKey). It performs the right operation for each command.
It is good to have both the result of MenuSelect and MenuKey go to
one routine like this to keep everything organized. */
#pragma segment Main
void DoMenuCommand(menuResult)
long menuResult;
{
short menuID; /* the resource ID of the selected menu */
short menuItem; /* the item number of the selected menu */
short itemHit;
Str255 daName;
short daRefNum;
Boolean handledByDA;
menuID = HiWord(menuResult); /* use macros for efficiency to... */
menuItem = LoWord(menuResult); /* get menu item number and menu number */
switch ( menuID ) {
case mApple:
switch ( menuItem ) {
case iAbout: /* bring up alert for About */
itemHit = Alert(rAboutAlert, nil);
break;
default: /* all non-About items in this menu are DAs */
/* type Str255 is an array in MPW 3 */
GetItem(GetMHandle(mApple), menuItem, daName);
daRefNum = OpenDeskAcc(daName);
break;
}
break;
case mFile:
switch ( menuItem ) {
case iClose:
DoCloseWindow(FrontWindow());
break;
case iQuit:
Terminate();
break;
}
break;
case mEdit: /* call SystemEdit for DA editing & MultiFinder */
handledByDA = SystemEdit(menuItem-1); /* since we dont do any Editing */
break;
case mLight:
switch ( menuItem ) {
case iStop:
SetLight(FrontWindow(), true);
break;
case iGo:
SetLight(FrontWindow(), false);
break;
}
break;
}
HiliteMenu(0); /* unhighlight what MenuSelect (or MenuKey) hilited */
} /*DoMenuCommand*/
/* Change the setting of the light. */
#pragma segment Main
void SetLight( window, newStopped )
WindowPtr window;
Boolean newStopped;
{
if ( newStopped != gStopped ) {
gStopped = newStopped;
SetPort(window);
InvalRect(&window->portRect);
}
} /*SetLight*/
/* Close a window. This handles desk accessory and application windows. */
/* 1.01 - 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 closed, i.e.,
the user didnt cancel from a save dialog. This result is handy when
the user quits an application, but then cancels the save of a document
associated with a window. */
#pragma segment Main
Boolean DoCloseWindow(window)
WindowPtr window;
{
if ( IsDAWindow(window) )
CloseDeskAcc(((WindowPeek) window)->windowKind);
else if ( IsAppWindow(window) )
CloseWindow(window);
return true;
} /*DoCloseWindow*/
/**************************************************************************************
*** 1.01 DoCloseBehind(window) was removed ***
1.01 - DoCloseBehind was a good idea for closing windows when quitting
and not having to worry about updating the windows, but it suffered
from a fatal flaw. If a desk accessory owned two windows, it would
close both those windows when CloseDeskAcc was called. When DoCloseBehind
got around to calling DoCloseWindow for that other window that was already
closed, things would go very poorly. Another option would be to have a
procedure, GetRearWindow, that would go through the window list and return
the last window. Instead, we decided to present the standard approach
of getting and closing FrontWindow until FrontWindow returns NIL. This
has a potential benefit in that the window whose document needs to be saved
may be visible since it is the front window, therefore decreasing the
chance of user confusion. For aesthetic reasons, the windows in the
application should be checked for updates periodically and have the
updates serviced.
**************************************************************************************/
/* Clean up the application and exit. We close all of the windows so that
they can update their documents, if any. */
/* 1.01 - If we find out that a cancel has occurred, we won't exit to the
shell, but will return instead. */
#pragma segment Main
void Terminate()
{
WindowPtr aWindow;
Boolean closed;
closed = true;
do {
aWindow = FrontWindow(); /* get the current front window */
if (aWindow != nil)
closed = DoCloseWindow(aWindow); /* close this window */
}
while (closed && (aWindow != nil));
if (closed)
ExitToShell(); /* exit if no cancellation */
} /*Terminate*/
/* Set up the whole world, including global variables, Toolbox managers,
and menus. We also create our one application window at this time.
Since window storage is non-relocateable, how and when to allocate space
for windows is very important so that heap fragmentation does not occur.
Because Sample has only one window and it is only disposed when the application
quits, we will allocate its space here, before anything that might be a locked
relocatable object gets into the heap. This way, we can force the storage to be
in the lowest memory available in the heap. Window storage can differ widely
amongst applications depending on how many windows are created and disposed. */
/* 1.01 - The code that used to be part of ForceEnvirons has been moved into
this module. If an error is detected, instead of merely doing an ExitToShell,
which leaves the user without much to go on, we call AlertUser, which puts
up a simple alert that just says an error occurred and then calls ExitToShell.
Since there is no other cleanup needed at this point if an error is detected,
this form of error- handling is acceptable. If more sophisticated error recovery
is needed, an exception mechanism, such as is provided by Signals, can be used. */
#pragma segment Initialize
void Initialize()
{
Handle menuBar;
WindowPtr window;
long total, contig;
EventRecord event;
short count;
gInBackground = false;
InitGraf((Ptr) &qd.thePort);
InitFonts();
InitWindows();
InitMenus();
TEInit();
InitDialogs(nil);
InitCursor();
/* Call MPPOpen and ATPLoad at this point to initialize AppleTalk,
if you are using it. */
/* NOTE -- It is no longer necessary, and actually unhealthy, to check
PortBUse and SPConfig before opening AppleTalk. The drivers are capable
of checking for port availability themselves. */
/* This next bit of code is necessary to allow the default button of our
alert be outlined.
1.02 - Changed to call EventAvail so that we don't lose some important
events. */
for (count = 1; count <= 3; count++)
EventAvail(everyEvent, &event);
/* Ignore the error returned from SysEnvirons; even if an error occurred,
the SysEnvirons glue will fill in the SysEnvRec. You can save a redundant
call to SysEnvirons by calling it after initializing AppleTalk. */
SysEnvirons(kSysEnvironsVersion, &gMac);
/* Make sure that the machine has at least 128K ROMs. If it doesn't, exit. */
if (gMac.machineType < 0) AlertUser();
/* 1.02 - Move TrapAvailable call to after SysEnvirons so that we can tell
in TrapAvailable if a tool trap value is out of range. */
gHasWaitNextEvent = TrapAvailable(_WaitNextEvent, ToolTrap);
/* 1.01 - We used to make a check for memory at this point by examining ApplLimit,
ApplicZone, and StackSpace and comparing that to the minimum size we told
MultiFinder we needed. This did not work well because it assumed too much about
the relationship between what we asked MultiFinder for and what we would actually
get back, as well as how to measure it. Instead, we will use an alternate
method comprised of two steps. */
/* It is better to first check the size of the application heap against a value
that you have determined is the smallest heap the application can reasonably
work in. This number should be derived by examining the size of the heap that
is actually provided by MultiFinder when the minimum size requested is used.
The derivation of the minimum size requested from MultiFinder is described
in Sample.h. The check should be made because the preferred size can end up
being set smaller than the minimum size by the user. This extra check acts to
insure that your application is starting from a solid memory foundation. */
if ((long) GetApplLimit() - (long) ApplicZone() < kMinHeap) AlertUser();
/* Next, make sure that enough memory is free for your application to run. It
is possible for a situation to arise where the heap may have been of required
size, but a large scrap was loaded which left too little memory. To check for
this, call PurgeSpace and compare the result with a value that you have determined
is the minimum amount of free memory your application needs at initialization.
This number can be derived several different ways. One way that is fairly
straightforward is to run the application in the minimum size configuration
as described previously. Call PurgeSpace at initialization and examine the value
returned. However, you should make sure that this result is not being modified
by the scrap's presence. You can do that by calling ZeroScrap before calling
PurgeSpace. Make sure to remove that call before shipping, though. */
/* ZeroScrap(); */
PurgeSpace(&total, &contig);
if (total < kMinSpace) AlertUser();
/* The extra benefit to waiting until after the Toolbox Managers have been initialized
to check memory is that we can now give the user an alert to tell him/her what
happened. Although it is possible that the memory situation could be worsened by
displaying an alert, MultiFinder would gracefully exit the application with
an informative alert if memory became critical. Here we are acting more
in a preventative manner to avoid future disaster from low-memory problems. */
/* we will allocate our own window storage instead of letting the Window
Manager do it because GetNewWindow may load in temp. resources before
making the NewPtr call, and this can lead to heap fragmentation. */
window = (WindowPtr) NewPtr(sizeof(WindowRecord));
if ( window == nil ) AlertUser();
window = GetNewWindow(rWindow, (Ptr) window, (WindowPtr) -1);
menuBar = GetNewMBar(rMenuBar); /* read menus into menu bar */
if ( menuBar == nil ) AlertUser();
SetMenuBar(menuBar); /* install menus */
DisposHandle(menuBar);
AddResMenu(GetMHandle(mApple), 'DRVR'); /* add DA names to Apple menu */
DrawMenuBar();
gStopped = true;
if ( !GoGetRect(rStopRect, &gStopRect) )
AlertUser(); /* the stop light rectangle */
if ( !GoGetRect(rGoRect, &gGoRect) )
AlertUser(); /* the go light rectangle */
} /*Initialize*/
/* 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. In this particular case, we know
that this routine is being called at initialization time. Therefore,
if a failure occurs here, we will assume that the application is in such
bad shape that we should just exit. Your error handling may differ, but
the check should still be made. */
#pragma segment Initialize
Boolean GoGetRect(rectID,theRect)
short rectID;
Rect *theRect;
{
Handle resource;
resource = GetResource('RECT', rectID);
if ( resource != nil ) {
*theRect = **((Rect**) resource);
return true;
}
else
return false;
} /* GoGetRect */
/* 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
mean it is a dialog.
1.02 - 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. */
#pragma segment Main
Boolean IsAppWindow(window)
WindowPtr window;
{
short windowKind;
if ( window == nil )
return false;
else { /* application windows have windowKinds = userKind (8) */
windowKind = ((WindowPeek) window)->windowKind;
return (windowKind == userKind);
}
} /*IsAppWindow*/
/* Check to see if a window belongs to a desk accessory. */
#pragma segment Main
Boolean IsDAWindow(window)
WindowPtr window;
{
if ( window == nil )
return false;
else /* DA windows have negative windowKinds */
return ((WindowPeek) window)->windowKind < 0;
} /*IsDAWindow*/
/* Check to see if a given trap is implemented. This is only used by the
Initialize routine in this program, so we put it in the Initialize segment.
The recommended approach to see if a trap is implemented is to see if
the address of the trap routine is the same as the address of the
Unimplemented trap. */
/* 1.02 - Needs to be called after call to SysEnvirons so that it can check
if a ToolTrap is out of range of a pre-MacII ROM. */
#pragma segment Initialize
Boolean TrapAvailable(tNumber,tType)
short tNumber;
TrapType tType;
{
if ( ( tType == ToolTrap ) &&
( gMac.machineType > envMachUnknown ) &&
( gMac.machineType < envMacII ) ) { /* it's a 512KE, Plus, or SE */
tNumber = tNumber & 0x03FF;
if ( tNumber > 0x01FF ) /* which means the tool traps */
tNumber = _Unimplemented; /* only go to 0x01FF */
}
return NGetTrapAddress(tNumber, tType) != GetTrapAddress(_Unimplemented);
} /*TrapAvailable*/
/* 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. The error number is used
to index an 'STR#' resource so that a relevant message can be displayed. */
#pragma segment Main
void AlertUser()
{
short itemHit;
SetCursor(&qd.arrow);
itemHit = Alert(rUserAlert, nil);
ExitToShell();
} /* AlertUser */

View File

@ -0,0 +1 @@
TEXTMPS

View File

@ -0,0 +1,18 @@
data 'MPSR' (1005) {
$"0009 4D6F 6E61 636F 006C 6F73 6500 4844" /* ..Monaco.lose.HD */
$"3A43 6F70 7920 6F66 204D 5057 5F4F 7574" /* :Copy of MPW_Out */
$"3A45 0006 0004 002A 0003 0142 01E3 002A" /* :E.....*...B...* */
$"0003 0142 01E3 A42B A620 0000 0000 0000" /* ...B...+. ...... */
$"0000 0000 0000 0100" /* ........ */
};
data 'MPSR' (1008) {
$"002A 0003 0142 01E3 002A 0003 0142 01E3" /* .*...B...*...B.. */
$"0000 0000 0000 0000 0000 0000 0000" /* .............. */
};
data 'vers' (2, purgeable) {
$"0320 8000 0000 0333 2E32 074D 5057 2033" /* . .....3.2.MPW 3 */
$"2E32" /* .2 */
};

View File

@ -0,0 +1,197 @@
/*------------------------------------------------------------------------------
#
# Apple Macintosh Developer Technical Support
#
# MultiFinder-Aware Simple Sample Application
#
# Sample
#
# Sample.h - Rez and C Include Source
#
# Copyright © Apple Computer, Inc. 1989-1990
# All rights reserved.
#
# Versions:
# 1.00 08/88
# 1.01 11/88
# 1.02 04/89 MPW 3.1
# 1.03 02/90 MPW 3.2
#
# Components:
# Sample.c Feb. 1, 1990
# Sample.r Feb. 1, 1990
# Sample.h Feb. 1, 1990
# Sample.make Feb. 1, 1990
#
# Sample is an example application that demonstrates how to
# initialize the commonly used toolbox managers, operate
# successfully under MultiFinder, handle desk accessories,
# and create, grow, and zoom windows.
#
# It does not by any means demonstrate all the techniques
# you need for a large application. In particular, Sample
# does not cover exception handling, multiple windows/documents,
# sophisticated memory management, printing, or undo. All of
# these are vital parts of a normal full-sized application.
#
# This application is an example of the form of a Macintosh
# application; it is NOT a template. It is NOT intended to be
# used as a foundation for the next world-class, best-selling,
# 600K application. A stick figure drawing of the human body may
# be a good example of the form for a painting, but that does not
# mean it should be used as the basis for the next Mona Lisa.
#
# We recommend that you review this program or TESample before
# beginning a new application.
------------------------------------------------------------------------------*/
/* These #defines correspond to values defined in the Pascal source code.
Sample.c and Sample.r include this file. */
/* Determining an application's minimum size to request from MultiFinder depends
on many things, each of which can be unique to an application's function,
the anticipated environment, the developer's attitude of what constitutes
reasonable functionality and performance, etc. Here is a list of some things to
consider when determining the minimum size (and preferred size) for your
application. The list is pretty much in order of importance, but by no means
complete.
1. What is the minimum size needed to give almost 100 percent assurance
that the application won't crash because it ran out of memory? This
includes not only things that you do have direct control over such as
checking for NIL handles and pointers, but also things that some
feel are not so much under their control such as QuickDraw and the
Segment Loader.
2. What kind of performance can a user expect from the application when
it is running in the minimum memory configuration? Performance includes
not only speed in handling data, but also things like how many documents
can be opened, etc.
3. What are the typical sizes of scraps [is a boy dog] that a user might
wish to work with when lauching or switching to your application? If
the amount of memory is too small, the scrap may get lost [will have
to be shot]. This can be quite frustrating to the user.
4. The previous items have concentrated on topics that tend to cause an
increase in the minimum size to request from MultiFinder. On the flip
side, however, should be the consideration of what environments the
application may be running in. There may be a high probability that
many users with relatively small memory configurations will want to
avail themselves of your application. Or, many users might want to use it
while several other, possibly related/complementary applications are
running. If that is the case, it would be helpful to have a fairly
small minimum size.
So, what did we decide on Sample? First, Sample has little risk of
running out of memory once it starts. Second, performance isn't much
of an issue since it doesn't do much and multiple windows are not
allowed. Third, there are no edit operations in Sample itself, so we
just want to provide enough space for a reasonable scrap to survive
between desk accessory launches. Lastly, Sample should intrude as little
as possible, so the effort should be towards making it as small as possible.
We looked at some heap dumps while the application was running under
various partition sizes. With a size of 23K, there was approximately
8-9K free, which is a good 'slop' factor in an application like this
which doesn't do much, but where we'd still like the scrap to survive
most of the time. */
#define kMinSize 23 /* application's minimum size (in K) */
/* We made the preferred size bigger than the minimum size by 12K, so that
there would be even more room for the scrap, FKEYs, etc. */
#define kPrefSize 35 /* application's preferred size (in K) */
#define rMenuBar 128 /* application's menu bar */
#define rAboutAlert 128 /* about alert */
#define rUserAlert 129 /* error user alert */
#define rWindow 128 /* application's window */
#define rStopRect 128 /* rectangle for Stop light */
#define rGoRect 129 /* rectangle for Go light */
/* kSysEnvironsVersion is passed to SysEnvirons to tell it which version of the
SysEnvRec we understand. */
#define kSysEnvironsVersion 1
/* kOSEvent is the event number of the suspend/resume and mouse-moved events sent
by MultiFinder. Once we determine that an event is an osEvent, we look at the
high byte of the message sent to determine which kind it is. To differentiate
suspend and resume events we check the resumeMask bit. */
#define kOSEvent app4Evt /* event used by MultiFinder */
#define kSuspendResumeMessage 1 /* high byte of suspend/resume event message */
#define kResumeMask 1 /* bit of message field for resume vs. suspend */
#define kMouseMovedMessage 0xFA /* high byte of mouse-moved event message */
#define kNoEvents 0 /* no events mask */
/* The following constants are used to identify menus and their items. The menu IDs
have an "m" prefix and the item numbers within each menu have an "i" prefix. */
#define mApple 128 /* Apple menu */
#define iAbout 1
#define mFile 129 /* File menu */
#define iNew 1
#define iClose 4
#define iQuit 12
#define mEdit 130 /* Edit menu */
#define iUndo 1
#define iCut 3
#define iCopy 4
#define iPaste 5
#define iClear 6
#define mLight 131 /* Light menu */
#define iStop 1
#define iGo 2
/* 1.01 - kTopLeft - This is for positioning the Disk Initialization dialogs. */
#define kDITop 0x0050
#define kDILeft 0x0070
/* 1.01 - kMinHeap - This is the minimum result from the following
equation:
ORD(GetApplLimit) - ORD(ApplicZone)
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. */
#define kMinHeap 21 * 1024
/* 1.01 - kMinSpace - This is the minimum 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. */
#define kMinSpace 8 * 1024
/* kExtremeNeg and kExtremePos are used to set up wide open rectangles and regions. */
#define kExtremeNeg -32768
#define kExtremePos 32767 - 1 /* required to address an old region bug */
/* these #defines are used to set enable/disable flags of a menu */
#define AllItems 0b1111111111111111111111111111111 /* 31 flags */
#define NoItems 0b0000000000000000000000000000000
#define MenuItem1 0b0000000000000000000000000000001
#define MenuItem2 0b0000000000000000000000000000010
#define MenuItem3 0b0000000000000000000000000000100
#define MenuItem4 0b0000000000000000000000000001000
#define MenuItem5 0b0000000000000000000000000010000
#define MenuItem6 0b0000000000000000000000000100000
#define MenuItem7 0b0000000000000000000000001000000
#define MenuItem8 0b0000000000000000000000010000000
#define MenuItem9 0b0000000000000000000000100000000
#define MenuItem10 0b0000000000000000000001000000000
#define MenuItem11 0b0000000000000000000010000000000
#define MenuItem12 0b0000000000000000000100000000000

View File

@ -0,0 +1 @@
TEXTMPS

View File

@ -0,0 +1,18 @@
data 'MPSR' (1005) {
$"0009 4D6F 6E61 636F 0045 9B74 0000 0000" /* ..Monaco.E.t.... */
$"0000 0074 0001 E6B8 0000 0035 0000 0064" /* ...t.......5...d */
$"636C 0006 0004 002A 0003 0142 01E3 002A" /* cl.....*...B...* */
$"0003 0142 01E3 A42B A620 0000 0000 0000" /* ...B...+. ...... */
$"0000 0000 0000 0100" /* ........ */
};
data 'MPSR' (1008) {
$"002A 0003 0142 01E3 002A 0003 0142 01E3" /* .*...B...*...B.. */
$"0000 0000 0000 0000 0000 0000 0000" /* .............. */
};
data 'vers' (2, purgeable) {
$"0320 8000 0000 0333 2E32 074D 5057 2033" /* . .....3.2.MPW 3 */
$"2E32" /* .2 */
};

View File

@ -0,0 +1,61 @@
#
# Apple Macintosh Developer Technical Support
#
# MultiFinder-Aware Simple Sample Application
#
# Sample
#
# [C]Sample.make - Make Source
#
# Copyright © Apple Computer, Inc. 1989-1990
# All rights reserved.
#
# Versions:
# 1.00 08/88
# 1.01 11/88
# 1.02 04/89 MPW 3.1
# 1.03 02/90 MPW 3.2
#
# Components:
# Sample.c Feb. 1, 1990
# Sample.r Feb. 1, 1990
# Sample.h Feb. 1, 1990
# Sample.make Feb. 1, 1990
#
# Sample is an example application that demonstrates how to
# initialize the commonly used toolbox managers, operate
# successfully under MultiFinder, handle desk accessories,
# and create, grow, and zoom windows.
#
# It does not by any means demonstrate all the techniques
# you need for a large application. In particular, Sample
# does not cover exception handling, multiple windows/documents,
# sophisticated memory management, printing, or undo. All of
# these are vital parts of a normal full-sized application.
#
# This application is an example of the form of a Macintosh
# application; it is NOT a template. It is NOT intended to be
# used as a foundation for the next world-class, best-selling,
# 600K application. A stick figure drawing of the human body may
# be a good example of the form for a painting, but that does not
# mean it should be used as the basis for the next Mona Lisa.
#
# We recommend that you review this program or TESample before
# beginning a new application.
#
# You can define {SymOptions} as "-sym on" or "-sym off" for use with SADE
# We also recommend requiring prototypes for all functions
COptions = -r {SymOptions}
CObjs = Sample.c.o ∂
"{Libraries}"Runtime.o ∂
"{Libraries}"Interface.o
Sample ƒƒ {CObjs} Sample.make
Link -o {Targ} {CObjs} {SymOptions}
SetFile {Targ} -t APPL -c 'MOOS' -a B
Sample ƒƒ Sample.r Sample.h Sample.make
Rez -rd -o {Targ} Sample.r -append
Sample.c.o ƒƒ Sample.make

View File

@ -0,0 +1 @@
TEXTMPS

View File

@ -0,0 +1,18 @@
data 'MPSR' (1005) {
$"0009 4D6F 6E61 636F 0061 6D70 6C65 2E6D" /* ..Monaco.ample.m */
$"616B 6500 2200 0024 2F2D FD58 2F2D FD54" /* ake."..$/-.X/-.T */
$"2F2D 0006 0004 002A 0003 0142 01E3 002A" /* /-.....*...B...* */
$"0003 0142 01E3 A42B A620 0000 0000 0000" /* ...B...+. ...... */
$"0000 0000 0000 0100" /* ........ */
};
data 'MPSR' (1008) {
$"002A 0003 0142 01E3 002A 0003 0142 01E3" /* .*...B...*...B.. */
$"0000 0000 0000 0000 0000 0000 0000" /* .............. */
};
data 'vers' (2, purgeable) {
$"0320 8000 0000 0333 2E32 074D 5057 2033" /* . .....3.2.MPW 3 */
$"2E32" /* .2 */
};

View File

@ -0,0 +1,284 @@
/*------------------------------------------------------------------------------
#
# Apple Macintosh Developer Technical Support
#
# MultiFinder-Aware Simple Sample Application
#
# Sample
#
# Sample.r - Rez Source
#
# Copyright © Apple Computer, Inc. 1989-1990
# All rights reserved.
#
# Versions:
# 1.00 08/88
# 1.01 11/88
# 1.02 04/89 MPW 3.1
# 1.03 02/90 MPW 3.2
#
# Components:
# Sample.c Feb. 1, 1990
# Sample.r Feb. 1, 1990
# Sample.h Feb. 1, 1990
# Sample.make Feb. 1, 1990
#
# Sample is an example application that demonstrates how to
# initialize the commonly used toolbox managers, operate
# successfully under MultiFinder, handle desk accessories,
# and create, grow, and zoom windows.
#
# It does not by any means demonstrate all the techniques
# you need for a large application. In particular, Sample
# does not cover exception handling, multiple windows/documents,
# sophisticated memory management, printing, or undo. All of
# these are vital parts of a normal full-sized application.
#
# This application is an example of the form of a Macintosh
# application; it is NOT a template. It is NOT intended to be
# used as a foundation for the next world-class, best-selling,
# 600K application. A stick figure drawing of the human body may
# be a good example of the form for a painting, but that does not
# mean it should be used as the basis for the next Mona Lisa.
#
# We recommend that you review this program or TESample before
# beginning a new application.
------------------------------------------------------------------------------*/
#include "SysTypes.r"
#include "Types.r"
#include "Sample.h"
resource 'vers' (1) {
0x02, 0x00, release, 0x00,
verUS,
"1.03",
"1.03, Copyright \251 Apple Computer, Inc. 1989-1990"
};
/* this is a definition for a resource which contains only a rectangle */
type 'RECT' {
rect;
};
/* we use an MBAR resource to conveniently load all the menus */
resource 'MBAR' (rMenuBar, preload) {
{ mApple, mFile, mEdit, mLight }; /* four menus */
};
resource 'MENU' (mApple, preload) {
mApple, textMenuProc,
AllItems & ~MenuItem2, /* Disable dashed line, enable About and DAs */
enabled, apple,
{
"About Sample…",
noicon, nokey, nomark, plain;
"-",
noicon, nokey, nomark, plain
}
};
resource 'MENU' (mFile, preload) {
mFile, textMenuProc,
MenuItem12, /* enable Quit only, program enables others */
enabled, "File",
{
"New",
noicon, "N", nomark, plain;
"Open",
noicon, "O", nomark, plain;
"-",
noicon, nokey, nomark, plain;
"Close",
noicon, "W", nomark, plain;
"Save",
noicon, "S", nomark, plain;
"Save As…",
noicon, nokey, nomark, plain;
"Revert",
noicon, nokey, nomark, plain;
"-",
noicon, nokey, nomark, plain;
"Page Setup…",
noicon, nokey, nomark, plain;
"Print…",
noicon, nokey, nomark, plain;
"-",
noicon, nokey, nomark, plain;
"Quit",
noicon, "Q", nomark, plain
}
};
resource 'MENU' (mEdit, preload) {
mEdit, textMenuProc,
NoItems, /* disable everything, program does the enabling */
enabled, "Edit",
{
"Undo",
noicon, "Z", nomark, plain;
"-",
noicon, nokey, nomark, plain;
"Cut",
noicon, "X", nomark, plain;
"Copy",
noicon, "C", nomark, plain;
"Paste",
noicon, "V", nomark, plain;
"Clear",
noicon, nokey, nomark, plain
}
};
resource 'MENU' (mLight, preload) {
mLight, textMenuProc,
NoItems, /* disable everything, program does the enabling */
enabled, "Traffic",
{
"Red Light",
noicon, nokey, nomark, plain;
"Green Light",
noicon, nokey, nomark, plain
}
};
/* this ALRT and DITL are used as an About screen */
resource 'ALRT' (rAboutAlert, purgeable) {
{40, 20, 160, 297},
rAboutAlert,
{ /* array: 4 elements */
/* [1] */
OK, visible, silent,
/* [2] */
OK, visible, silent,
/* [3] */
OK, visible, silent,
/* [4] */
OK, visible, silent
}
};
resource 'DITL' (rAboutAlert, purgeable) {
{ /* array DITLarray: 5 elements */
/* [1] */
{88, 185, 108, 265},
Button {
enabled,
"OK"
},
/* [2] */
{8, 8, 24, 214},
StaticText {
disabled,
"Simple Sample (Traffic Light)"
},
/* [3] */
{32, 8, 48, 296},
StaticText {
disabled,
"Copyright © Apple Computer 1989-1990"
},
/* [4] */
{56, 8, 72, 136},
StaticText {
disabled,
"Brought to you by:"
},
/* [5] */
{80, 24, 112, 167},
StaticText {
disabled,
"Macintosh Developer  Technical Support"
}
}
};
/* this ALRT and DITL are used as an error screen */
resource 'ALRT' (rUserAlert, purgeable) {
{40, 20, 120, 260},
rUserAlert,
{ /* array: 4 elements */
/* [1] */
OK, visible, silent,
/* [2] */
OK, visible, silent,
/* [3] */
OK, visible, silent,
/* [4] */
OK, visible, silent
}
};
resource 'DITL' (rUserAlert, purgeable) {
{ /* array DITLarray: 3 elements */
/* [1] */
{50, 150, 70, 230},
Button {
enabled,
"OK"
},
/* [2] */
{10, 60, 30, 230},
StaticText {
disabled,
"Sample - Error occurred!"
},
/* [3] */
{8, 8, 40, 40},
Icon {
disabled,
2
}
}
};
resource 'WIND' (rWindow, preload, purgeable) {
{60, 40, 290, 160},
noGrowDocProc, visible, noGoAway, 0x0, "Traffic"
};
resource 'RECT' (rStopRect, preload, purgeable) {
{10, 10, 110, 110}
};
resource 'RECT' (rGoRect, preload, purgeable) {
{120, 10, 220, 110}
};
/* here is the quintessential MultiFinder friendliness device, the SIZE resource */
resource 'SIZE' (-1) {
dontSaveScreen,
acceptSuspendResumeEvents,
enableOptionSwitch,
canBackground, /* we can background; we don't currently, but our sleep value */
/* guarantees we don't hog the Mac while we are in the background */
multiFinderAware, /* this says we do our own activate/deactivate; don't fake us out */
backgroundAndForeground, /* this is definitely not a background-only application! */
dontGetFrontClicks, /* change this is if you want "do first click" behavior like the Finder */
ignoreChildDiedEvents, /* essentially, I'm not a debugger (sub-launching) */
not32BitCompatible, /* this app should not be run in 32-bit address space */
reserved,
reserved,
reserved,
reserved,
reserved,
reserved,
reserved,
kPrefSize * 1024,
kMinSize * 1024
};

View File

@ -0,0 +1 @@
TEXTMPS

View File

@ -0,0 +1,18 @@
data 'MPSR' (1005) {
$"0009 4D6F 6E61 636F 0061 6D70 6C65 2E72" /* ..Monaco.ample.r */
$"0022 0000 00C0 FFF8 4E5E 4E75 8773 6967" /* ."......N^Nu.sig */
$"5F64 0006 0004 002A 0003 0142 01E3 002A" /* _d.....*...B...* */
$"0003 0142 01E3 A42B A620 0000 0000 0000" /* ...B...+. ...... */
$"0000 0000 0000 0100" /* ........ */
};
data 'MPSR' (1008) {
$"002A 0003 0142 01E3 002A 0003 0142 01E3" /* .*...B...*...B.. */
$"0000 0000 0000 0000 0000 0000 0000" /* .............. */
};
data 'vers' (2, purgeable) {
$"0320 8000 0000 0333 2E32 074D 5057 2033" /* . .....3.2.MPW 3 */
$"2E32" /* .2 */
};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@
TEXTMPS

View File

@ -0,0 +1,18 @@
data 'MPSR' (1005) {
$"0009 4D6F 6E61 636F 0045 9B80 0000 0000" /* ..Monaco.E...... */
$"0000 0074 0001 E72C 0000 0037 0000 0064" /* ...t...,...7...d */
$"636C 0006 0004 002A 0003 0142 01E3 002A" /* cl.....*...B...* */
$"0003 0142 01E3 A42B A620 0000 0000 0000" /* ...B...+. ...... */
$"0000 0000 0000 0100" /* ........ */
};
data 'MPSR' (1008) {
$"002A 0003 0142 01E3 002A 0003 0142 01E3" /* .*...B...*...B.. */
$"0000 0000 0000 0000 0000 0000 0000" /* .............. */
};
data 'vers' (2, purgeable) {
$"0320 8000 0000 0333 2E32 074D 5057 2033" /* . .....3.2.MPW 3 */
$"2E32" /* .2 */
};

View File

@ -0,0 +1,242 @@
/*------------------------------------------------------------------------------
#
# Apple Macintosh Developer Technical Support
#
# MultiFinder-Aware TextEdit Sample Application
#
# TESample
#
# TESample.h - Rez and C Include Source
#
# Copyright © Apple Computer, Inc. 1989-1990
# All rights reserved.
#
# Versions:
# 1.00 08/88
# 1.01 11/88
# 1.02 04/89 MPW 3.1
# 1.03 02/90 MPW 3.2
#
# Components:
# TESample.c Feb. 1, 1990
# TESampleGlue.a Feb. 1, 1990
# TESample.r Feb. 1, 1990
# TESample.h Feb. 1, 1990
# TESample.make Feb. 1, 1990
#
# TESample is an example application that demonstrates how
# to initialize the commonly used toolbox managers, operate
# successfully under MultiFinder, handle desk accessories and
# create, grow, and zoom windows. The fundamental TextEdit
# toolbox calls and TextEdit autoscroll are demonstrated. It
# also shows how to create and maintain scrollbar controls.
#
# It does not by any means demonstrate all the techniques you
# need for a large application. In particular, Sample does not
# cover exception handling, multiple windows/documents,
# sophisticated memory management, printing, or undo. All of
# these are vital parts of a normal full-sized application.
#
# This application is an example of the form of a Macintosh
# application; it is NOT a template. It is NOT intended to be
# used as a foundation for the next world-class, best-selling,
# 600K application. A stick figure drawing of the human body may
# be a good example of the form for a painting, but that does not
# mean it should be used as the basis for the next Mona Lisa.
#
# We recommend that you review this program or Sample before
# beginning a new application. Sample is a simple app. which doesnt
# use TextEdit or the Control Manager.
#
------------------------------------------------------------------------------*/
/* These #defines correspond to values in the Pascal source code.
TESample.c and TESample.r include this file. */
/* Determining an application's minimum size to request from MultiFinder depends
on many things, each of which can be unique to an application's function,
the anticipated environment, the developer's attitude of what constitutes
reasonable functionality and performance, etc. Here is a list of some things to
consider when determining the minimum size (and preferred size) for your
application. The list is pretty much in order of importance, but by no means
complete.
1. What is the minimum size needed to give almost 100 percent assurance
that the application won't crash because it ran out of memory? This
includes not only things that you do have direct control over such as
checking for NIL handles and pointers, but also things that some
feel are not so much under their control such as QuickDraw and the
Segment Loader.
2. What kind of performance can a user expect from the application when
it is running in the minimum memory configuration? Performance includes
not only speed in handling data, but also things like how many documents
can be opened, etc.
3. What are the typical sizes of scraps is [a boy dog] that a user might
wish to work with when lauching or switching to your application? If
the amount of memory is too small, the scrap may get lost [will have
to be shot]. This can be quite frustrating to the user.
4. The previous items have concentrated on topics that tend to cause an
increase in the minimum size to request from MultiFinder. On the flip
side, however, should be the consideration of what environments the
application may be running in. There may be a high probability that
many users with relatively small memory configurations will want to
avail themselves of your application. Or, many users might want to use it
while several other, possibly related/complementary applications are
running. If that is the case, it would be helpful to have a fairly
small minimum size.
What we did for TESample:
We determined the smallest heap size that TESample could have and still
run (22K). For the preferred size we added enough space to permit:
a. a maximum size TextEdit text handle (32000 characters)
b. a maximum usable TextEdit scrap (32000 characters)
b. a maximum scrap as a result of Copy (32000 characters)
d. a little performance cushion (see 2, above) (10K)
Result: 122K for preferred size
For the minimum size we took the 22K and then scaled down our requirements
for a,b, and c above. We thought that providing 16K more would be lean
and mean (see 4, above).
Result: 38K for minimum size
*/
#define kPrefSize 122
#define kMinSize 38
/* The following constants are used to identify menus and their items. The menu IDs
have an "m" prefix and the item numbers within each menu have an "i" prefix. */
#define mApple 128 /* Apple menu */
#define iAbout 1
#define mFile 129 /* File menu */
#define iNew 1
#define iClose 4
#define iQuit 12
#define mEdit 130 /* Edit menu */
#define iUndo 1
#define iCut 3
#define iCopy 4
#define iPaste 5
#define iClear 6
/* 1.01 - kTopLeft - This is for positioning the Disk Initialization dialogs. */
#define kDITop 0x0050
#define kDILeft 0x0070
/* 1.01 - changed constants to begin with 'k' for consistency, except for resource IDs */
/* kTextMargin is the number of pixels we leave blank at the edge of the window. */
#define kTextMargin 2
/* kMaxOpenDocuments is used to determine whether a new document can be opened
or created. We keep track of the number of open documents, and disable the
menu items that create a new document when the maximum is reached. If the
number of documents falls below the maximum, the items are enabled again. */
#define kMaxOpenDocuments 1
/* kMaxDocWidth is an arbitrary number used to specify the width of the TERec's
destination rectangle so that word wrap and horizontal scrolling can be
demonstrated. */
#define kMaxDocWidth 576
/* kMinDocDim is used to limit the minimum dimension of a window when GrowWindow
is called. */
#define kMinDocDim 64
/* kControlInvisible is used to 'turn off' controls (i.e., cause the control not
to be redrawn as a result of some Control Manager call such as SetCtlValue)
by being put into the contrlVis field of the record. kControlVisible is used
the same way to 'turn on' the control. */
#define kControlInvisible 0
#define kControlVisible 0xFF
/* kScrollbarAdjust and kScrollbarWidth are used in calculating
values for control positioning and sizing. */
#define kScrollbarWidth 16
#define kScrollbarAdjust (kScrollbarWidth - 1)
/* kScrollTweek compensates for off-by-one requirements of the scrollbars
to have borders coincide with the growbox. */
#define kScrollTweek 2
/* kCrChar is used to match with a carriage return when calculating the
number of lines in the TextEdit record. kDelChar is used to check for
delete in keyDowns. */
#define kCrChar 13
#define kDelChar 8
/* kButtonScroll is how many pixels to scroll horizontally when the button part
of the horizontal scrollbar is pressed. */
#define kButtonScroll 4
/* kMaxTELength is an arbitrary number used to limit the length of text in the TERec
so that various errors won't occur from too many characters in the text. */
#define kMaxTELength 32000
/* kSysEnvironsVersion is passed to SysEnvirons to tell it which version of the
SysEnvRec we understand. */
#define kSysEnvironsVersion 1
/* kOSEvent is the event number of the suspend/resume and mouse-moved events sent
by MultiFinder. Once we determine that an event is an OSEvent, we look at the
high byte of the message sent to determine which kind it is. To differentiate
suspend and resume events we check the resumeMask bit. */
#define kOSEvent app4Evt /* event used by MultiFinder */
#define kSuspendResumeMessage 1 /* high byte of suspend/resume event message */
#define kResumeMask 1 /* bit of message field for resume vs. suspend */
#define kMouseMovedMessage 0xFA /* high byte of mouse-moved event message */
#define kNoEvents 0 /* no events mask */
/* 1.01 - kMinHeap - This is the minimum result from the following
equation:
ORD(GetApplLimit) - ORD(ApplicZone)
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. */
#define kMinHeap (29 * 1024)
/* 1.01 - kMinSpace - This is the minimum 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. */
#define kMinSpace (20 * 1024)
/* kExtremeNeg and kExtremePos are used to set up wide open rectangles and regions. */
#define kExtremeNeg -32768
#define kExtremePos (32767 - 1) /* required to address an old region bug */
/* kTESlop provides some extra security when pre-flighting edit commands. */
#define kTESlop 1024
/* The following are indicies into STR# resources. */
#define eWrongMachine 1
#define eSmallSize 2
#define eNoMemory 3
#define eNoSpaceCut 4
#define eNoCut 5
#define eNoCopy 6
#define eExceedPaste 7
#define eNoSpacePaste 8
#define eNoWindow 9
#define eExceedChar 10
#define eNoPaste 11
#define rMenuBar 128 /* application's menu bar */
#define rAboutAlert 128 /* about alert */
#define rUserAlert 129 /* user error alert */
#define rDocWindow 128 /* application's window */
#define rVScroll 128 /* vertical scrollbar control */
#define rHScroll 129 /* horizontal scrollbar control */
#define kErrStrings 128 /* error string list */

View File

@ -0,0 +1 @@
TEXTMPS

View File

@ -0,0 +1,18 @@
data 'MPSR' (1005) {
$"0009 4D6F 6E61 636F 0045 9B80 0000 0000" /* ..Monaco.E...... */
$"0000 0074 0001 E6B4 0000 0037 0000 0064" /* ...t.......7...d */
$"636C 0006 0004 002A 0003 0142 01E3 002A" /* cl.....*...B...* */
$"0003 0142 01E3 A42B A620 0000 0000 0000" /* ...B...+. ...... */
$"0000 0000 0000 0100" /* ........ */
};
data 'MPSR' (1008) {
$"002A 0003 0142 01E3 002A 0003 0142 01E3" /* .*...B...*...B.. */
$"0000 0000 0000 0000 0000 0000 0000" /* .............. */
};
data 'vers' (2, purgeable) {
$"0320 8000 0000 0333 2E32 074D 5057 2033" /* . .....3.2.MPW 3 */
$"2E32" /* .2 */
};

View File

@ -0,0 +1,66 @@
#
# Apple Macintosh Developer Technical Support
#
# MultiFinder-Aware Simple TextEdit Sample Application
#
# TESample
#
# [C]TESample.make - Make Source
#
# Copyright © Apple Computer, Inc. 1989-1990
# All rights reserved.
#
# Versions:
# 1.00 08/88
# 1.01 11/88
# 1.02 04/89 MPW 3.1
# 1.03 02/90 MPW 3.2
#
# Components:
# TESample.c Feb. 1, 1990
# TESampleGlue.a Feb. 1, 1990
# TESample.r Feb. 1, 1990
# TESample.h Feb. 1, 1990
# TESample.make Feb. 1, 1990
#
# TESample is an example application that demonstrates how
# to initialize the commonly used toolbox managers, operate
# successfully under MultiFinder, handle desk accessories and
# create, grow, and zoom windows. The fundamental TextEdit
# toolbox calls and TextEdit autoscroll are demonstrated. It
# also shows how to create and maintain scrollbar controls.
#
# It does not by any means demonstrate all the techniques you
# need for a large application. In particular, Sample does not
# cover exception handling, multiple windows/documents,
# sophisticated memory management, printing, or undo. All of
# these are vital parts of a normal full-sized application.
#
# This application is an example of the form of a Macintosh
# application; it is NOT a template. It is NOT intended to be
# used as a foundation for the next world-class, best-selling,
# 600K application. A stick figure drawing of the human body may
# be a good example of the form for a painting, but that does not
# mean it should be used as the basis for the next Mona Lisa.
#
# We recommend that you review this program or Sample before
# beginning a new application. Sample is a simple app. which doesnt
# use TextEdit or the Control Manager.
#
# You can define {SymOptions} as "-sym on" or "-sym off" for use with SADE
# We also recommend requiring prototypes for all functions
COptions = -r {SymOptions}
CObjs = TESample.c.o ∂
TESampleGlue.a.o ∂
"{Libraries}"Runtime.o ∂
"{Libraries}"Interface.o
TESample ƒƒ {CObjs} TESample.make
Link -o {Targ} {CObjs} {SymOptions}
SetFile {Targ} -t APPL -c 'MOOT' -a B
TESample ƒƒ TESample.r TESample.h TESample.make
Rez -rd -append -o {Targ} TESample.r
TESample.c.o ƒƒ TESample.c TESample.make

Some files were not shown because too many files have changed in this diff Show More