home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Generous Efforts of Many
/
gemcd.zip
/
GEM.CD.E.po
/
NDA:CLOCKS:CLOCK
/
CLOCK.ASM.txt
< prev
next >
Wrap
Text File
|
2010-05-14
|
15KB
|
508 lines
*******************************************
* This is the source file for a New Desk *
* Accessory (NDA) which displays the *
* current date and time in a window on *
* the GS desktop. After assembling, use *
* the APW FILETYPE command to change the *
* file type code of CLOCK to $B8, then *
* transfer CLOCK to the SYSTEM/DESK.ACCS/ *
* directory of the ProDOS 16 boot disk. *
* *
* by Gary Little April 5, 1987 *
* *
* (This program is adapted from a similar *
* one in the Desk Accessories chapter of *
* my "Exploring the Apple IIGS" book, to *
* be published in July, 1987 by *
* Addison-Wesley.) *
* *
*******************************************
LIST OFF
SYMBOL OFF
ABSADDR ON
INSTIME ON
GEN ON
KEEP CLOCK ;Code file
MCOPY CLOCK.MAC ;Macro file
Period GEQU 60 ;Ask for "run" action every second
EventMask GEQU $FFFF ;Handle all events
NDA_Clock START
DC I4'NDA_Open' ;Open the NDA
DC I4'NDA_Close' ;Close the NDA
DC I4'NDA_Action' ;Perform NDA action
DC I4'NDA_Init' ;Startup/Shutdown the NDA
DC I2'Period' ;Periodicity of "run" action
DC I2'EventMask' ;Permitted events
DC C'##' ;Name in menu item form
DC C'Clock' ;Text for NDA name
DC C'\H**',I1'0' ;ID field + terminator
; Open the NDA if it has not been previously opened. This routine
; must return a pointer to the NDA window on the stack, just above
; the 3-byte return address. The Desk Manager reserves this result
; space just before calling NDA_Open with a JSL instruction.
NDA_Open ANOP
Result EQU $05 ;Result stack offset after JSL, PHB
PHB
PHK
PLB ;data bank = code bank
LDA ClockOpen ;Clock window already open?
BNE Ignore ;if so, branch
PHA ;Space for result
PHA
PushPtr WindowDef
_NewWindow ;Create and open NDA window
PLX ;Pop pointer (low)
PLA ;Pop pointer (high)
STX WindowPtr ;Save pointer to window
STA WindowPtr+2
STA Result+2,S ;Save result on stack (high)
TXA
STA Result,S ; (low)
PushLong WindowPtr
_SetSysWindow ;Mark this as a DA window
LDA #$FFFF
STA ClockOpen ;Set "open" flag
PHA ;space for result
PHA
_GetCursorAdr
PopLong OldCursor ;Save pointer to regular cursor
Ignore PLB
RTL
; Close the NDA if it is not already closed:
NDA_Close ANOP
PHB
PHK
PLB ;data bank = code bank
LDA ClockOpen ;Is the clock window open?
BEQ Ignore ;No, so branch
PushLong WindowPtr
_CloseWindow ;Get rid of the window
STZ ClockOpen ;Mark clock as closed
PushLong OldCursor
_SetCursor ;Restore application cursor
PLB
RTL
; Perform the NDA action:
NDA_Action ANOP
PHB ;Save data bank
PHK
PLB ;Make data bank = program bank
PHY ;Save incoming parameters
PHX ;(event record or menu info)
ASL A ;x2 to step into table
TAX
JSR (ActionTbl,X)
PLX ;Fix up the stack
PLY
PLB
RTL
ActionTbl ANOP
DC I2'NoAction'
DC I2'NDA_Event'
DC I2'NDA_Run'
DC I2'NDA_Cursor'
DC I2'NDA_Menu'
DC I2'NDA_Undo'
DC I2'NDA_Cut'
DC I2'NDA_Copy'
DC I2'NDA_Paste'
DC I2'NDA_Clear'
NoAction ANOP
RTS
NDA_Menu ANOP
RTS
NDA_Undo ANOP
NDA_Cut ANOP
NDA_Copy ANOP
NDA_Paste ANOP
NDA_Clear ANOP
; On exit A=0 if edit command wasn't handled; non-zero if it was.
; You will usually want to say it was handled, because the application
; will not be active and so shouldn't be dealing with edit commands.
LDA #$FFFF ;Say we handled it.
RTS
; Display a wristwatch cursor if the cursor is over top of
; the content region of the window. This routine is only called
; when the DA window is the front window.
NDA_Cursor ANOP
PHA
PHA
_GetPort ;Save current GrafPort
PushLong WindowPtr
_SetPort ;Make clock window active GrafPort
PushPtr PortRect
_GetPortRect ;Get the port rectangle (local coords)
PushPtr MousePosn ;Return mouse position in GrafPort coords
_GetMouse ;Get cursor position
PHA ;space for result
PushPtr MousePosn ;pointer to mouse coordinate
PushPtr PortRect ;pointer to content region rectangle
_PtInRect
PLA ;Is it in content region?
BEQ NDA_Curs1 ;No, so branch
; Switch to watch cursor, but only if it's not already active:
PHA
PHA
_GetCursorAdr ;Get current cursor pointer
PLA
PLX
CMP #WatchCurs ;Is it the watch?
BNE NDA_Curs0 ;Definitely not
CPX #^WatchCurs ;Is it the watch?
BEQ NDA_Curs3 ;Yes, so do nothing
NDA_Curs0 PushPtr WatchCurs
BRA NDA_Curs2
; Switch to application cursor, but only if it's not already active:
NDA_Curs1 PHA
PHA
_GetCursorAdr ;Get current cursor pointer
PLA
PLX
CMP #WatchCurs ;Is it the watch?
BNE NDA_Curs3 ;No, so don't do anything
CPX #^WatchCurs ;Is it the watch?
BNE NDA_Curs3 ;No, so don't do anything
PushLong OldCursor ;Switch to application cursor
NDA_Curs2 _SetCursor
NDA_Curs3 _SetPort ;Restore GrafPort
RTS
; This subroutine is called once every "Period" ticks:
NDA_Run ANOP
PHA ;Space for result
PHA
_GetPort ;Save current port
PushLong WindowPtr
_SetPort ;Switch to clock window for drawing
JSR ShowTime ;Display the new time
_SetPort ;(Pointer still on stack)
RTS
; X and Y (pushed on stack) contain pointer to event record
NDA_Event ANOP
TheEvent EQU $05 ;1 (base) + 2 (JSR) + 2 (PHD)
PHD
TSC
TCD ;Align d.p. with stack
LDA [TheEvent] ;Get "what" code
CMP #9 ;Anything we support?
BCS TE1 ;No, so branch
ASL A ;x2 to step into table
TAX
JSR (EventTbl,X)
TE1 PLD ;Restore direct page
RTS
EventTbl ANOP
DC I2'NoEvent' ;Not supported
DC I2'DoMouseDwn' ; Mouse down
DC I2'DoMouseUp' ; Mouse up
DC I2'DoKeyDwn' ; Key down
DC I2'NoEvent' ;Not supported
DC I2'DoAutoKey' ; Autokey
DC I2'DoUpdate' ; Update
DC I2'NoEvent' ;Not supported
DC I2'DoActivate' ; Activate
DoMouseUp ANOP
DoMouseDwn ANOP
DoKeyDwn ANOP
DoAutoKey ANOP
NoEvent RTS
DoUpdate ANOP
PushLong WindowPtr
_BeginUpdate ;Visible region = update region
JSR ShowTime ;Display the current time
PushLong WindowPtr
_EndUpdate ;Restore entire visible region
RTS
; If NDA window is deactivated, return to original cursor.
DoActivate ANOP
LDY #14 ;Access modifiers field
LDA [TheEvent],Y
AND #$01 ;Isolate activate/deactivate flag
BEQ NDA_Off ;If 0, deactivate
RTS
NDA_Off PushLong OldCursor
_SetCursor ;Switch to previous cursor
RTS
ShowTime ANOP
PushPtr TheTime
_ReadASCIITime ;Read the clock
SEP #$20 ;8-bit A register for byte accesses
LONGA OFF
LDY #19
ST1 LDA TheTime,Y
AND #$7F ;Convert to standard ASCII
STA TheTime,Y
DEY
BPL ST1
REP #$20 ;Back to 16-bit A register
LONGA ON
;Get the name of the day of the week:
PHA ;Space for 8 bytes of result
PHA
PHA
PHA
_ReadTimeHex
PLA ;Pop minute/second
PLA ;Pop year/hour
PLA ;Pop month/day
PLA ;Pop day of week (high byte)
XBA ;Put day of week in low byte
AND #$0F ;Strip unused bits
DEC A ;Convert 1..7 to 0..6 (1=Sunday)
; Look for the Nth entry in the table:
TAY
LDX #0
SEP #$20 ;Use 8-bit accumulator
LONGA OFF
Find_DOW CPY #0 ;At correct name?
BEQ Move_DOW ;Yes, so branch
FE1 LDA DayTable,X
BEQ FE2 ;Branch if at end of name
INX ;Move to next character
BRA FE1
FE2 INX ;Move to start of next name
DEY ;Decrement day-of-week counter
BRA Find_DOW
; Transfer the name to the buffer area:
Move_DOW ANOP
LDY #0
SR1 LDA DayTable,X
BEQ SR2 ;Branch if at end of name
STA TheDay,Y
INX
INY
BRA SR1
SR2 REP #$20 ;Back to 16-bit accumulator
LONGA ON
PushWord #2 ;horizontal
PushWord #9 ;vertical
_MoveTo
PushPtr TheTime
_DrawCString ;Draw the time string
PushWord #10 ;horizontal
PushWord #19 ;vertical
_MoveTo
PHA
_GetForeColor ;Save foreground color
Pushword #5 ;Dark Green letters
_SetForeColor
PRINTG 'Copyright (c) 1987 Gary B. Little'
_SetForeColor ;Restore foreground color
RTS
; Startup or shutdown the NDA. On entry, A=0 for DeskShutdown,
; A is nonzero for DeskStartup.
NDA_Init ANOP
PHB
PHK
PLB
CMP #0 ;Starting up?
BNE NDA_Init1 ;Yes, so do nothing
LDA ClockOpen ;Clock window open?
BEQ NDA_Init1 ;No, so branch
PushLong WindowPtr
_CloseWindow ;Close the window (releases memory)
STZ ClockOpen ;Set "closed" flag
NDA_Init1 PLB
RTL
; The data area begins here:
NDA_Title STR 'Calendar/Clock' ;Window title
WindowDef ANOP
DC I2'EndWind-WindowDef'
DC I2'%1100000010100000' ;Window with close box, title
DC I4'NDA_Title' ;Pointer to window name
DC I4'0'
DC I2'0,0,0,0'
DC I4'0'
DC I4'0' ;Origin at (0,0)
DC I4'0'
DC I4'0'
DC I4'0'
DC I4'0'
DC I4'0'
DC I2'0'
DC I4'0'
DC I4'0'
DC I4'0' ;(Handle our own updates)
DC I'30,33,52,284' ;Dimensions of window
DC I4'-1' ;Put clock window in front
DC I4'0'
EndWind ANOP
WindowPtr DS 4 ;Pointer to window record
ClockOpen DS 2 ;Used as a flag
PortRect DS 8 ;Content region rectangle
MousePosn DS 4 ;Current mouse position (local)
TheTime DS 20 ;ReadASCIITime returns 20 bytes here
DC C' -- '
TheDay DS 9 ;Day of week inserted here
DC C' ' ;Add padding
DC I1'0' ;(terminator for DrawCString)
DayTable ANOP
DC C'Sunday ',I1'0'
DC C'Monday ',I1'0'
DC C'Tuesday ',I1'0'
DC C'Wednesday',I1'0'
DC C'Thursday ',I1'0'
DC C'Friday ',I1'0'
DC C'Saturday ',I1'0'
OldCursor DS 4 ;Pointer to application's cursor record
; This the is the cursor record for a "wristwatch" cursor:
WatchCurs DC I2'12' ;Rows in cursor image
DC I2'3' ;Cursor width (in words)
DC H'000000000000' ;The cursor image
DC H'000FF0000000'
DC H'000FF0000000'
DC H'00F00F000000'
DC H'0F00F0F00000'
DC H'0F00F0F00000'
DC H'0F0FF0FF0000'
DC H'0F0000F00000'
DC H'00F00F000000'
DC H'000FF0000000'
DC H'000FF0000000'
DC H'000000000000'
DC H'000FF0000000' ;The cursor mask
DC H'00FFFF000000'
DC H'00FFFF000000'
DC H'0FFFFFF00000'
DC H'FFFFFFFF0000'
DC H'FFFFFFFF0000'
DC H'FFFFFFFFF000'
DC H'FFFFFFFF0000'
DC H'0FFFFFF00000'
DC H'00FFFF000000'
DC H'00FFFF000000'
DC H'000FF0000000'
DC I2'6,8' ;Hot spot (y,x)
END