Files
Shawn Quick dfcaae62dd Add qlink, the disk tools, and a bootable ProDOS 8 image.
Move the assembler to src/qasm. qlink links OMF 1.0 and 2.0 from a script. makeBin flattens a load file, qomf dumps OMF, and qpro builds ProDOS volumes. APW and MPW assemble through the ORCA front end. Relocatable modules emit OMF objects. Listings stay off unless -l is set.

make boot assembles the GS/OS 6.0.1 ProDOS 8 kernel and BASIC.SYSTEM into an 800K volume. BASIC.SYSTEM accepts ls and pfx, and its splash reports PRODOS BASIC 2.0, copyright 1983-2026. IIGS.601.SRC is the source and the BASIC.SYSTEM oracle that image is built from.
2026-10-16 14:41:55 -07:00

1 line
17 KiB
Plaintext

**********************************************************************
*
* GSTextEdit Version 1.0
* File: scroll.aii
*
* Copyright Apple Computer, Inc. 1988-89
* All rights reserved
*
*
*
*
* Notes
*
* All the routines in GSTextEdit must be called in full native mode and
* return that way.
*
* All the files in GSTextEdit must be assembled with the "-unsafe"
* option to pass unresolved references to the linker.
*
*
*
*
* Change History
*
* 30 May 89 Dave Good
*
* Cleaned up comments for final release.
*
**********************************************************************
INCLUDE 'GlobalIncludes'
****************************************************************
ScrollActionProc PROCNAME Export
;---------------------------------------------------------------
DefineStack
origPort long
origD word
origB byte
returnAddr block 3
theCtrlHandle long
partCode word
;---------------------------------------------------------------
;---------------------------------------------------------------
phb ;save the old data bank
phk ;set the new data bank
plb
phd ;save the old direct page
jsr GetDirectPage ;setup our direct page
tcd
jsr GetPort ;save the current port
lda theCtrlHandle,s ;find the TextEdit record associated
sta TempPtr ;..with this scroll bar.
lda theCtrlHandle+2,s
sta TempPtr+2
jsr DerefTempPtr
ldy #CtrlRecord.ctlRefCon
lda [TempPtr],y
sta RecordHandle
iny
iny
lda [TempPtr],y
sta RecordHandle+2
jsr LockRecordHandle ;lock the main record handle
jsr SetWindowPort ;switch to the TextEdit port
ldx #0
lda partCode,s
cmp #upArrow
beq doUp
cmp #downArrow
beq doDown
cmp #pageUp
beq doPageUp
cmp #pageDown
beq doPageDown
cmp #thumb
beq doThumb
;---------------------------------------------------------------
allDone jsr SetPort ;restore the current port
jsr UnlockRecordHandle
pld
lda 3,s
sta 9,s
lda 1,s
sta 7,s
pla ;pull off the garbage
pla
pla
plb
rtl
;---------------------------------------------------------------
doThumb ldy #CtrlRecord.ctlValue
lda [TempPtr],y
sec
ldy #TERecord.VertScrollPos
sbc [RecordPtr],y
bpl doTheScroll
dex
bra doTheScroll
;---------------------------------------------------------------
doUp lda #-1
dex
bra doTheScroll
;---------------------------------------------------------------
doDown lda #1
bra doTheScroll
;---------------------------------------------------------------
doPageUp ldy #CtrlRecord.viewSize
lda [TempPtr],y
dec a
eor #$FFFF
inc a
dex
bra doTheScroll
;---------------------------------------------------------------
doPageDown ldy #CtrlRecord.viewSize
lda [TempPtr],y
dec a
;---------------------------------------------------------------
doTheScroll jsr ScrollByAmount
bra allDone
;---------------------------------------------------------------
ENDP
****************************************************************
Scroll1Proc PROC
;---------------------------------------------------------------
EXPORT CenterTheSelection
EXPORT ScrollToSelection
;---------------------------------------------------------------
;---------------------------------------------------------------
AdjustmentForCenter equ ScrollDelta
;---------------------------------------------------------------
;---------------------------------------------------------------
CenterTheSelection jsr GetSelectionStart
jsr FindLineInfo
stz AdjustmentForCenter
ldy #TERecord.ViewRect.bottom
lda [RecordPtr],y
sec
ldy #TERecord.ViewRect.top
sbc [RecordPtr],y
sbc LineHeight
bcc @skip
lsr a
sta AdjustmentForCenter
@skip
bra doIt
;---------------------------------------------------------------
ScrollToSelection stz AdjustmentForCenter
jsr GetRecordLong ;find either the start or the end of the
stax TextOffset ;..current selection
;---------------------------------------------------------------
doIt jsr checkForNoScroll ;if we cannot scroll, then exit
jsr OffsetToVPos ;check to see if the current text offset
movl TextOffset,OriginalOffset ;..is off the screen. Also save the text
bcs @offScreen ;..offset
lda TextVPos ;the line is on screen here, now check to
ldy #TERecord.ViewRect.top ;..see if the top is off the screen. If it
cmp [RecordPtr],y ;..is, then moveBack specially
bmi @specialBack
jsr FindLineInfo ;now see if the bottom of the line is off
lda TextVPos ;..the screen. If it is, then move forward
clc
adc LineHeight
ldy #TERecord.ViewRect.bottom
cmp [RecordPtr],y
bmi @exit
bne @specialForward
@exit rts
@specialBack ldy #TERecord.TopTextVPos
lda [RecordPtr],y
ldx #0
bra realBack
@specialForward sec ;find out how far the line is off the
ldy #TERecord.ViewRect.bottom ;..bottom of the screen
sbc [RecordPtr],y
clc ;add the adjustment for center
adc AdjustmentForCenter
ldx #0
jsr DivideByScrollAmount ;convert to scroll chunks and save the number
sta TempWord ;..of chunks in TempWord
jsr MultiplyByScrollAmount ;convert back to pixels and see if the top
eor #$FFFF ;..of the line will be moved off the
inc a ;..screen.
clc
adc TextVPos
ldy #TERecord.ViewRect.top
cmp [RecordPtr],y ;if it will be moved off the top, then
bmi @exit ;..exit
lda TempWord ;otherwise scroll by the saved amount
ldx #0
brl ScrollByAmount
@offScreen lda TextVPos ;if the TextVPos is not equal to the top
ldy #TERecord.ViewRect.top ;..then move forward
cmp [RecordPtr],y
bne moveForward
;---------------------------------------------------------------
moveBackward jsr GetScreenTopOffset
ldy #TERecord.TopTextVPos
lda [RecordPtr],y
sta TempLong
stz TempLong+2
@loop decl TextOffset
jsr FindLineStart
lda LineHeight
addl TempLong
cmpl OriginalOffset,TextOffset
blt @loop
ldax TempLong
realBack clc
adc AdjustmentForCenter
bcc @1
inx
@1 jsr DivideByScrollAmount
jsr NegateAX
brl ScrollByAmount
;---------------------------------------------------------------
moveForward ldy #TERecord.ViewRect.bottom
lda [RecordPtr],y
sta TextVPos
jsr VPosToOffset
lda #$FFFF
sta TempLong+2
lda TextVPos
sec
ldy #TERecord.ViewRect.bottom
sbc [RecordPtr],y
sta TempLong
bne @1
stz TempLong+2
@1
jsr FindLineInfo
@loop jsr MoveOffsetToNextItem
jsr FindLineInfo
lda LineHeight
addl TempLong
cmpl OriginalOffset,TextOffset
bgt @loop
jsr IsOffsetAtEnd
bne @skipEnd
ldy #TERecord.LineAtEndFlag
lda [RecordPtr],y
beq @skipEnd
lda LineHeight
addl TempLong
@skipEnd ldax TempLong
clc
adc AdjustmentForCenter
bcc @2
inx
@2 jsr DivideByScrollAmount
brl ScrollByAmount
;---------------------------------------------------------------
ENDP
****************************************************************
ScrollByAmount PROCNAME Export
;---------------------------------------------------------------
stax AmountScrolled ;this is the number of chunks to scroll
jsr checkForNoScroll ;if we are not scrolling, then exit
;---------------------------------------------------------------
doIt jsr ClearOffsetCache
ldy #TERecord.VertScrollMax
jsr GetRecordLong
stax TempPtr
ldy #TERecord.VertScrollPos ;update the new vertical position,
lda [RecordPtr],y ;..clipping to TempPtr. Also leave the
sta TempLong ;..original in TempLong
clc
adc AmountScrolled
tax
iny
iny
lda [RecordPtr],y
sta TempLong+2
adc AmountScrolled+2
bpl @notMinus
lda #0
tax
@notMinus cmp TempPtr+2
blt @noClip
bne @clipIt
cpx TempPtr
ble @noClip
@clipIt lda TempPtr+2
ldx TempPtr
@noClip sta [RecordPtr],y
dey
dey
txa
sta [RecordPtr],y
sta TempWord ;save the new value in TempPtr
jsr GetVertScrollBar
beq @skipSet
PushZWord TempWord
PushAX
_SetCtlValue
@skipSet
;---------------------------------------------------------------
lda TempLong ;the old position minus the new position
sec ;..is the amount we are scrolling.
ldy #TERecord.VertScrollPos
sbc [RecordPtr],y
pha
iny
iny
lda TempLong+2
sbc [RecordPtr],y
tax
ora 1,s
bne doTheScroll
pla
rts
;---------------------------------------------------------------
doTheScroll pla ;cleanup the stack
jsr MultiplyByScrollAmount ;convert chunks to pixels and save in
stax AmountScrolled ;..AmountScrolled
jsr GetViewRect ;scroll the entire view rect
ldax AmountScrolled ;get back the amount to scroll
jsr FastScrollRect
lda AmountScrolled+2
bpl movingBack
;---------------------------------------------------------------
movingForward jsr GetScreenTopOffset
lda AmountScrolled
sec
ldy #TERecord.TopTextVPos
sbc [RecordPtr],y
sta AmountScrolled
bcs @1
dec AmountScrolled+2
@1
@loop jsr FindLineInfo
lda LineHeight
addl AmountScrolled
lda AmountScrolled+2
bpl @done
jsr MoveOffsetToNextItem
bra @loop
@done lda AmountScrolled
bne @subIt
jsr MoveOffsetToNextItem
lda #0
bra setAndDraw
@subIt lda LineHeight
sec
sbc AmountScrolled
bra setAndDraw
;---------------------------------------------------------------
movingBack jsr GetScreenTopOffset
ldy #TERecord.TopTextVPos
lda [RecordPtr],y
sec
sbc AmountScrolled
sta AmountScrolled
lda #0
sbc AmountScrolled+2
sta AmountScrolled+2
bcs @thru
@loop decl TextOffset
jsr FindLineStart
lda LineHeight
addl AmountScrolled
lda AmountScrolled+2
bmi @loop
@thru lda AmountScrolled
;---------------------------------------------------------------
setAndDraw ldy #TERecord.TopTextVPos
sta [RecordPtr],y
jsr SetScreenTopOffset
brl DoDraw
;---------------------------------------------------------------
ENDP
****************************************************************
DivideByScrollAmount PROCNAME Export
PushLongSpace
PushLongSpace
PushAX ;this is what to divide
pea $0000
ldy #TERecord.VertScrollAmount
lda [RecordPtr],y
pha
_LongDivide
ply ;get back the low word of the result
plx ;get back the high word of the result
pla
sta TempWord
pla
ora TempWord
beq @exact
tya
incl a
clc
rts
@exact tya
sec
rts
ENDP
****************************************************************
MultiplyByScrollAmount PROCNAME Export
;---------------------------------------------------------------
PushLongSpace ;space for the result
PushLongSpace
PushAX ;push the amount in chuncks
pea $0000 ;push the chunk size
ldy #TERecord.VertScrollAmount
lda [RecordPtr],y
pha
_LongMul
PullAX ;this is the number of pixels
ply ;cleanup the stack
ply
rts
;---------------------------------------------------------------
ENDP
****************************************************************
ResetScrollBar PROCNAME Export
;---------------------------------------------------------------
jsr checkForNoScroll ;if we are not scrolling, then exit
;---------------------------------------------------------------
ldy #TERecord.TotalHeight ;find the new maximum value for the
jsr GetRecordLong ;..vertical scroll bar
clc
ldy #TERecord.ViewRect.top
adc [RecordPtr],y
bcc @1
inx
@1 sec
ldy #TERecord.ViewRect.bottom
sbc [RecordPtr],y
bcs @2
dex
@2 cpx #$8000
blt @notZero
lda #0
tax
bra @clipToMax
@notZero jsr DivideByScrollAmount
@clipToMax PushAX ;save the new maximum scroll pos on the
ldy #TERecord.VertScrollMax ;..stack. Also save it in the record.
jsr SetRecordLong
lda 1,s ;restore the A-Reg
ldy #TERecord.VertScrollPos
sec
sbc [RecordPtr],y
pha
iny
iny
txa
sbc [RecordPtr],y
tax
pla
cpx #$8000
blt @noClip
stax TempLong
jsr NegateAX
jsr MultiplyByScrollAmount
cpx #0
bne @clearDrawRect
cmp #$8000
bge @clearDrawRect
sta TempWord
clc
adc DrawRect.top
bvs @clearDrawRect
ldy #TERecord.ViewRect.bottom
cmp [RecordPtr],y
bpl @clearDrawRect
sta DrawRect.top
lda TempWord
clc
adc DrawRect.bottom
bvs @useView
ldy #TERecord.ViewRect.bottom
cmp [RecordPtr],y
bmi @useAReg
@useView ldy #TERecord.ViewRect.bottom
lda [RecordPtr],y
@useAReg sta DrawRect.bottom
bra @skipClear
@clearDrawRect stz DrawRect.top
stz DrawRect.bottom
@skipClear jsr PushDrawRect
ldax TempLong
jsr ScrollByAmount
jsr PullDrawRect
@noClip PullLong TempLong
;---------------------------------------------------------------
fixTheBar jsr GetVertScrollBar ;is there a vertical scroll bar ? If not,
beq @done ;..then exit.
stax TempPtr
jsr DerefTempPtr
ldy #TERecord.ViewRect.bottom ;find the view size in scroll increments
lda [RecordPtr],y
sec
ldy #TERecord.ViewRect.top
sbc [RecordPtr],y
ldx #0
jsr DivideByScrollAmount
sta TempWord
lda TempLong ;clip TempLong to a word for accessing the
ldx TempLong+2 ;..scroll bar
beq @1
lda #$FFFF
@1 clc
adc TempWord
sta TempLong
ldy #CtrlRecord.viewSize ;are the scroll bar parameters changing ?
lda [TempPtr],y
cmp TempWord
bne @setIt
ldy #CtrlRecord.dataSize
lda [TempPtr],y
cmp TempLong
beq @done ;..nope, so done
@setIt PushZWord TempLong ;push the new data size
PushZWord TempWord ;push the new view size
jsr GetVertScrollBar
PushAX
_SetCtlParams
@done rts
;---------------------------------------------------------------
ENDP
****************************************************************
RecalcScrollBar PROCNAME Export
;---------------------------------------------------------------
jsr checkForNoScroll ;if we are not scrolling, then exit
;---------------------------------------------------------------
ldy #TERecord.TotalHeight ;find the new maximum value for the
jsr GetRecordLong ;..vertical scroll bar
clc
ldy #TERecord.ViewRect.top
adc [RecordPtr],y
bcc @1
inx
@1 sec
ldy #TERecord.ViewRect.bottom
sbc [RecordPtr],y
bcs @2
dex
@2 cpx #$8000
blt @notZero
lda #0
tax
bra @clipToMax
@notZero jsr DivideByScrollAmount
@clipToMax stax TempLong ;save the new maximum value in TempLong
ldy #TERecord.VertScrollMax ;..and put it in the record
jsr SetRecordLong
lda TempLong ;restore A-Reg (SetRecordLong killed it)
ldy #TERecord.VertScrollPos ;see if the old scroll position is greater
sec ;..that the new maximum.
sbc [RecordPtr],y
iny
iny
txa ;the high word of the maximum is still in
sbc [RecordPtr],y ;..the X-Reg
bpl @noClip
txa ;yes, the old position is greater than the
sta [RecordPtr],y ;..maximum, so set the new position
dey
dey
lda TempLong
sta [RecordPtr],y
@noClip
;---------------------------------------------------------------
fixTheBar jsr GetVertScrollBar ;is there a vertical scroll bar ? If not,
beq @noScrollBar ;..then exit.
ldy #TERecord.ViewRect.bottom ;find the view size in scroll increments
lda [RecordPtr],y
sec
ldy #TERecord.ViewRect.top
sbc [RecordPtr],y
ldx #0
jsr DivideByScrollAmount
sta TempWord
lda TempLong ;clip TempLong to a word for accessing the
ldx TempLong+2 ;..scroll bar
beq @1
lda #$FFFF
@1 clc
adc TempWord
pha ;push the new data size
PushZWord TempWord ;push the new view size
jsr GetVertScrollBar
PushAX
_SetCtlParams
ldy #TERecord.VertScrollPos ;set the new scroll bar value
lda [RecordPtr],y
pha
jsr GetVertScrollBar
PushAX
_SetCtlValue
@noScrollBar
;---------------------------------------------------------------
resetTheTop ldy #TERecord.VertScrollPos
lda [RecordPtr],y
ldx #0
jsr MultiplyByScrollAmount ;this is the top of the text box in
stax TempLong ;..pixels
stzl TextOffset
ldy #TERecord.LineSuper
jsr FindSuperInfo
dey
dey
;---------------------------------------------------------------
@loop sty TempWord
lda [TempPtr],y ;get the high word of the length and
bmi @deleted ;..check to see if the item has been
tax ;..deleted. If not, then save the high word
iny ;..in X-Reg
iny ;move to the line height field
lda TempLong ;subtract the line height from the pixel
sec ;..scroll position. If this number is
sbc [TempPtr],y ;..negative, we have found the line
sta TempLong
bcs @1
dec TempLong+2
bmi foundIt
@1
dey ;move back to the low word of the length
dey ;..and add the length to the current
dey ;..text offset
dey
lda [TempPtr],y
clc
adc TextOffset
sta TextOffset
txa
adc TextOffset+2
sta TextOffset+2
lda TempLong ;if there are no more pixels to go thru
ora TempLong+2 ;..we have found the line we are looking
beq foundZero ;..for
@deleted lda TempWord ;move to the next item
clc
adc #SuperItemSize
tay
cpy SuperMaxIndex
blt @loop
jsr MoveToNextHandle ;NOTE: we should never reach the end
ldy #SuperBlock.RecordSize+2 ;..here
bra @loop
;---------------------------------------------------------------
foundIt lda TempLong
clc
adc [TempPtr],y
foundZero ldy #TERecord.TopTextVPos
sta [RecordPtr],y
brl SetScreenTopOffset
;---------------------------------------------------------------
ENDP
****************************************************************
checkForNoScroll PROCNAME Entry
;---------------------------------------------------------------
ldy #TERecord.TextFlags+2
lda [RecordPtr],y
and #fNoScroll
beq @mustExecute
pla ;get rid of one return address, so we skip
@mustExecute rts ;..the main routine
;---------------------------------------------------------------
ENDP
****************************************************************
END