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
121 KiB
NASM

the TE control should handle scrolling automatically, along with insertion of
text, automatically scrolls the text. insertion must be handled quickly -- no
moving of the entire text array with every character. look into background
tasks to handle recalculating of line starts, etc. the first character
inserted my be slow; as long as all the rest are fast. For now redraw every-
thing after the inserted text. later optimize to only redraw if a line wraps
and to bit-blit text instead of redrawing it. Use offscreen drawing to make
it all look smooth. provide special speedups for special cases like: single
font, fixed-width font, no word wrap, single text rectangle. allow multiple
rectangles for the text, but must develop a new way of linking them to handle
wrapping. make EVERYTHING into a control; this should be completely automatic.
Must decide how to work scroll bars with muliple text rectangles. must figure
out some way of getting keystrokes when i'm a control.
50 milliseconds maximum per char. so can do 20 chars / sec
200 mils at the beginning of a selection
100 mils per line of scrolling
500 mils per cut, copy, paste
25 mils per idle (1/40) second
********** end of notes on GS TextEdit ********** */
print off
INCLUDE 'all.macros'
INCLUDE 'E16.EVENT'
print on
INCLUDE 'GlobalRecords'
INCLUDE 'GlobalVars'
INCLUDE 'MemoryImports'
string asis
****************************************************************
;
;
; super arrays are an array of up to 8192 elements each one of which
; is a handle to up to 8192 elements
;
;
****************************************************************
****************************************************************
setupSuperCache PROC ENTRY
PushLong SuperCacheHandle ;get a pointer to the block of items
jsr DerefHandle
stax SuperLocalPtr
ldy SuperCacheIndex ;and load the current index
rts
ENDP
****************************************************************
GetSuperOffset PROC EXPORT
lda SuperCacheHandle ;check to see if the cache handle is zero
ora SuperCacheHandle+2 ;..if it is, there is no cache
beq notInCache
cmp4 TextOffset,SuperCacheEndOffset ;check the current offset against the
bge notInCache ;..cache bounds
cmp4 TextOffset,SuperCacheOffset
blt notInCache
inCache MoveLong SuperCacheItem,SuperItem ;copy the cached item number
SubLong TextOffset,SuperCacheOffset,SuperOffsetLeft
jsr setupSuperCache ;setup the local pointer and index
brl localLoop
notInCache MoveLong TextOffset,SuperOffsetLeft ;setup the offset counter
stz4 SuperItem ;zero out the super item number
PushLong SuperHandle ;get a pointer to the array of handles
jsr DerefHandle
stax SuperMainPtr
mainLoop ldy #2
lda [SuperMainPtr],y
sta SuperCacheHandle+2
pha
lda [SuperMainPtr]
sta SuperCacheHandle
pha
ora SuperCacheHandle+2
beq notFound
jsr DerefHandle
stax SuperLocalPtr
ldy #2
lda [SuperLocalPtr],y
tax
lda [SuperLocalPtr]
cpx SuperOffsetLeft+2
blt skipLocal
bne doLocal
cmp SuperOffsetLeft
blt skipLocal
bne doLocal
skipLocal ldy #4
lda [SuperLocalPtr],y
clc
adc SuperItem
sta SuperItem
bcc @1
inc SuperItem+2
@1 lda SuperMainPtr
clc
adc #4
sta SuperMainPtr
bcc mainLoop
inc SuperMainPtr+2
bra mainLoop
doLocal clc
adc TextOffset
sta SuperCacheEndOffset
txa
adc TextOffset+2
sta SuperCacheEndOffset+2
SubLong SuperCacheEndOffset,SuperOffsetLeft,SuperCacheEndOffset
ldy #4
lda [SuperLocalPtr],y
clc
adc SuperItem
sta SuperCacheEndItem
lda SuperItem+2
adc #0
sta SuperCacheEndItem+2
ldy #6
localLoop lda [SuperLocalPtr],y
sta SuperLength
iny2
lda [SuperLocalPtr],y
sta SuperLength+2
cmp4 SuperLength,SuperOffsetLeft
bgt foundIt
SubLong SuperOffsetLeft,SuperLength,SuperOffsetLeft
inc4 SuperItem
iny4
bra localLoop
foundIt tya
dec A
dec A
sta SuperCacheIndex
iny2
lda [SuperLocalPtr],y
sta SuperData
SubLong SuperLength,SuperOffsetLeft,SuperLength
SubLong TextOffset,SuperOffsetLeft,SuperCacheOffset
MoveLong SuperItem,SuperCacheItem
clc
rts
notFound pla
pla
sec
rts
ENDP
****************************************************************
GetSuperItem PROC EXPORT
lda SuperCacheHandle
ora SuperCacheHandle+2
beq notInCache
cmp4 SuperItem,SuperCacheEndItem
bge notInCache
cmp4 SuperItem,SuperCacheItem
blt notInCache
inCache MoveLong SuperCacheOffset,TextOffset
SubLong SuperItem,SuperCacheItem,SuperItemsLeft
jsr setupSuperCache
brl localLoop
notInCache MoveLong SuperItem,SuperItemsLeft
stz4 TextOffset
PushLong SuperHandle
jsr DerefHandle
stax SuperMainPtr
mainLoop ldy #2
lda [SuperMainPtr],y
sta SuperCacheHandle+2
pha
lda [SuperMainPtr]
sta SuperCacheHandle
pha
ora SuperCacheHandle+2
beq notFound
jsr DerefHandle
stax SuperLocalPtr
ldy #4
lda [SuperLocalPtr],y
tax
lda SuperItemsLeft+2
bne skipLocal
cpx SuperItemsLeft
blt skipLocal
bne doLocal
skipLocal lda SuperItemsLeft
sec
sbc [SuperLocalPtr],y
sta SuperItemsLeft
lda SuperItemsLeft+2
sbc #0
sta SuperItemsLeft+2
ldy #2
lda [SuperLocalPtr]
clc
adc TextOffset
sta TextOffset
lda [SuperLocalPtr],y
adc TextOffset+2
sta TextOffset+2
lda SuperMainPtr
clc
adc #4
sta SuperMainPtr
bcc mainLoop
inc SuperMainPtr+2
bra mainLoop
doLocal txa
clc
adc SuperItem
sta SuperCacheEndItem
lda SuperItem+2
adc #0
sta SuperCacheEndItem+2
SubLong SuperCacheEndItem,SuperItemsLeft,SuperCacheEndItem
ldy #2
lda [SuperLocalPtr]
adc TextOffset
sta SuperCacheEndOffset
lda [SuperLocalPtr],y
adc TextOffset+2
sta SuperCacheEndOffset+2
ldy #6
lda SuperItemsLeft
ora SuperItemsLeft+2
beq foundIt
localLoop lda [SuperLocalPtr],y
sta SuperLength
clc
adc TextOffset
sta TextOffset
iny2
lda [SuperLocalPtr],y
sta SuperLength+2
adc TextOffset+2
sta TextOffset+2
iny4
dec SuperItemsLeft
bne localLoop
foundIt tya
dec A
dec A
sta SuperCacheIndex
iny2
lda [SuperLocalPtr],y
sta SuperData
MoveLong TextOffset,SuperCacheOffset
MoveLong SuperItem,SuperCacheItem
clc
rts
notFound pla
pla
sec
rts
ENDP
****************************************************************
SetSuperItem PROC EXPORT
lda SuperCacheHandle
ora SuperCacheHandle+2
beq notInCache
cmp4 SuperItem,SuperCacheEndItem
bge notInCache
cmp4 SuperItem,SuperCacheItem
blt notInCache
inCache SubLong SuperItem,SuperCacheItem,SuperItemsLeft
PushLong SuperCacheHandle ;get a pointer to the block of items
jsr DerefHandle
clc
adc SuperCacheIndex
sta SuperLocalPtr
stx SuperLocalPtr
bcc @1
inc SuperLocalPtr+2
@1 brl doLocal
notInCache MoveLong SuperItem,SuperItemsLeft
PushLong SuperHandle
jsr DerefHandle
stax SuperMainPtr
mainLoop ldy #2
lda [SuperMainPtr],y
pha
lda [SuperMainPtr]
pha
ora 3,s
beq notFound
jsr DerefHandle
stax SuperLocalPtr
ldy #4
lda [SuperLocalPtr],y
tax
lda SuperItemsLeft+2
bne skipLocal
cpx SuperItemsLeft
blt skipLocal
bne doLocal
skipLocal lda SuperItemsLeft
sec
sbc [SuperLocalPtr],y
sta SuperItemsLeft
lda SuperItemsLeft+2
sbc #0
sta SuperItemsLeft+2
lda SuperMainPtr
clc
adc #4
sta SuperMainPtr
bcc mainLoop
inc SuperMainPtr+2
bra mainLoop
doLocal asl SuperItemsLeft ;multiply the number of items by six
lda SuperItemsLeft
asl SuperItemsLeft
clc
adc SuperItemsLeft
clc
adc #6 ;skip the first 6 bytes in the handle
tay ;use as an index.
lda SuperLength
sta [SuperLocalPtr],y
iny
iny
lda SuperLength+2
sta [SuperLocalPtr],y
iny
iny
lda SuperData
sta [SuperLocalPtr],y
clc
rts
notFound pla
pla
sec
rts
ENDP
****************************************************************
InsertSuperItem PROC EXPORT
clc
rts
ENDP
****************************************************************
RemoveSuperItem PROC EXPORT
notInCache MoveLong SuperItem,SuperItemsLeft
PushLong SuperHandle
jsr DerefHandle
stax SuperMainPtr
mainLoop ldy #2
lda [SuperMainPtr],y
pha
lda [SuperMainPtr]
pha
ora 3,s
beq notFound
jsr DerefHandle
stax SuperLocalPtr
ldy #4
lda [SuperLocalPtr],y
tax
lda SuperItemsLeft+2
bne skipLocal
cpx SuperItemsLeft
blt skipLocal
bne doLocal
skipLocal lda SuperItemsLeft
sec
sbc [SuperLocalPtr],y
sta SuperItemsLeft
lda SuperItemsLeft+2
sbc #0
sta SuperItemsLeft+2
lda SuperMainPtr
clc
adc #4
sta SuperMainPtr
bcc mainLoop
inc SuperMainPtr+2
bra mainLoop
doLocal asl SuperItemsLeft ;multiply the number of items by six
lda SuperItemsLeft
asl SuperItemsLeft
clc
adc SuperItemsLeft
clc
adc #6 ;skip the first 6 bytes in the handle
clc
adc SuperLocalPtr
sta SuperLocalPtr
bcc @1
inc SuperLocalPtr+2
@1 nop
clc
rts
notFound pla
pla
sec
rts
ENDP
****************************************************************
END
GetSuperOffset: uses TextOffset and SuperHandle. searches the super array in SuperHandle for
the item at TextOffset. Sets the SuperItem, SuperLength, and SuperData values.
SuperLength will be the number of characters AFTER TextOffset that the data
pertains to. The SuperCache values will be used if SuperCacheHandle is non zero.
They will also be updated by this routine.
GetSuperItem: uses SuperItem and SuperHandle. Returns the SuperLength, SuperData, and
TextOffset values. The SuperCache values will be used and updated.
SetSuperItem: uses SuperHandle and SuperItem. Sets the length and data fields from SuperLength
and SuperData. The SuperCache values will be used and updated.
InsertSuperItem: uses SuperHandle and SuperItem. Inserts a new item AFTER SuperItem using
the SuperLength and SuperData values. The SuperCache values will be
used and updated.
RemoveSuperItem: uses SuperHandle and SuperItem. The item specified will be removed from the list.
The SuperCache values will be used and updated.
****************************************************************
OldDoKeystroke PROC EXPORT
IMPORT DoRightDelete
IMPORT DoLeftArrow
IMPORT DoDownArrow
IMPORT DoUpArrow
IMPORT DoCR
IMPORT DoRightArrow
IMPORT DoClear
IMPORT DoClearEOL
IMPORT DoDelete
IMPORT ScrollToSelection
IMPORT IsSelectionEmpty
IMPORT GetRecordLong
IMPORT IsItAWordBreak
IMPORT SimpleKey
IMPORT GetSelectionStart
IMPORT SetRecordLong
IMPORT AreWeWordWrapping
lda TheChar
casejmp $06,DoRightDelete ;Ctrl-F
casejmp $08,DoLeftArrow
casejmp $0A,DoDownArrow
casejmp $0B,DoUpArrow
casejmp $0D,DoCR
casejmp $15,DoRightArrow
casejmp $18,DoClear ;ctrl-X, clear
casejmp $19,DoClearEOL ;ctrl-Y
casejmp $7f,DoDelete ;Delete
normalchar PushWordSpace ;get the width of the character we
PushWord TheChar ;..inserted
_CharWidth
PullWord TheCharWidth
jsr ScrollToSelection ;scroll to the current selection.
jsr IsSelectionEmpty ;check to see if we have a selection
bcsl notEmpty
jsr AreWeWordWrapping
bcsl doSimple ;nope, so do simple case
jsr GetSelectionStart ;check to see if we are inserting into
ldy #TERecord.FirstWordEnd ;..the first word
jsr GetRecordLong
cmpl TextOffset
blt notInFirst
lda TheChar ;we are inserting into the first word
jsr IsItAWordBreak ;..so check for inserting a word break
bcc notWordBreak
ldax TextOffset ;set the first word end to the
ldy #TERecord.FirstWordEnd ;..current offset.
jsr SetRecordLong
; jsr MeasureTillOffset ;measure from the start of the line to
ldy #TERecord.FirstWordWidth ;..the current offset. Store the new width
sta [RecordPtr],y ;..in globals
bra checkPrevWrap
notWordBreak ldy #TERecord.FirstWordEnd ;increment the ending offset for the
jsr GetRecordLong ;..first word.
incl a
ldy #TERecord.FirstWordEnd ;increment the ending offset for the
jsr SetRecordLong ;re-store the value in globals
ldy #TERecord.FirstWordWidth ;add the width of the inserted character
lda [RecordPtr],y ;..to the first word width
clc ;..and re-store this in globals
adc TheCharWidth
sta [RecordPtr],y
lda WasSelectionEmpty ;if the selection was empty the width of
cmp #TRUE ;the first word INCREASED, so we don't
beq notInFirst ;need to check for wrap to the prev line
checkPrevWrap ldy #TERecord.FirstWordWidth ;get the width of the first word into
lda [RecordPtr],y ;..TempWord
sta TempWord
ldy #TERecord.PrevLineLeft ;get the number of pixels left on the
lda [RecordPtr],y ;..previous line.
cmp TempWord ;If pixels left >= word width we must
bge doComplex ;..word wrap, so call doComplex
notInFirst ldy #TERecord.LineWidth ;add the width of the character inserted
lda [RecordPtr],y ;..to the line width and re-store this
clc ;..value in globals
adc TheCharWidth
sta TempWord
sta [RecordPtr],y
ldy #TERecord.NextFirstWordWidth ;get the width of the first word on the
lda [RecordPtr],y ;..next line and check to see if it will
clc ;..fit on this line (this is necessary
adc TempWord ;..there was a non-empty selection)
sta TempWord+2 ;if this word will fit on this line, we
ldy #TERecord.WrapWidth ;..need to word wrap so call doComplex
lda [RecordPtr],y
cmp TempWord+2
bge doComplex
cmp TempWord
blt doComplex
doSimple jmp SimpleKey
notEmpty nop ;do some checks later
brk $26
doComplex nop
brk $25
rts
ENDP
****************************************************************
****************************************************************
DoCR PROC EXPORT
clc
rts
oldHeight equ 0
jsr Save0_4
jsr UnhilightSelection ;hide the old cursor
jsr ScrollToSelection ;scroll to the current selection.
jsr IsSelectionEmpty ;check to see if we have a selection
bcsl doComplex
jsr GetSelectionStart
jsr FindLineInfo ;get the info for the current line
lda IsLineEndHard ;is this line ended by a CR or by end
cmp #FALSE ;..of text ? If it is not then we need
beql doComplex ;..to word wrap, so go do that.
mov LineHeight,oldHeight ;save the old line height and ascent.
jsr InsertChar ;insert the CR into the text.
jsr GetSelectionStart
incl TextOffset
jsr SetSelectionStart
jsr SetSelectionEnd
jsr AddLineBreak ;add a line break at the current TextOffset.
jsr GetSelectionStart
decl TextOffset
jsr FindLineInfo
mov LineHeight,TextHeight ;the first line new height is in TextHeight
incl TextOffset
jsr FindLineInfo ;the second line new height is in LineHeight
jsr GetViewRect
lda TextVPos ;this is the top of the line rect
clc
adc oldHeight ;this is the original line height
sta TempRect.top
lda LineHeight
clc
adc TextHeight
sec
sbc oldHeight
tax
PushZPtr TempRect
PushWord #0
phx
PushLong #0
_ScrollRect
jsr GetSelectionRect ;erase the rest of this line from the
ldy #TERecord.ViewRect.right ;..selection on.
jsr GetRecordWord
sta TempRect.right
lda TempRect.top
clc
adc TextHeight
sta TempRect.bottom
PushZPtr TempRect
_EraseRect
jsr GetSelectionStart
jsr OffsetToPoint
PushWord TextHPos
PushWord TextVPos
_MoveTo
jsr GetTextFormat ;get the format values
drawloop PushLong TextPtr
PushWord TextCount
_DrawText
lda TextCount
clc
adc TextOffset
sta TextOffset
bcc @1
inc TextOffset+2
@1 lda WhatStoppedFormat
cmp #lineBreak
beq done
cmp #endOfText
beq done
jsr GetTextFormat
bra drawloop
done jsr HilightSelection ;show the new cursor
jmp Restore0_4
doComplex brk $51
ENDP
****************************************************************
****************************************************************
* remove all the items from TextOffset to EndOffset
****************************************************************
RemoveSuperItems PROC EXPORT
IMPORT FindSuperInfo
PushAX ;save the super handle
jsr FindSuperInfo ;find the right spot in the super array
PushLong TextOffset ;save the starting TextOffset
addl SuperStart,SuperLength,TextOffset
cmpl TextOffset,EndOffset
bgtl nothingToDo
mov SuperLocalIndex,DestPtr ;save the local index
stzl SuperItemNumber ;use this as a counter
removeLoop lda SuperLocalIndex ;move the local index to the next
clc ;..position
adc #SuperItemSize
sta SuperLocalIndex
tay
lda [TempPtr],y ;add the new length to the original
pha ;..length. Also save the new length
clc
adc SuperLength
sta SuperLength
iny
iny
lda [TempPtr],y ;add the high word
tax
adc SuperLength+2
sta SuperLength+2
bcsl nextBlock ;if we wrapped around, we are in the
and SuperLength ;..next block
cmp #$FFFF ;if $FFFF FFFF then also in the next block
beql nextBlock
iny ;get the new height
iny
lda [TempPtr],y ;add to the original height
clc
adc LineHeight
sta LineHeight
ldy #BlockRecord.count ;update the line count field
lda [TempPtr],y
dec a
sta [TempPtr],y
incl SuperItemNumber ;increment the number of items we removed
pla ;restore the low word of the new length
clc ;move TextOffset to the next item
adc TextOffset
sta TextOffset
txa ;the high word is still in X
adc TextOffset+2
sta TextOffset+2
cmp EndOffset+2
blt removeLoop
bne done
lda TextOffset
cmp EndOffset
ble removeLoop
done ldy DestPtr ;get our original index
lda SuperLength ;copy the length into the original line.
sta [TempPtr],y
iny
iny
lda SuperLength+2
sta [TempPtr],y
iny
iny
lda LineHeight
sta [TempPtr],y
lda SuperLocalIndex
clc
adc #SuperItemSize
sta MoveLength
adc TempPtr
sta SourcePtr
lda TempPtr+2
adc #0
sta SourcePtr+2
lda DestPtr
adc #SuperItemSize ;carry is already clear
sta SuperLocalIndex
adc TempPtr
sta DestPtr
lda TempPtr+2
adc #0
sta DestPtr+2
ldy SuperMainIndex ;get the local handle into TempPtr
lda [MainSuperPtr],y
tax
iny
iny
lda [MainSuperPtr],y
pha ;one copy for set handle size
phx
pha ;..and one for get handle size
phx
jsr GetHandleSize
pha ;save the size (one word)
sec
sbc MoveLength
sta MoveLength
stz MoveLength+2
jsr BlockMove
pla
clc
adc DestPtr
sec
sbc SourcePtr
ldx #0
jsr SetHandleSize
nothingToDo PullLong TextOffset
PullAX ;restore the super handle
jmp FindSuperInfo ;re-position things to the new item.
nextBlock brk $33
ENDP
****************************************************************
; lda theOutputHandle,s
; sta OutputHandle
; lda theOutputHandle+2,s
; sta OutputHandle+2
; PushZLong OutputHandle ;resize the output handle
; ldy #TERecord.textLength
; jsr GetRecordLong
; jsr SetHandleSize
; bcs sizeError
; ldy #TERecord.textLength ;check for zero length
; lda [RecordPtr],y
; iny
; iny
; ora [RecordPtr],y
; beq skipCopy
; PushZLong OutputHandle ;deref the output handle
; jsr LockHandle
; stax DestPtr ;save the pointer in dest pointer
; jsr GetBlockListPtr
; ldy #BlockListRecord.firstItem
;copyLoop lda [MemoryPtr],y
; pha ;save the low word of block handle
; iny
; iny
; lda [MemoryPtr],y
; tax ;the high word goes in X
; and 1,s ;check for end of list
; cmp #$FFFF
; beq copyDone
; iny
; iny
; lda [MemoryPtr],y ;save the block length in move length
; sta MoveLength
; iny
; iny
; lda [MemoryPtr],y
; sta MoveLength+2
; pla
; phy ;save our current index
; jsr DerefAX ;get the source pointer
; stax SourcePtr
; jsr BlockMove ;move the data
; addl DestPtr,MoveLength,DestPtr ;bump the dest pointer forward.
; pla ;get back our index
; clc
; adc #BlockListItemSize-6
; tay
; bra copyLoop
;copyDone pla ;cleanup stack
; PushZLong OutputHandle
; jsr UnlockHandle
****************************************************************
* remove all the items from TextOffset to EndOffset
****************************************************************
RemoveSuperItems PROC EXPORT
IMPORT FindSuperInfo
PushAX ;save the super handle
jsr FindSuperInfo ;find the right spot in the super array
stzl SuperItemNumber ;use this as a counter
PushZLong TextOffset ;save the starting TextOffset
addl SuperStart,SuperLength,TextOffset
cmpl TextOffset,EndOffset
bgtl nothingToDo
mov SuperLocalIndex,DestPtr ;save the local index
removeLoop lda SuperLocalIndex ;move the local index to the next
clc ;..position
adc #SuperItemSize
sta SuperLocalIndex
tay
lda [TempPtr],y ;add the new length to the original
pha ;..length. Also save the new length
clc
adc SuperLength
sta SuperLength
iny
iny
lda [TempPtr],y ;add the high word
tax
adc SuperLength+2
sta SuperLength+2
bcsl nextBlock ;if we wrapped around, we are in the
and SuperLength ;..next block
cmp #$FFFF ;if $FFFF FFFF then also in the next block
beql nextBlock
iny ;get the new height
iny
lda [TempPtr],y ;add to the original height
clc
adc LineHeight
sta LineHeight
ldy #SuperBlockRecord.count ;update the line count field
lda [TempPtr],y
dec a
sta [TempPtr],y
incl SuperItemNumber ;increment the number of items we removed
pla ;restore the low word of the new length
clc ;move TextOffset to the next item
adc TextOffset
sta TextOffset
txa ;the high word is still in X
adc TextOffset+2
sta TextOffset+2
cmp EndOffset+2
blt removeLoop
bne done
lda TextOffset
cmp EndOffset
blt removeLoop
done ldy DestPtr ;get our original index
cpy SuperLocalIndex
beq nothingToDo
lda SuperLength ;copy the length into the original line.
sta [TempPtr],y
iny
iny
lda SuperLength+2
sta [TempPtr],y
iny
iny
lda LineHeight
sta [TempPtr],y
lda SuperLocalIndex
clc
adc #SuperItemSize
sta MoveLength
adc TempPtr
sta SourcePtr
lda TempPtr+2
adc #0
sta SourcePtr+2
lda DestPtr
adc #SuperItemSize ;carry is already clear
sta SuperLocalIndex
adc TempPtr
sta DestPtr
lda TempPtr+2
adc #0
sta DestPtr+2
ldy SuperMainIndex ;get the local handle into TempPtr
lda [MainSuperPtr],y
tax
iny
iny
lda [MainSuperPtr],y
pha ;one copy for set handle size
phx
pha ;..and one for get handle size
phx
jsr GetHandleSize
pha ;save the size (one word)
sec
sbc MoveLength
sta MoveLength
stz MoveLength+2
jsr BlockMove
pla
clc
adc DestPtr
sec
sbc SourcePtr
ldx #0
jsr SetHandleSize
nothingToDo PullLong TextOffset
PullAX ;restore the super handle
ldy SuperItemNumber+2
phy
ldy SuperItemNumber
phy
jsr FindSuperInfo ;re-position things to the new item.
PullAX ;return how many lines we removed
rts
nextBlock pla ;pull off trash
incl SuperLength ;adjust for the $FFFF FFFF length
lda SuperLocalIndex
sec
sbc #SuperItemSize
sta SuperLocalIndex
; cmp DestPtr
; beq skipCrunch
; brk $33 ;crunch it
movl TempPtr,TempLong
lda SuperMainIndex
clc
adc #4
sta SuperMainIndex
tay
lda [MainSuperPtr],y
sta TempPtr
iny
iny
lda [MainSuperPtr],y
sta TempPtr+2
and TempPtr
cmp #$FFFF
beq atEnd
brk $34
atEnd movl TempLong,TempPtr
lda SuperMainIndex
sec
sbc #4
sta SuperMainIndex
brl done
ENDP
****************************************************************
* This routine takes TextOffset as an input. TextOffset is an offset
* to the first line that changed. This line and all subsequent lines
* must be reformatted. This routine will also redraw the lines that
* it needs to. It will also scroll lines, by keeping track
* of the old TextVPos and the new TextVPos.
****************************************************************
RewrapUntilScreenEnd PROC EXPORT
ldy #TERecord.TextLength ;if there is no text, we can skip this
jsr GetRecordLong ;..entire routine - (there are no lines)
stx TempWord
ora TempWord
beql justRedraw
PushZLong TextOffset ;save the old text offset
jsr FindLineInfo ;start at the beginning of this line
lda SuperStart ;copy super start into text offset and
sta TextOffset ;..set end offset to be at the end of
clc ;..this line.
adc SuperLength
sta EndOffset
lda SuperStart+2
sta TextOffset+2
adc SuperLength+2
sta EndOffset+2
mov LineHeight,oldHeight
jsr OffsetToPoint ;find the TextVPos
lda TextVPos
clc
adc LineHeight
sta OldNextVPos ;this is the old VPos of the next line
lineLoop jsr FindNextLineBreak ;carry set means there was no line break
bcs done ;..found.
cmpl TextOffset,EndOffset
bge done
jsr GetLineSuperHandle ;get the line super pointers -- note
jsr SetupSuperPtrs ;..we must already be at the right spot
lda [TempPtr],y ;is the new length != the old length ?
cmp SuperLength ;then, we need to add a new item
bne addItem
iny
iny
lda [TempPtr],y
cmp SuperLength+2
beq checkForThru ;exactly equal means we are done.
addItem lda #$FFFF
sta addFlag
jsr GetLineSuperHandle
jsr InsertSuperItem ;insert a line at the current offset
ldy #TERecord.NumberOfLines ;increment the number of lines
jsr IncRecordLong
decl TextOffset ;move to the previous line
jsr CalculateLineHeight ;get the height
lda TextVPos ;move the new top of line down by the
clc ;..height of the previous line
adc LineHeight
sta TextVPos
incl TextOffset ;move to the new line
jsr CalculateLineHeight ;get the new height
brl lineLoop ;go back for another line
checkForThru ldy #TERecord.TextLength ;are we at the very end ?
jsr GetRecordLong
cmpl TextOffset
bne thruWrapping
decl TextOffset
jsr FindBlockInfo
jsr BlockToTextPtr
incl TextOffset
lda [TextPtr] ;was the last character a CR ?
and #$00FF
cmp #$0D
bne thruWrapping ;..nope
jsr FindLineInfo ;we are, so find the line info
cmpl SuperStart,TextOffset ;if there is alreay a new line, then
bne addItem ;..quit. otherwise, add the line
thruWrapping decl TextOffset
jsr CalculateLineHeight ;recal the line height for this line
incl TextOffset
jsr GetViewRect ;setup the scrolling rectangle
lda OldNextVPos ;start at the old next position
ldx addFlag
bne skipAdjust
sec
sbc oldHeight
clc
adc LineHeight
skipAdjust sta TempRect.top
lda TextVPos ;get the new top position of the line
clc ;..that didn't change
adc LineHeight
sta TextVPos
sec
sbc OldNextVPos
sta OldNextVPos ;save the amount to scroll
beq skipScroll
PushZPtr TempRect
PushWord #0
PushZWord OldNextVPos
PushLong #0
_ScrollRect
lda OldNextVPos
bpl skipScroll
; must redraw the bottom here
skipScroll movl TextOffset,SavedOffset
lda 1,s
sta TextOffset
lda 3,s
sta TextOffset+2
drawLoop jsr RedrawLine
cmpl TextOffset,SavedOffset
blt drawLoop
PullLong TextOffset ;restore text offset
allDone jmp Restore0_4
justRedraw jsr RedrawLine
bra allDone
ENDP
PROC
doSimple
jsr InsertChar ;put the character into the text block
jsr GetSelectionStart ;get the selection start into TextOffset
jsr GetJust
cmp #leftJust
bnel notLeftJust
jsr UnhilightSelection ;remove the selection hilighting
jsr CaretToPoint
lda TextHPos
pha ;save the old horizontal pos in TempRect
clc
adc TheCharWidth
sta TextHPos
jsr PointToCaret ;this kills TempRect
ldy #TERecord.ViewRect.right ;set the right side of the rectangle
lda [RecordPtr],y
sta TempRect.right
lda 1,s
sta TempRect.left
lda TextVPos
clc
adc LineAscent
pha
_MoveTo
jsr GetTextFormat ;get the format values
lda WhatStoppedFormat
cmp #lineBreak ;check to see if there are several styles
beq drawloop ;..in this line. If there are we want to
cmp #endOfText ;..erase the line
beq drawloop
jsr EraseTempRect
drawloop PushZLong TextPtr
PushZWord TextCount
_DrawText
lda TextCount
clc
adc TextOffset
sta TextOffset
bcc @1
inc TextOffset+2
@1 lda WhatStoppedFormat
cmp #lineBreak
beq done
cmp #endOfText
beq done
jsr GetTextFormat
bra drawloop
done lda WasSelectionEmpty
cmp #TRUE
beq allDone
PushZPtr TempLong
_GetPen
mov TempLong+2,TempRect.left
jsr EraseTempRect
allDone jsr GetSelectionStart
incl TextOffset
jsr SetSelectionStart
jsr SetSelectionEnd
jsr HilightSelection
clc
rts
notLeftJust brk $49
ENDP
****************************************************************
* remove all the line starts between TextOffset & EndOffset
* destroys TempPtr, TempWord, & TempLong
****************************************************************
RemoveLineStarts PROC EXPORT
ItemsRemoved equ SuperItemNumber
MaxLength equ EndOffset
jsr GetLineSuperHandle ;find the starting line in the super
jsr FindSuperInfo ;array.
lda SuperStart ;do a quick check to see if we are
clc ;..removing items or not. If not then
adc SuperLength ;..quickly exit.
tax
lda SuperStart+2
adc SuperLength+2
cmp EndOffset+2
blt mustRemoveItems
cpx EndOffset
bgtl nothingToDo
mustRemoveItems ldy SuperMainIndex ;save the original local handle
lda [MainSuperPtr],y
sta SuperLocalHandle
iny
iny
lda [MainSuperPtr],y
sta SuperLocalHandle+2
subl EndOffset,SuperStart,MaxLength ;we stop when SuperLength reaches MaxLength
stzl ItemsRemoved ;use this as an item counter
stzl SuperLength ;zero out SuperLength for the loop and
stz LineHeight ;..the same with line height
ldy SuperLocalIndex ;start at the current index
itemStart sty DestPtr ;save the starting index
itemLoop lda [TempPtr],y ;get the length of the current item
sta TempWord ;save it temporarily
clc ;X, A will contain the old super length
adc SuperLength ;..plus the length of the new item
tax ;..X is low, A is High
iny
iny
lda [TempPtr],y ;but first check to see if we are at
and TempWord ;..the end of a block ($FFFF FFFF)
cmp #$FFFF
beql nextBlock ;yes, goto next block
lda [TempPtr],y ;add the high word of the lengths and
clc ;..compare against the maximum length
adc SuperLength+2
cmp MaxLength+2
blt itemContinue
bne removeItems
cpx MaxLength
bge removeItems
itemContinue stx SuperLength+2 ;store the new length
sta SuperLength
iny
iny
tya
clc
adc #SuperItemSize-4
pha ;save on the stack
incl ItemsRemoved
ldy #SuperBlockRecord.count ;fix the block count field.
lda [TempPtr],y
dec a
sta [TempPtr],y
ply ;restore our index
bra itemLoop
removeItems bne skipLastItem ;check to see if we should remove the
tya ;..last item
clc
adc #SuperItemSize
pha
incl ItemsRemoved ;remove one more item.
ldy #SuperBlockRecord.count ;fix the block count field.
lda [TempPtr],y
dec a
sta [TempPtr],y
ply ;restore our index
skipLastItem dey ;adjust Y back to beginning of item
dey
sty SourcePtr
cpy DestPtr
beq skipCrunch ;is there anything to do ?
ldy SuperMainIndex ;get the current local handle
lda [MainSuperPtr],y
pha
iny
iny
lda [MainSuperPtr],y
tax
pla
jsr crunchIt ;crunch it.
skipCrunch PushZLong SuperLocalHandle ;dereference the orginal handle
jsr DerefHandle
stax TempPtr
ldy SuperLocalIndex
lda SuperLength
sta [TempPtr],y
iny
iny
lda SuperLength+2
sta [TempPtr],y
iny
iny
lda LineHeight
sta [TempPtr],y
ldy #TERecord.NumberOfLines ;adjust the number of lines in the record
lda [RecordPtr],y
sec
sbc ItemsRemoved
sta [RecordPtr],y
iny
iny
lda [RecordPtr],y
sbc ItemsRemoved+2
sta [RecordPtr],y
nothingToDo rts ;go back to caller
nextBlock lda #$FFFF ;on next block, mark line height overflow
sta LineHeight
lda SuperLocalIndex ;move just past the starting line
clc
adc #SuperItemSize
tay
jsr TerminateTempPtr ;terminate our original block
iny
iny
tya
ldx #0
PushZLong SuperLocalHandle ;resize the original handle
jsr SetHandleSize
lda SuperMainIndex ;save the destination index for the
clc ;..crunch
adc #4
sta DestPtr
blockLoop lda SuperMainIndex ;move the main index to the next handle
clc
adc #4
sta SuperMainIndex
tay
lda [MainSuperPtr],y ;save the local handle in tempPtr
sta TempPtr
iny
iny
lda [MainSuperPtr],y
sta TempPtr+2
and TempPtr
cmp #$FFFF
beq atEnd
PushZLong TempPtr ;save the local handle
jsr DerefTempPtr
ldy #SuperBlockRecord.length
lda [TempPtr],y
clc
adc SuperLength
tax
iny
iny
lda [TempPtr],y
adc SuperLength+2
cmp MaxLength+2
blt blockContinue
bne removeBlocks
cpx MaxLength
bge removeBlocks
blockContinue stx SuperLength
sta SuperLength+2
ldy #SuperBlockRecord.count
lda [TempPtr],y
clc
adc ItemsRemoved
sta ItemsRemoved
bcc @1
inc ItemsRemoved+2
@1 PullAX
jsr KillHandle ;kill the handle on the stack
bra blockLoop
atEnd jsr GetLineSuperHandle ;get the main line super handle
PushAX ;put it on the stack
ldy DestPtr
lda #$FFFF
sta [MainSuperPtr],y
iny
iny
sta [MainSuperPtr],y
iny
iny
ldx #0 ;high word is always zero
tya ;this is the low word
jsr SetHandleSize
brl skipCrunch
removeBlocks bne skipLast ;if equal, we want to remove this block too
PullAX
jsr KillHandle ;kill the last handle
stzl TempPtr ;set our last flag
lda SuperMainIndex ;saves bytes
bra crunchMain
skipLast PullLong TempPtr ;pull off the handle into temp pointer
lda SuperMainIndex ;move the index back
sec
sbc #4
crunchMain sta SourcePtr
jsr GetLineSuperHandle ;get the main line super handle
jsr crunchIt
lda TempPtr ;are we all through ?
ora TempPtr+2
beq allDone
jsr DerefTempPtr ;get the local pointer
ldy #SuperBlockRecord.firstItem ;start at the first item and go back to
brl itemStart ;..the item loop
allDone rts
crunchIt PushAX ;(handle comes in in A,X) - GetHandleSize
PushAX ;one copy for DerefHandle
PushAX ;one copy for DerefHandle
PushAX ;one copy for SetHandleSize
jsr GetHandleSize
sec
sbc SourcePtr
sta MoveLength ;this is the length to move
stz MoveLength
clc
adc DestPtr ;calculate the new size for the handle
pha ;..and save it on the stack
jsr DerefHandle ;add the starting pointer to the source
clc ;..index
adc SourcePtr
sta SourcePtr
bcc @1
inx
@1 stx SourcePtr+2
jsr DerefHandle ;add the starting pointer to the dest
clc ;..index
adc DestPtr
sta DestPtr
bcc @2
inx
@2 stx DestPtr+2
jsr BlockMove ;move the data
pla ;recover the new size and set the size of
ldx #0 ;..the handle
jsr SetHandleSize
rts
ENDP
****************************************************************
CalculateLineHeight PROC EXPORT
PushZLong EndOffset ;save the original ending offset
PushZLong TextOffset ;save the original text offset
jsr FindLineInfo
stz LineHeight
stz LineAscent
lda SuperStart
sta TextOffset
clc
adc SuperLength
sta EndOffset
lda SuperStart+2
sta TextOffset+2
adc SuperLength+2
sta EndOffset+2
heightLoop jsr FindStyleInfo ;find the new style information
lda SuperData ;see, if there is a new style item
cmp TextStyleItem
beq skipSetStyle ;nope = skip this
sta TextStyleItem ;yes, so setup the values
jsr InstallStyleItem
skipSetStyle lda TextHeight
cmp LineHeight
blt @1
sta LineHeight
@1 lda TextAscent
cmp LineAscent
blt @2
sta LineAscent
@2 addl SuperStart,SuperLength,TextOffset
cmpl TextOffset,EndOffset
blt heightLoop
mov LineHeight,SuperData
mov LineAscent,SuperData+2
jsr GetLineSuperHandle
jsr SetSuperData
PullLong TextOffset ;restore the original text offset
PullLong EndOffset ;restore the original ending offset
rts
ENDP
****************************************************************
* This routine takes TextOffset as an input. TextOffset is an offset
* to the first line that changed. This line and all subsequent lines
* must be reformatted. This routine will also redraw the lines that
* it needs to. It will also scroll lines, by keeping track
* of the old TextVPos and the new TextVPos.
****************************************************************
RewrapLines PROC EXPORT
addFlag equ 0
oldHeight equ 2
jsr Save0_4
stz addFlag ;this is for scrolling adjustment
ldy #TERecord.TextLength ;if there is no text, we can skip this
jsr GetRecordLong ;..entire routine - (there are no lines)
stx TempWord
ora TempWord
beql justRedraw
jsr AreWeWordWrapping
bcc simple ;nope
complex brk $4A ;needs more work.
simple PushZLong TextOffset ;save the starting text offset
jsr FindLineInfo ;move the offset to the beginning of the
movl SuperStart,TextOffset ;..current line
mov LineHeight,oldHeight
jsr OffsetToPoint ;find the TextVPos
lda TextVPos
clc
adc LineHeight
sta OldNextVPos ;this is the old VPos of the next line
blockLoopStart stzl SuperLength ;zero out the length field
blockLoop jsr FindBlockInfo ;get the text pointer
jsr BlockToTextPtr
lda BlockCount ;are we done ?
beql thruWrapping
ldy #0 ;search for a CR.
shortm
findCRLoop lda [TextPtr],y
cmp #$0D
beq foundCR
iny
cpy BlockCount
blt findCRLoop
longm
tya ;move the text offset forward by block
clc ;..count
adc TextOffset ;(Y is the block count)
sta TextOffset
bcc @1
inc TextOffset+2
@1 tya ;add block count to the new line length
clc ;(Y is the block count)
adc SuperLength
sta SuperLength
bcc @2
inc SuperLength+2
@2 ldy #TERecord.TextLength ;are we at the end of the text ?
jsr GetRecordLong ;..nope so go back to the block loop
cmp TextOffset
bne blockLoop
cpx TextOffset+2
bne blockLoop
brl checkLine ;we are done if we are at the end
foundCR longm ;back to long mode
tya ;where were we at ?
sec ;skip over the CR
adc TextOffset ;move the text offset to the new spot.
sta TextOffset
bcc @1
inc TextOffset+2
@1 tya ;add to the length.
sec
adc SuperLength
sta SuperLength
bcc checkLine
inc SuperLength+2
checkLine jsr GetLineSuperHandle ;get the line super pointers -- note
jsr SetupSuperPtrs ;..we must already be at the right spot
lda [TempPtr],y ;is the new length != the old length ?
cmp SuperLength ;then, we need to add a new item
bne addItem
iny
iny
lda [TempPtr],y
cmp SuperLength+2
beq checkForThru ;exactly equal means we are done.
addItem lda #$FFFF
sta addFlag
jsr GetLineSuperHandle
jsr InsertSuperItem ;insert a line at the current offset
ldy #TERecord.NumberOfLines ;increment the number of lines
jsr IncRecordLong
decl TextOffset ;move to the previous line
jsr CalculateLineHeight ;get the height
lda TextVPos ;move the new top of line down by the
clc ;..height of the previous line
adc LineHeight
sta TextVPos
incl TextOffset ;move to the new line
jsr CalculateLineHeight ;get the new height
brl blockLoopStart ;go back for another line
checkForThru ldy #TERecord.TextLength ;are we at the very end ?
jsr GetRecordLong
cmpl TextOffset
bne thruWrapping
decl TextOffset
jsr FindBlockInfo
jsr BlockToTextPtr
incl TextOffset
lda [TextPtr] ;was the last character a CR ?
and #$00FF
cmp #$0D
bne thruWrapping ;..nope
jsr FindLineInfo ;we are, so find the line info
cmpl SuperStart,TextOffset ;if there is alreay a new line, then
bne addItem ;..quit. otherwise, add the line
thruWrapping decl TextOffset
jsr CalculateLineHeight ;recal the line height for this line
incl TextOffset
jsr GetViewRect ;setup the scrolling rectangle
lda OldNextVPos ;start at the old next position
ldx addFlag
bne skipAdjust
sec
sbc oldHeight
clc
adc LineHeight
skipAdjust sta TempRect.top
lda TextVPos ;get the new top position of the line
clc ;..that didn't change
adc LineHeight
sta TextVPos
sec
sbc OldNextVPos
sta OldNextVPos ;save the amount to scroll
beq skipScroll
PushZPtr TempRect
PushWord #0
PushZWord OldNextVPos
PushLong #0
_ScrollRect
lda OldNextVPos
bpl skipScroll
; must redraw the bottom here
skipScroll movl TextOffset,SavedOffset
lda 1,s
sta TextOffset
lda 3,s
sta TextOffset+2
drawLoop jsr RedrawLine
cmpl TextOffset,SavedOffset
blt drawLoop
PullLong TextOffset ;restore text offset
allDone jmp Restore0_4
justRedraw jsr RedrawLine
bra allDone
ENDP
****************************************************************
INCLUDE 'GlobalIncludes'
****************************************************************
DebugPrintMain PROC EXPORT
phb
phk
plb
jsr SetupDebugPrint
PushWord #10
PushWord #20
_MoveTo
PushWord Value1
PushLong #tempStr
PushWord #5
PushWord #1
_Int2Dec
PushLong #tempStr
_DrawCString
PushWord #110
PushWord #20
_MoveTo
PushWord Value2
PushLong #tempStr
PushWord #5
PushWord #1
_Int2Dec
PushLong #tempStr
_DrawCString
PushWord #210
PushWord #20
_MoveTo
PushWord Value3
PushLong #tempStr
PushWord #5
PushWord #1
_Int2Dec
PushLong #tempStr
_DrawCString
PushWord #310
PushWord #20
_MoveTo
PushWord Value4
PushLong #tempStr
PushWord #5
PushWord #1
_Int2Dec
PushLong #tempStr
_DrawCString
jsr RestoreDebugPrint
plb
rts
EXPORT Value1,Value2,Value3,Value4
Value1 ds.w 1
Value2 ds.w 1
Value3 ds.w 1
Value4 ds.w 1
tempStr ds.b 5
dc.b ' ',0
ENDP
****************************************************************
DebugPrintDefProc PROC EXPORT
DefineStack ;these are our direct page variables
OrigB byte ;..for the defproc
OrigD word
RTL block 3
theControlHandle long
ctrlParam long
ctrlMessage word
result long
phb
phk
plb
jsr SetupDebugPrint
inc debugCount
PushWord #100
PushWord #10
_MoveTo
PushLong #mess1
_DrawCString
lda ctrlMessage
jsr DrawHexWord
PushLong #mess2
_DrawCString
ldax ctrlParam
jsr DrawHexLong
PushLong #mess3
_DrawCString
ldax theControlHandle
jsr DrawHexLong
PushLong #mess4
_DrawCString
PushWord debugCount
PushLong #tempStr
PushWord #4
PushWord #0 ;not signed
_Int2Dec
PushLong #tempStr
_DrawCString
lda ctrlMessage
cmp #0
bra done
loop PushWordSpace ;pause for a key
PushWord #$000A
PushLong #extraRecord
_GetNextEvent
pla
beq loop
done jsr RestoreDebugPrint
plb
rts
mess1 dc.b 'Message = $',0
mess2 dc.b ', Parameter = $',0
mess3 dc.b ', Handle = $',0
mess4 dc.b ', ',0
extraRecord ds.b 32
debugCount dc.w 0
tempStr ds.b 4
dc.b 0
ENDP
****************************************************************
SetupDebugPrint PROC EXPORT
EXPORT SetDebugPort
EXPORT RestoreDebugPrint
;---------------------------------------------------------------
PullWord returnAddr
PushLongSpace ;save the old port
_GetPort
PushLong DebugPort
_SetPort
PushLongSpace
_GetVisHandle ;leave it on the stack
PushLongSpace
_NewRgn
lda 3,s
tax
lda 1,s
PushAX ;save three total copies on the stack
PushAX
PushWord #-2000
PushWord #-2000
PushWord #2000
PushWord #2000
_SetRectRgn ;use first copy
_SetVisHandle ;use second copy
PushLong #clearRect
_EraseRect
PushWord returnAddr
rts
;---------------------------------------------------------------
SetDebugPort
phb
phk
plb
stax DebugPort
plb
rts
;---------------------------------------------------------------
RestoreDebugPrint
PullWord returnAddr
_DisposeRgn ;dispose our clipping region
_SetVisHandle
_SetPort ;restore the port
PushWord returnAddr
rts
;---------------------------------------------------------------
returnAddr ds.w 1
clearRect dc.w 0,0,28,640
DebugPort ds.l 1
ENDP
****************************************************************
* the value to be draw comes in in A
****************************************************************
DrawHexWord PROC EXPORT
phb ;save the data bank
phk ;set it to ours
plb
PushLongSpace
pha
_HexIt
PullLong tempStr
PushLong #tempStr
_DrawCString
plb ;restore the data bank
rts
tempStr ds.b 4
dc.b 0
ENDP
****************************************************************
* the value to be draw comes in in A and X
****************************************************************
DrawHexLong PROC EXPORT
phb ;save the data bank
phk ;set it to ours
plb
PushLongSpace ;save low word for later
pha
PushLongSpace ;do high word first.
phx
_HexIt
PullLong tempStr
PushLong #tempStr
_DrawCString
_HexIt ;now do the low word
PullLong tempStr
PushLong #tempStr
_DrawCString
plb ;restore the data bank
rts
tempStr ds.b 4
dc.b 0
ENDP
****************************************************************
****************************************************************
* This routine takes TextOffset as an input and returns the
* top of the line in TextVPos and the left of the character in
* TextHPos
****************************************************************
OffsetToPoint PROC EXPORT
originalOffset equ 0
myCounter equ 0
jsr Save0_4 ;get space for our locals
movl TextOffset,originalOffset ;save this for later
ldy #TERecord.ViewRect.top
jsr GetRecordLong ;this gets both the top and left
sta TextVPos ;this is the top
stx TextHPos ;this is the left
ldy #TERecord.VertScrollPos ;this is the offset for the top of the
jsr GetRecordLong ;..screen.
stax TextOffset
lineLoop jsr FindLineInfo ;get information on the line
lda TextOffset
clc
adc SuperLength
tax ;save in X
sta TextOffset
lda TextOffset+2
adc SuperLength+2
sta TextOffset+2
cmp originalOffset+2
blt keepGoing
bne foundLine
cpx originalOffset
blt keepGoing
bne foundLine
checkEnd ldy #TERecord.NumberOfLines+2
lda [RecordPtr],y
cmp LineNumber+2
bne keepGoing
dey
dey
lda [RecordPtr],y
cmp LineNumber
beq foundLine
keepGoing lda TextVPos ;add the line height to TextVPos
clc
adc LineHeight
sta TextVPos
bra lineLoop
foundLine movl SuperStart,TextOffset ;start at the beginning of this line
lda originalOffset
sec
sbc TextOffset
sta myCounter
lda originalOffset+2
sbc TextOffset+2
sta myCounter+2
jsr GetLeftMargin ;later on, we need to test for stuff
clc ;..like left just, etc
adc TextHPos
sta TextHPos
jsr SetupWidthTable ;setup the width table pointer
mainLoop jsr GetTextFormat
lda myCounter+2
bne skipCheck
lda myCounter
beq done
cmp TextCount
bge skipCheck
sta TextCount
skipCheck lda myCounter
sec
sbc TextCount
sta myCounter
bcs @1
dec myCounter+2
@1 lda #0
shortm
ldx TextCount
bra loopEnd
widthLoop txy
lda [TextPtr],y
tay
lda [WidthTablePtr],y
clc
adc TextHPos
sta TextHPos
bcc loopEnd
inc TextHPos+1
loopEnd dex
bne widthLoop
lda [TextPtr] ;do the last one.
tay
lda [WidthTablePtr],y
longm ;back to long mode here
clc
adc TextHPos
sta TextHPos
lda TextOffset
clc
adc TextCount
sta TextOffset
bcc @2
inc TextOffset+2
@2 lda myCounter
ora myCounter+2
bne mainLoop
done jsr FreeWidthTable ;unlock the width table
jmp Restore0_4
ENDP
****************************************************************
* This routine takes TextOffset as an input. It draws the line
* from TextOffset to the end if it is left justified; otherwise
* it draws the entire line.
****************************************************************
RedrawLine PROC EXPORT
jsr FindLineInfo
jsr GetJust ;get the current justification
cmp #leftJust
beq doLeft
movl SuperStart,TextOffset
jsr OffsetToPoint
jsr MeasureLineWidth
sta TextHPos
jsr GetLeftEdge
pha
jsr GetRightMargin
sec
sbc 1,s
plx
; sta WrapWidth
doLeft lda TextHPos ;position the cursor for drawing
sta TempRect.left
pha
lda TextVPos
sta TempRect.top
clc
adc LineAscent
pha
_MoveTo
drawloop jsr GetTextFormat ;get the format values
ldy #o_PnLoc+2 ;get the horizontal pen position before
lda [GrafPortPtr],y ;..the draw operation
sta TempRect.left
PushZLong TextPtr
PushZWord TextCount
_DrawText
lda TextCount
clc
adc TextOffset
sta TextOffset
bcc @1
inc TextOffset+2
@1 lda WhatStoppedFormat
cmp #lineBreak
beq done
cmp #endOfText
beq done
cmp #styleBreak ;if not style break then loop back
bne drawloop
lda LineAscent
sec
sbc TextAscent
beq drawLoop
clc
adc TextVPos
sta TempRect.bottom
ldy #o_PnLoc+2 ;horizontal pen position
lda [GrafPortPtr],y
sta TempRect.right
jsr EraseTempRect
bra drawloop
done ldy #o_PnLoc+2 ;horizontal pen position
lda [GrafPortPtr],y ;erase the rest of the line
sta TempRect.left
lda TempRect.top
clc
adc LineHeight
sta TempRect.bottom
ldy #TERecord.ViewRect.right
lda [RecordPtr],y
sta TempRect.right
jsr EraseTempRect
clc
rts
ENDP
****************************************************************
DoDelete PROC EXPORT
jsr UnhilightSelection ;remove the selection from the screen
jsr GetSelectionStart ;where are we ?
lda TextOffset
ora TextOffset+2
beql allDone
decl TextOffset ;move back one character
jsr SetSelectionStart ;set the new cursor offset.
jsr SetSelectionEnd
ldax TextOffset
; jsr DeleteChar ;remove this character from the block
; lda TextOffset ;we need to find some way to fix
; ora TextOffset+2 ;..this bug without kludges
; beq skip
; decl TextOffset
skip
; jsr RewrapLines
jsr GetSelectionStart ;set the new cursor position.
jsr OffsetToPoint
jsr PointToCaret
allDone jsr HilightSelection
clc
rts
ENDP
****************************************************************
InsertChar PROC EXPORT
jsr GetSelectionStart ;get the selection start into TextOffset
jsr FindBlockInfo ;get block info for the current selection
subl TextOffset,BlockStart,SourcePtr ;the number of chars before the insert
subl BlockLength,SourcePtr,MoveLength ;calculate the number of chars to move
incl BlockLength ;increment the block length and re-store
jsr SetBlockSize ;..it in the block list
ldy #2 ;add the start of the block to source ptr
lda [BlockHandle]
clc
adc SourcePtr
sta SourcePtr
lda [BlockHandle],y
adc SourcePtr+2
sta SourcePtr+2
ldax SourcePtr ;copy source ptr to dest ptr. dest will be
inc a ;..one greater than source, so as to make
bne @1 ;..space for one character.
inx
@1 stax DestPtr
jsr BlockMove
shortm
lda TheChar ;store the character in the text
sta [SourcePtr]
longm
ldy #TERecord.TextLength ;increment the text length
jsr IncRecordLong
jsr FindLineInfo ;bump the line length counter by one
incl SuperLength
jsr SetLineLength
ldy #TERecord.monoStyle
lda [RecordPtr],y
cmp #TRUE
beq skipStyle
jsr FindStyleInfo ;bump the style length counter by one
incl SuperLength
jsr SetStyleInfo ;..since we didn't add any lines.
skipStyle clc
rts
ENDP
****************************************************************
DeleteChar PROC EXPORT
jsr GetSelectionStart ;get the selection start into TextOffset
jsr FindBlockInfo ;get block info for the current selection
subl TextOffset,BlockStart,DestPtr ;the number of chars before the delete
subl BlockLength,DestPtr,MoveLength ;calculate the number of chars to move
decl MoveLength
ldy #2 ;add the start of the block to source ptr
lda [BlockHandle]
clc
adc DestPtr
sta DestPtr
lda [BlockHandle],y
adc DestPtr+2
sta DestPtr+2
ldax DestPtr ;copy source ptr to dest ptr. dest will be
inc a ;..one greater than source, so as to make
bne @1 ;..space for one character.
inx
@1 stax SourcePtr
jsr BlockMove
decl BlockLength ;decrement the block length and re-store
jsr SetBlockSize ;..it in the block list
ldy #TERecord.TextLength
lda [RecordPtr],y
dec a
sta [RecordPtr],y
cmp #$FFFF
bne @2
iny
iny
lda [RecordPtr],y
dec a
sta [RecordPtr],y
@2 jsr FindLineInfo ;bump the line length counter by one
decl SuperLength
jsr SetLineLength
ldy #TERecord.monoStyle
lda [RecordPtr],y
cmp #TRUE
beq skipStyle
jsr FindStyleInfo ;bump the style length counter by one
decl SuperLength
jsr SetStyleInfo
skipStyle clc
rts
ENDP
****************************************************************
END
;---------------------------------------------------------------
; Quickdraw equates...stolen directly from the qd.equate file. Maybe later
; use QD's actual file.
;---------------------------------------------------------------
DSECT $00
o_PortSCB word
o_ImageRef long
o_Width word
o_BoundsRect block 8
o_PortRect block 8
o_ClipRgn long ;start of the stuff that we save
o_VisRgn long
o_BkPat block 32
o_PnLoc long
o_PnSize long
o_PnMode word
o_PnPat block 32
o_PnMask block 8
o_PnVis word
o_Font long
o_FontID long
o_FontFlags word
o_TxSize word
o_TxFace word
o_TxMode word
o_SpExtra long
o_ChExtra long
o_FGColor word
o_BGColor word ;end of the stuff that we save
o_PicSave long
o_RgnSave long
o_PolySave long
o_GrafProcs long
o_ArcRot word
o_UserField long
o_SysField long
;---------------------------------------------------------------
PushLongSpace ;space for control handle
PushZLong GrafPortPtr ;push the current port's pointer
ldax ParameterPtr ;pointer to the bounding rectangle
clc
adc #TEParam.viewRect
bcc @1
inx
@1 PushAX
PushLong #0 ;CtlData field
PushWord #0 ;CtlFlags field
PushWord #0 ;CtlValue
PushLong #0 ;Param1 + Param2
PushLong #TEDefProc ;my custom defproc
PushLong #0 ;refcon.. for application use
PushLong #0 ;color table pointer
_NewControl ;get our text edit control
****************************************************************
* This routine takes a pointer to the new ruler block in A,X
****************************************************************
AddToRulerList PROC EXPORT
stax MemoryPtr ;save the pointer to the new ruler
ldx #MinRulerSize ;calculate the ruler size
ldy #TERuler.tabType
lda [MemoryPtr],y
cmp #noTabs
beq resizeIt
inx ;if equal tabs then the ruler is two bytes
inx ;..bigger
cmp #equalTabs
beq resizeIt
inx ;if user tabs then the ruler is four bytes
inx ;..bigger than the minimum
cmp #variableTabs
bne resizeIt
ldy #TERuler.numberOfTabs ;the ruler has a variable number of tabs
lda [MemoryPtr],y ;..so find out how many, multiply by four
asl a ;..add the minimum size, and add two for
asl a ;..the count to get the final ruler size.
clc
adc #MinRulerSize+2
tax
resizeIt stx RulerSize
ldy #TERecord.RulerList ;the new ruler is not in the list, so
jsr GetRecordLong ;..add it to the end of the list
PushAX ;three copys of the list handle for
PushAX ;..Get, Set, and Deref.
PushAX
jsr GetHandleSize
stax TextRulerOffset
clc
adc RulerSize
bcc @1
inx
@1 jsr SetHandleSize
lda TextRulerOffset
sec
sbc #4
sta TextRulerOffset
bcs @2
dec TextRulerOffset+2
@2 jsr DerefHandle ;get a pointer to the end of the new list.
clc
adc TextRulerOffset
sta TempPtr
txa
adc TextRulerOffset+2
sta TempPtr+2
ldy #2 ;set the new count field to one.
lda #1
sta [TempPtr]
dec a
sta [TempPtr],y
ldy #4 ;then copy in the new ruler
@loop lda [MemoryPtr],y
sta [TempPtr],y
iny
iny
cpy RulerSize
blt @loop
jmp TerminateTempPtr
ENDP
****************************************************************
****************************************************************
InitialWordWrapOld PROC EXPORT
NewLineLength equ $00
PushZLong NewLineLength
PushLong [RecordPtr],TERecord.LineSuper
jsr KillSuperHandle
ldy #TERecord.NumberOfLines ;clear the number of lines field
lda #0
tax
jsr SetRecordLong
ldy #TERecord.TextLength ;if there is no text, we can skip this
jsr GetRecordLong ;..entire routine - (there are no lines)
stx TempWord
ora TempWord
bne wordWrap
PullLong NewLineLength
rts ;return right here, if there is no text.
;---------------------------------------------------------------
wordWrap stzl TextOffset ;start at the beginning of the text and
lda #LineSuperItemSize*256+MinSuperBlockSize
jsr GetSmallHandle ;get a handle for the new line starts
stax LineBlockHandle ;..array
PushAX ;lock it down and get two pointers:
jsr LockHandle ;..one to the start and one to the current
stax LineBlockStart ;..item
clc
adc #SuperBlockRecord.firstItem
bcc @1
inx
@1 stax LineStartsPtr
ldy #TERecord.TextLength ;set the initial length field of the super
jsr GetRecordLong ;..block
stax [LineBlockStart],SuperBlockRecord.length
ldy #SuperBlockRecord.count ;clear the initial count field of the
lda #0 ;..super block
sta [LineBlockStart],y
stz LineStartsCount ;zero out the count field.
jsr SetupWidthTable ;setup the width table pointer
;---------------------------------------------------------------
lineLoop stz NewLineLength
stz LineHeight
stz LineAscent
jsr GetWrapWidth ;get the width of the line.
sta WrapWidth
sta LineWidth
;---------------------------------------------------------------
mainLoop jsr FindStyleInfo ;find the new style information
bcc @1
jsr InstallStyleItem
@1 jsr GetSuperCount
sta TextCount
jsr FindBlockInfo ;find the current block information
jsr BlockToTextPtr
lda BlockCount
cmp TextCount
bge @2
sta TextCount
@2 lda TextHeight ;set the height and ascent fields
cmp LineHeight
blt @skipHeight
sta LineHeight
@skipHeight lda TextAscent
cmp LineAscent
blt @skipAscent
sta LineAscent
@skipAscent lda #0 ;zero out both A and X
tax
shortm ;short mode for speed
;---------------------------------------------------------------
widthLoop txy
lda [TextPtr],y ;get the character
cmp #$0D ;is it a carriage return ?
beq foundCR
cmp #TAB
beq doTab
tay ;use as an index into the width table
lda WrapWidth ;subtract the character width
sec
sbc [WidthTablePtr],y
sta WrapWidth
bcs @1
dec WrapWidth+1
bmi breakIt ;did we go below zero ?
@1 inx ;increment our counter
cpx TextCount
blt widthLoop ;branch back
;---------------------------------------------------------------
longm ;we need a new block of text, here
ldx TextCount ;add TextCount to the new line's length
jsr addXToTextOffset
ldy #TERecord.TextLength ;check for being at the end of the text.
jsr GetRecordLong
cmp TextOffset
bne mainLoop
cpx TextOffset+2
bne mainLoop
brl lastBreak
;---------------------------------------------------------------
doTab longm
brk $4B
;---------------------------------------------------------------
foundCR longm
inx ;skip over the CR
jsr addXToTextOffset
jsr forceBreak
brl lineLoop
;---------------------------------------------------------------
breakIt lda [WidthTablePtr],y ;get the width of the current char
longm ;back to long mode (B = 0)
clc ;add it back to the WrapWidth
adc WrapWidth
sta WrapWidth
sta LineWidth
jsr addXToTextOffset
tya ;the character was in the Y-Reg
jsr IsItNotAWordBreak ;is the character a word break ?
bcc skipOverThem ;if yes, then skip over them
lda TextOffset ;move back to the beginning of this line
sec
sbc NewLineLength
sta TextOffset
bcs @1
dec TextOffset+2
@1 jsr FindTextPtr
ldx NewLineLength
;---------------------------------------------------------------
@loop dex
bmi breakAtEnd
txy
lda [TextPtr],y
and #$00FF
tay
lda [WidthTablePtr],y
and #$00FF
clc
adc WrapWidth
sta WrapWidth
tya
jsr IsItNotAWordBreak
bcs @loop
;---------------------------------------------------------------
lda [WidthTablePtr],y ;subtract the width of the character
and #$00FF
sta TempWord
lda WrapWidth
sec
sbc TempWord
sta WrapWidth
inx
stx NewLineLength
txa
addIt addl TextOffset
jsr forceBreak
brl lineLoop
breakAtEnd mov LineWidth,WrapWidth
lda NewLineLength
bra addIt
;---------------------------------------------------------------
skipOverThem inc NewLineLength
incl TextOffset
ldy #TERecord.TextLength
lda [RecordPtr],y
cmp TextOffset
bne @ok
iny
iny
lda [RecordPtr],y
cmp TextOffset+2 ;if at the end, then break.
beq lastBreak
@ok jsr FindTextPtr
lda #0
shortm
lda [TextPtr]
tay
lda WrapWidth
sec
sbc [WidthTablePtr],y
sta WrapWidth
bcs @1
dec WrapWidth+1
@1 longm
tya
jsr IsItNotAWordBreak
bcc skipOverThem
jsr forceBreak
brl lineLoop
;---------------------------------------------------------------
lastBreak jsr forceBreak ;break at the very end of the text.
jsr FreeWidthTable
ldy #TERecord.NumberOfLines
jsr GetRecordLong
clc
adc LineStartsCount
bcc @1
inx
@1 ldy #TERecord.NumberOfLines
jsr SetRecordLong
ldy #2
lda #$FFFF
sta [LineStartsPtr]
sta [LineStartsPtr],y
IF LineSuperItemSize<>8 THEN
AERROR 'WARNING... The multiply code must change !'
ENDIF
ldax LineBlockHandle
PushAX ;for the set handle size
PushAX ;for the get handle size
PushAX ;for the unlock
jsr UnlockHandle
lda #256
sec
sbc LineStartsCount
asl a
asl a
asl a
sta LineStartsCount
jsr GetHandleSize
sec
sbc LineStartsCount
bcs @2
dex
@2 jsr SetHandleSize
;---------------------------------------------------------------
lda #MinSuperSize
jsr GetClearHandle
PushAX ;for the unlock
PushAX ;for the lock
stax [RecordPtr],TERecord.LineSuper
jsr LockHandle
stax TempPtr
ldy #SuperRecord.terminator
jsr TerminateTempPtr
ldy #SuperRecord.mainIndex
lda #SuperRecord.firstItem ;set the main index cache value
sta [TempPtr],y
iny
iny
lda #SuperBlockRecord.firstItem ;set the local index cahce value
sta [TempPtr],y
ldy #SuperRecord.itemNumber ;set the low word of item # to one
lda #1
sta [TempPtr],y
ldy #SuperRecord.itemSize ;set the item size field
lda #LineSuperItemSize
sta [TempPtr],y
jsr UnlockHandle ;unlock the main handle from the stack
;---------------------------------------------------------------
ldy #SuperRecord.firstItem
lda LineBlockHandle
sta [TempPtr],y
iny
iny
lda LineBlockHandle+2
sta [TempPtr],y
;---------------------------------------------------------------
ldy #TERecord.VertScrollBar
jsr GetRecordLong
stx TempWord
ora TempWord
beq @skipParams
ldy #TERecord.NumberOfLines ;this won't work for more than 64K lines
lda [RecordPtr],y
pha
jsr CountLinesInView ;returns the number of lines in the view
pha ;..rect
ldy #TERecord.VertScrollBar
jsr GetRecordLong
PushAX
stax TempPtr
_SetCtlParams
jsr DerefTempPtr
ldy #CtrlRecord.ctlRect
@loop lda [TempPtr],y
tyx
sta TempRect-CtrlRecord.ctlRect,x
iny
iny
cpy #CtrlRecord.ctlRect+8
blt @loop
PushZPtr TempRect
_InvalRect
@skipParams stzl TextOffset
PullLong NewLineLength
rts
;---------------------------------------------------------------
;---------------------------------------------------------------
; this subroutine puts a line break in at the current NewLineLength
;---------------------------------------------------------------
forceBreak ldy #2
lda NewLineLength ;set the new line length
sta [LineStartsPtr]
lda #0
sta [LineStartsPtr],y
iny
iny
lda LineHeight ;set the new line height
sta [LineStartsPtr],y
iny
iny
lda LineAscent ;set the new line ascent
sta [LineStartsPtr],y
iny
iny
lda #LineSuperItemSize
addl LineStartsPtr
ldy #SuperBlockRecord.count
lda [LineBlockStart],y
inc a
sta [LineBlockStart],y
inc LineStartsCount ;increment our count
lda LineStartsCount
cmp #256
bne @done
ldax LineBlockHandle
PushAX ;for the lock
PushAX ;for the set handle size
PushAX ;for the get handle size
PushAX ;for the unlock
jsr UnlockHandle
jsr GetHandleSize
stax MoveLength
clc
adc #LineSuperItemSize*256
bcc @1
inx
@1 jsr SetHandleSize
jsr LockHandle
stax LineBlockStart
clc
adc MoveLength
sta LineStartsPtr
txa
adc MoveLength+2
sta LineStartsPtr+2
stz LineStartsCount ;zero out the count field.
ldy #TERecord.NumberOfLines
jsr GetRecordLong
clc
adc #256
bcc @2
inx
@2 ldy #TERecord.NumberOfLines
jsr SetRecordLong
@done rts
;---------------------------------------------------------------
;---------------------------------------------------------------
; this subroutine adds the X-Reg to both NewLineLength and TextOffset
;---------------------------------------------------------------
addXToTextOffset txa
clc
adc NewLineLength
sta NewLineLength
txa
addl TextOffset
rts
;---------------------------------------------------------------
ENDP
scrollColors dc.w $0000 ;Outline.
dc.w $00F0 ;Arrow when normal.
dc.w $00F0 ;Arrow when selected.
dc.w $00F0 ;Arrow's box interior.
dc.w $00F0 ;Thumber when normal.
dc.w $0000 ;Not used and should never be used.
dc.w $0030 ;Page region interior.
dc.w $00F0 ;Interior color of inactive bar.
****************************************************************
; this routine takes TextOffset pointing anywhere within the current
; line and it calculates the width of the LAST field in the line.
; It returns TextOffset pointing to the start of the last field, X-Reg
; as an offset into the line for the same thing. Finally TempWord is
; the field width
****************************************************************
MeasureLastField PROCNAME
jsr FindLineStart ;start at the beginning of the line
jsr FindTextPtr ;setup the text pointer
ldy SuperLength ;start at the end of the line
shortm ;short mode for speed
@tabLoop dey ;search backwards for the first TAB
bmi atStart
lda [TextPtr],y
cmp #TAB
bne @tabLoop
atStart longm ;back to long mode
iny ;skip over the TAB
tya ;move TextOffset to the start of the last
addl TextOffset ;..field
cpy SuperLength ;are we at the end of the line ?
beq tabAtEnd
phy ;nope, so save Y-Reg
jsr MeasureField ;measure the last field
sta TempWord ;store the result in TempWord
plx ;restore our index into X
rts
tabAtEnd stz TempWord ;zero out our width
tyx ;X-Reg is our returned index
rts
ENDP
****************************************************************
****************************************************************
* This checks TempRect to see if it is contained by the vis region
* of the current grafport. carry clr if TempRect IS inside the
* region. carry set if not. Uses MemoryPtr.
****************************************************************
IsTempRectInVisRgn PROCNAME
ldy #GrafPort.VisRgn+2 ;get the region handle out of the grafport
lda [GrafPortPtr],y
sta MemoryPtr+2
ldy #GrafPort.VisRgn
lda [GrafPortPtr],y
sta MemoryPtr
ldy #2 ;deref it into a pointer.
lda [MemoryPtr],y
tax
lda [MemoryPtr]
stax MemoryPtr
lda [MemoryPtr] ;is the vis region rectangular ?
cmp #10 ;if not then we can't check so return
bne outside ;..FALSE
lda [MemoryPtr],y
cmp TempRect.top
bgt outside
ldy #4
lda [MemoryPtr],y
cmp TempRect.left
bgt outside
ldy #6
lda [MemoryPtr],y
cmp TempRect.bottom
blt outside
ldy #8
lda [MemoryPtr],y
cmp TempRect.right
blt outside
clc ;we are completly within the region !!
rts
outside sec
rts
ENDP
****************************************************************
ScrollUpOne PROCNAME
jsr GetScreenTopOffset
lda TextOffset
ora TextOffset+2
beq atTop
decl TextOffset ;get the height of the line right before
jsr FindLineStart ;..the screen top. start at the line start
jsr SetScreenTopOffset ;set the new screen top offset
jsr GetViewRect ;get the view rectangle
lda LineHeight ;scroll it down by the line height
jsr VScrollTempRect
jsr CalculateSelection
jsr GetScreenTopOffset
jsr FindLineInfo
jsr GetViewRect
lda TempRect.top
clc
adc LineHeight
sta TempRect.bottom
ldy #GrafPort.VisRgn
jsr GetPortLong
PushAX
jsr SetupVisRgn ;setup our vis region to clip to the textRect.
jsr OffsetToPoint ;find TextVPos for the drawLine
jsr DrawLine
PullAX
ldy #GrafPort.VisRgn
jsr SetPortLong
jsr SetCtrlValue
clc
rts
atTop sec
rts
ENDP
****************************************************************
ScrollDownOne PROCNAME
jsr GetScreenTopOffset ;start at the top of the screen for both
ldy #TERecord.ViewRect.top ;..TextOffset and TextVPos
lda [RecordPtr],y
sta TextVPos
@loop jsr IsTextOffsetAtEnd
beq atBottom
jsr FindLineInfo
addl TextOffset,SuperLength,TextOffset
lda TextVPos
clc
adc LineHeight
sta TextVPos
ldy #TERecord.ViewRect.bottom
cmp [RecordPtr],y
blt @loop
jsr GetScreenTopOffset ;get the height of the line at the screen
jsr FindLineInfo
addl TextOffset,SuperLength,TextOffset
jsr SetScreenTopOffset ;set the new screen top offset
jsr FindLineInfo
jsr GetViewRect ;get the view rectangle
lda LineHeight ;scroll it down by the line height
eor #$FFFF ;change the sign (the INC is part of the
inc a ;..sign change)
pha
jsr VScrollTempRect
jsr CalculateSelection
PullWord LineHeight ;get our saved value into LineHeight
ldy #GrafPort.VisRgn
jsr GetPortLong
PushAX
jsr SetupVisRgn ;setup our vis region to clip to the textRect.
ldy #TERecord.ViewRect.left
lda [RecordPtr],y
sta DrawRect.left
ldy #TERecord.ViewRect.bottom
jsr GetRecordLong
sta DrawRect.bottom
stx DrawRect.right
clc
adc LineHeight
sta DrawRect.top
jsr DoDraw
PullAX
ldy #GrafPort.VisRgn
jsr SetPortLong
jsr SetCtrlValue
atBottom clc
rts
ENDP
****************************************************************
SetCtrlValue PROCNAME
jsr GetScreenTopOffset
jsr FindLineInfo
jsr GetVertScrollBar
beq skipSet
ldy LineNumber ;save the new value
dey
phy
PushAX ;the control handle for the scroll bar.
stax TempPtr
jsr DerefTempPtr
ldy #CtrlRecord.dataSize
lda [TempPtr],y
ldy #CtrlRecord.viewSize
sec
sbc [TempPtr],y
cmp 5,s
bge @ok
sta 5,s
@ok _SetCtlValue
skipSet rts
ENDP
****************************************************************
SetupVisRgn PROCNAME
jsr GetViewRect ;clip to the text rectangle
ldy #GrafPort.VisRgn ;get the region handle, deref it and store
jsr GetPortLong ;..in memory pointer
jsr DerefAX
stax MemoryPtr
lda [MemoryPtr] ;is the region rectangular ? If not, we
cmp #10 ;..must intersect the regions
bne mustSectRgn
lda [MemoryPtr],y ;Y-Reg is still two here
cmp TempRect.top
bgt notContained
ldy #4
lda [MemoryPtr],y
cmp TempRect.left
bgt notContained
ldy #6
lda [MemoryPtr],y
cmp TempRect.bottom
blt notContained
ldy #8
lda [MemoryPtr],y
cmp TempRect.right
bge setRectClip
;---------------------------------------------------------------
notContained ldy #8 ;compare right point
lda [MemoryPtr],y
cmp TempRect.right
bpl @1
sta TempRect.right
@1 ldy #6 ;compare bottom point
lda [MemoryPtr],y
cmp TempRect.bottom
bpl @2
sta TempRect.bottom
@2 ldy #4 ;compare left point
lda [MemoryPtr],y
cmp TempRect.left
bmi @3
sta TempRect.left
@3 cmp TempRect.right ;check for empty rect
bpl @zeroIt
ldy #2 ;compare top point
lda [MemoryPtr],y
cmp TempRect.top
bmi @4
sta TempRect.top
@4 cmp TempRect.bottom ;check for empty rect
bmi setRectClip
@zeroIt jsr zeroTempRect
;---------------------------------------------------------------
setRectClip jsr SetRectClipRgn
bra setClip
;---------------------------------------------------------------
mustSectRgn jsr SetRectClipRgn ;set our clipping region to the ViewRect
ldy #GrafPort.VisRgn
jsr GetPortLong
PushWordSpace ;space for empty region results
PushAX ;for EmptyRgn
PushAX ;for sect region
ldax TextClipRgn ;push two copies of TempRgn
stax TempPtr ;save in TempPtr for deref
PushAX
PushAX
_SectRgn
_EmptyRgn
pla
beq @notEmpty
jsr zeroTempRect
bra setClip
@notEmpty jsr DerefTempPtr ;dereference the TextClipRgn's handle
ldy #2 ;copy the bounding box into DrawRect
@loop lda [TempPtr],y
tyx
sta TempRect-2,x
iny
iny
cpy #10
blt @loop
;---------------------------------------------------------------
setClip ldax TextClipRgn
ldy #GrafPort.VisRgn
jsr SetPortLong
mov TempRect.top,DrawRect.top ;copy TempRect into DrawRect
mov TempRect.left,DrawRect.left
mov TempRect.bottom,DrawRect.bottom
mov TempRect.right,DrawRect.right
jsr SetupColorPtr ;set the background pattern for the text
ldy #TEColorTable.content
lda [TempPtr],y
jsr SmearColor
ldy #GrafPort.BkPat
@loop sta [GrafPortPtr],y
iny
iny
cpy #GrafPort.BkPat+32
blt @loop
lda #0 ;zero out the space and character extra
tax ;..fields
ldy #GrafPort.SpExtra
jsr SetPortLong
ldy #GrafPort.ChExtra
jmp SetPortLong ;exit back to the caller
;---------------------------------------------------------------
ENDP
****************************************************************
ZeroTempRect PROCNAME
stz TempRect.top
stz TempRect.left
stz TempRect.bottom
stz TempRect.right
rts
ENDP
****************************************************************
SetRectClipRgn PROCNAME
jsr derefTextRgn ;dereference the Text region and leave
lda #10 ;..the pointer in TempPtr. Also leave Y-Reg
cmp [TempPtr] ;..set to #2
beq @sizeOK
sta [TempPtr] ;the new size is 10 bytes
ldx #0
PushZLong TextClipRgn
jsr SetHandleSize
jsr derefTextRgn
@sizeOK lda TempRect.top
sta [TempPtr],y
iny
iny
lda TempRect.left
sta [TempPtr],y
iny
iny
lda TempRect.bottom
sta [TempPtr],y
iny
iny
lda TempRect.right
sta [TempPtr],y
rts
derefTextRgn ldy #2
lda [TextClipRgn],y
sta TempPtr+2
lda [TextClipRgn]
sta TempPtr
rts
ENDP
****************************************************************
****************************************************************
ldy #2
@loop lda [MemoryPtr],y
cmp #$FFFF
beq @done
tya
adc #6 ;carry is already clear from the compare
tay
bra @loop
@done tya
sbc #8 ;carry is set from the compare
tay
lda [MemoryPtr],y
sta TempLong
iny
iny
lda [MemoryPtr],y
sta TempLong+2
ldy #TERecord.SelectionStart
jsr GetRecordLong
cmpl TempLong
bgel notOnScreen
****************************************************************
jsr SetupColorPtr ;set the background pattern for the text
ldy #TEColorTable.content
lda [TempPtr],y
jsr SmearColor
ldy #GrafPort.BkPat
@loop sta [GrafPortPtr],y
iny
iny
cpy #GrafPort.BkPat+32
blt @loop
****************************************************************
DrawFromOffset PROCNAME
EXPORT DrawLine
jsr GetJust ;if the text is not left justified then
cmp #leftJust ;..we must redraw the entire line
bnel DrawLine
jsr OffsetToPoint ;find the starting point
ldy #TERecord.ViewRect.left ;subtract the left edge of the text rect
lda TextHPos
sec
sbc [RecordPtr],y
sta TextHPos
;---------------------------------------------------------------
moveIt lda TextVPos
clc
adc LineAscent
ldy #GrafPort.PnLoc.v
sta [GrafPortPtr],y
lda TextVPos ;move the text position down to the next
sta TempRect.top ;..line. Also set TempRect to the line
clc ;..rect
adc LineHeight
sta TextVPos
sta TempRect.bottom
lda TextHPos ;erase before we draw
ldy #TERecord.ViewRect.left ;add the left edge of the view rect
clc ;..to get the final HPos
adc [RecordPtr],y
sta TempRect.left
ldy #TERecord.ViewRect.right
lda [RecordPtr],y
sta TempRect.right
jsr EraseTempRect
lda TextHPos
moveHorz ldy #TERecord.ViewRect.left ;add the left edge of the view rect
clc ;..to get the final HPos
adc [RecordPtr],y
ldy #GrafPort.PnLoc.h
sta [GrafPortPtr],y
;---------------------------------------------------------------
partLoop jsr GetTextFormat ;get the next chunck of text
PushZLong TextPtr ;.. and draw it.
PushZWord TextCount
_DrawText
lda TextCount ;move the TextOffset forward.
addl TextOffset
lda WhatStoppedFormat
cmp #endOfText ;are we at the end ? Yes = stop drawing
beq atEnd
cmp #tabBreak
beq doTab
cmp #lineBreak
bne partLoop
clc
allDone rts
atEnd sec
bra allDone
;---------------------------------------------------------------
doTab incl TextOffset ;skip over the TAB
ldy #GrafPort.PnLoc.h
lda [GrafPortPtr],y
sec
ldy #TERecord.ViewRect.left
sbc [RecordPtr],y
sta TextHPos
jsr MoveOverTab
sta TextHPos
jsr AdjustForJust
clc
adc TextHPos
bra moveHorz
;---------------------------------------------------------------
DrawLine jsr FindLineStart ;skip offset to point
jsr GetLeftEdge
sta TextHPos
jsr AdjustForJust
clc
adc TextHPos
sta TextHPos
brl moveIt
;---------------------------------------------------------------
ENDP
ldy #TERecord.SelectionState
lda [RecordPtr],y
cmp #offScreen
beq @skipFlip
ldy #TERecord.ViewRect
ldx #0
@loop1 lda [RecordPtr],y
pha
lda DrawRect,x
sta [RecordPtr],y
inx
inx
iny
iny
cpy #TERecord.ViewRect+8
blt @loop1
jsr FlipSelection
ldy #TERecord.ViewRect+6
@loop2 pla
sta [RecordPtr],y
dey
dey
cpy #TERecord.ViewRect
bge @loop2
@skipFlip ldy #TERecord.InsideDrawFlag
lda #$0000
sta [RecordPtr],y
****************************************************************
DoLeftArrow PROCNAME
ldy #TERecord.SavedHPos
lda #$FFFF
sta [RecordPtr],y
jsr GetSelectionStart ;see if we are at the beginning.
lda TextOffset
ora TextOffset+2
bne notAtStart
bit ExtendFlag ;are we extending the selection
bmi nothingToDo
setEnd jsr SetSelectionEnd ;make the selection a caret
jsr UnhilightSelection
jsr CalculateSelection
jsr HilightSelection
nothingToDo brl ScrollToSelection ;scroll to the selection if we are offscreen
;---------------------------------------------------------------
notAtStart lda MoveByFlag
cmp #2
beq moveLine
cmp #1
beq moveWord
decl TextOffset ;move the selection back
bra moveIt
;---------------------------------------------------------------
moveWord decl TextOffset
jsr FindTextPtr
lda [TextPtr]
jsr IsItNotAWordBreak
bcs @nowMove
lda TextOffset
ora TextOffset+2
beq moveIt
bra moveWord
@nowMove jsr FindWordStart
bra moveIt
;---------------------------------------------------------------
moveLine jsr FindLineStart
;---------------------------------------------------------------
moveIt bit ExtendFlag
bmi extend
jsr SetSelectionStart
bra setEnd
;---------------------------------------------------------------
extend ldy #TERecord.SelectionState
lda #onScreen
cmp [RecordPtr],y
beq @1
sta [RecordPtr],y
bra @2
@1 ldy #TERecord.SelectionType
lda [RecordPtr],y
cmp #caretType
bne @2
jsr FlipSelection
@2 ldy #TERecord.SelectionEnd
jsr PushRecordLong
ldy #TERecord.SelectionStart
jsr GetRecordLong
ldy #TERecord.SelectionEnd
jsr SetRecordLong
jsr SetSelectionStart
jsr CalculateSelection
jsr FlipSelection
PullAX
ldy #TERecord.SelectionEnd
jsr SetRecordLong
jsr CalculateSelection
brl ScrollToSelection
;---------------------------------------------------------------
ENDP
****************************************************************
DoRightArrow PROCNAME
ldy #TERecord.SavedHPos
lda #$FFFF
sta [RecordPtr],y
jsr GetSelectionEnd ;see if we are at the beginning.
jsr IsTextOffsetAtEnd
bne notAtEnd
bit ExtendFlag
bmi nothingToDo
setStart jsr SetSelectionStart ;make the selection a caret
jsr UnhilightSelection
jsr CalculateSelection
jsr HilightSelection
nothingToDo brl ScrollToSelection ;scroll to the selection if we are offscreen
;---------------------------------------------------------------
notAtEnd lda MoveByFlag
cmp #2
beq moveLine
cmp #1
beq moveWord
incl TextOffset ;move the selection forward
bra moveIt
;---------------------------------------------------------------
moveWord jsr FindTextPtr
lda [TextPtr]
jsr IsItNotAWordBreak
bcs @nowMove
incl TextOffset
jsr IsTextOffsetAtEnd
beq moveIt
bra moveWord
@nowMove incl TextOffset
jsr FindWordEnd
bra moveIt
;---------------------------------------------------------------
moveLine jsr FindLineInfo
jsr MoveOffsetToNextItem
decl TextOffset
;---------------------------------------------------------------
moveIt bit ExtendFlag
bmi extend
jsr SetSelectionEnd
bra setStart
;---------------------------------------------------------------
extend ldy #TERecord.SelectionState
lda #onScreen
cmp [RecordPtr],y
beq @1
sta [RecordPtr],y
bra @2
@1 ldy #TERecord.SelectionType
lda [RecordPtr],y
cmp #caretType
bne @2
jsr FlipSelection
@2 ldy #TERecord.SelectionStart
jsr PushRecordLong
ldy #TERecord.SelectionEnd
jsr GetRecordLong
ldy #TERecord.SelectionStart
jsr SetRecordLong
jsr SetSelectionEnd
jsr CalculateSelection
jsr FlipSelection
PullAX
ldy #TERecord.SelectionStart
jsr SetRecordLong
jsr CalculateSelection
brl ScrollToSelection
;---------------------------------------------------------------
ENDP
****************************************************************
DoDownArrow PROCNAME
jsr GetSelectionEnd
jsr FindLineInfo ;find the current line
ldy #TERecord.NumberOfLines
jsr GetRecordLong
cpx LineNumber+2
bne notAtEnd
cmp LineNumber
bne notAtEnd
bit ExtendFlag
bmi nothingToDo
jsr SetSelectionStart ;make the selection a caret
jsr UnhilightSelection
jsr CalculateSelection
jsr HilightSelection
nothingToDo brl ScrollToSelection ;scroll to the selection if we are offscreen
;---------------------------------------------------------------
notAtEnd jsr OffsetToPoint
ldy #TERecord.SavedHPos
lda [RecordPtr],y
cmp #$FFFF
beq @1
sta TextHPos
@1 pei TextHPos ;save the old horizontal position
jsr FindLineInfo
jsr MoveOffsetToNextItem
jsr HPosToOffset
bit ExtendFlag
bmi extend
jsr SetSelectionEnd
jsr SetSelectionStart ;make the selection a caret
jsr UnhilightSelection
jsr CalculateSelection
jsr HilightSelection
setSave ldy #TERecord.SavedHPos
pla
sta [RecordPtr],y
bra nothingToDo
;---------------------------------------------------------------
extend ldy #TERecord.SelectionState
lda #onScreen
cmp [RecordPtr],y
beq @1
sta [RecordPtr],y
bra @2
@1 ldy #TERecord.SelectionType
lda [RecordPtr],y
cmp #caretType
bne @2
jsr FlipSelection
@2 ldy #TERecord.SelectionStart
jsr PushRecordLong
ldy #TERecord.SelectionEnd
jsr GetRecordLong
ldy #TERecord.SelectionStart
jsr SetRecordLong
jsr SetSelectionEnd
jsr CalculateSelection
jsr FlipSelection
PullAX
ldy #TERecord.SelectionStart
jsr SetRecordLong
jsr CalculateSelection
bra setSave
;---------------------------------------------------------------
ENDP
****************************************************************
DoUpArrow PROCNAME
jsr GetSelectionStart
jsr FindLineInfo ;find the current line
lda LineNumber+2
bne notAtStart
lda LineNumber
cmp #1
bne notAtStart
bit ExtendFlag
bmi nothingToDo
jsr SetSelectionEnd ;make the selection a caret
jsr UnhilightSelection
jsr CalculateSelection
jsr HilightSelection
nothingToDo brl ScrollToSelection ;scroll to the selection if we are offscreen
;---------------------------------------------------------------
notAtStart jsr OffsetToPoint
ldx #0
bcs @notOnScreen
dex
@notOnScreen stx ScreenFlag
ldy #TERecord.SavedHPos
lda [RecordPtr],y
cmp #$FFFF
beq @1
sta TextHPos
@1 pei TextHPos ;save the old horizontal position
jsr FindLineInfo
ldax SuperStart
decl a
stax TextOffset
jsr HPosToOffset
bit ExtendFlag
bmi extend
jsr SetSelectionStart
jsr SetSelectionEnd ;make the selection a caret
jsr UnhilightSelection
bit ScreenFlag
bmi @checkIt
jsr ScrollToSelection
bra calcIt
@checkIt ldy #TERecord.TopTextOffset
jsr GetRecordLong
cmpl TextOffset
blt calcIt
jsr ScrollUpOne
calcIt jsr CalculateSelection
jsr HilightSelection
setSave ldy #TERecord.SavedHPos
pla
sta [RecordPtr],y
rts
;---------------------------------------------------------------
extend ldy #TERecord.SelectionState
lda #onScreen
cmp [RecordPtr],y
beq @1
sta [RecordPtr],y
bra @2
@1 ldy #TERecord.SelectionType
lda [RecordPtr],y
cmp #caretType
bne @2
jsr FlipSelection
@2 PushZLong TextOffset
bit ScreenFlag
bpl @cont
ldy #TERecord.TopTextOffset
jsr GetRecordLong
cmpl TextOffset
blt @nope
jsr ScrollUpOne
bra @cont
@nope stz ScreenFlag
@cont PullLong TextOffset
ldy #TERecord.SelectionEnd
jsr PushRecordLong
ldy #TERecord.SelectionStart
jsr GetRecordLong
ldy #TERecord.SelectionEnd
jsr SetRecordLong
jsr SetSelectionStart
jsr CalculateSelection
jsr FlipSelection
PullAX
ldy #TERecord.SelectionEnd
jsr SetRecordLong
jsr CalculateSelection
bit ScreenFlag
bpl setSave
jsr ScrollToSelection
bra setSave
;---------------------------------------------------------------
ENDP
****************************************************************
****************************************************************
; this routine returns the screen point TextVPos and TextHPos
; associated with TextOffset. It returns carry set (TRUE) if the
; offset is not on the screen. In this case TextVPos and TextHPos
; will be the topleft of the viewRect or the botRight of the viewRect
****************************************************************
OffsetToPoint PROCNAME
movl TextOffset,OriginalOffset ;save this for comparing against later
ldy #TERecord.ViewRect.top ;start TextVPos at the top of the
lda [RecordPtr],y ;..viewRect
sec
ldy #TERecord.TopTextVPos
sbc [RecordPtr],y
sta TextVPos
ldy #TERecord.TopTextOffset ;start scanning from the top of the screen
jsr GetRecordLong
cpx TextOffset+2 ;check to see if the offset we are looking
blt pastTheTop ;..for is before the top of the screen.
bne abortTop ;If so, then abort with carry set and
cmp TextOffset ;..TextVPos set to the viewRect.top
ble pastTheTop ;we're on screen here so continue
;---------------------------------------------------------------
abortTop ldy #TERecord.ViewRect.top ;start TextVPos at the top of the
lda [RecordPtr],y ;..viewRect
sta TextVPos
jsr GetLeftMargin ;find the leftmost position in the line
sta TextHPos ;..and return this as the TextHPos when
jsr GetLeftEdge ;..aborting because of being before the
cmp TextHPos ;..screen top
bge abortBottom
sta TextHPos
abortBottom ldy #TERecord.ViewRect.left
lda TextHPos
clc
adc [RecordPtr],y
sta TextHPos
movl OriginalOffset,TextOffset ;restore the original text offset
sec ;set the carry to indicate the text is
rts ;..off the screen. Then return
;---------------------------------------------------------------
pastTheTop stax TextOffset ;start at the offset of the screen top.
@lineLoop jsr FindLineInfo ;find the line length and height
lda TextOffset ;add the length to TextOffset and leave
clc ;..the result in the X-Reg (low) and the
adc SuperLength ;..A-Reg (high)
tax
lda TextOffset+2
adc SuperLength+2
cmp OriginalOffset+2 ;are we at (or past) the original offset?
blt @storeIt ;..yes = goto foundLine
bne foundLine
cpx OriginalOffset
blt @storeIt
bne foundLine
@storeIt sta TextOffset+2 ;save the new value of TextOffset
stx TextOffset
ldy #TERecord.NumberOfLines+2 ;check to see if there are any more lines
lda [RecordPtr],y ;..in the record. If not, we must be on
cmp LineNumber+2 ;..the last line, since illegal values
bne @keepGoing ;..of text offset are not permited.
ldy #TERecord.NumberOfLines
lda [RecordPtr],y
cmp LineNumber
beq @lastLine
@keepGoing jsr AreWePageBreaking
beq @skipPage
lda TextOffset
ora TextOffset+2
beq @skipPage
jsr FindPageInfo
lda TextOffset
cmp SuperStart
bne @skipPage
lda TextOffset+2
cmp SuperStart+2
bne @skipPage
mov PageHeight,LineHeight
@skipPage lda TextVPos ;add the line height to TextVPos to move
clc ;..to the next line
adc LineHeight
sta TextVPos
ldy #TERecord.ViewRect.bottom ;are we still in the viewRect ?
cmp [RecordPtr],y
bmi @lineLoop ;..yep, so continue looping
lda [RecordPtr],y ;get the bottom of the view rect again
sta TextVPos ;..and put it in TextVPos
jsr GetRightMargin
sta TextHPos
brl abortBottom ;abort with past the end of the screen
@lastLine subl TextOffset,SuperLength,TextOffset
;---------------------------------------------------------------
foundLine jsr GetLeftEdge ;start at the left edge of the rectangle
sta TextHPos
jsr FindAndInstallStyle ;find and install the new style info, then
jsr SetupWidthTable ;..setup the width table
lda OriginalOffset ;find out how many characters are left
sec ;..in the line.
sbc TextOffset
sta AmountLeft ;this is our outer text counter
sta LineOffset ;cache this for later with tabs
beql foundChar
;---------------------------------------------------------------
mainLoop jsr FindAndInstallStyle ;find and install the current style info
jsr GetSuperCount ;count how many characters are in the
cmp AmountLeft ;..current style. If this is > 64k, $FFFF
bge useLeft ;..will be returned.
sta TextCount ;the amount left is greater than the count
lda AmountLeft ;..in the current style, so reduce the amount
sec ;..left and use the current style count.
sbc TextCount ;In this case we will need to loop back to
sta AmountLeft ;..mainLoop eventually.
bra widthStart
useLeft lda AmountLeft ;the current style extends at least to the offset
sta TextCount ;..we are looking for.
stz AmountLeft ;zero out our outer text counter
;---------------------------------------------------------------
widthStart jsr FindTextPtr ;setup the text pointer
lda #0 ;set the high word of A to zero
tax ;also clear the index (X-Reg)
shortm ;short mode for speed
widthLoop txy
lda [TextPtr],y ;get the character
cmp #TAB ;is it a TAB ?
beq doTab
tay ;nope, so use the char as an index into
lda [WidthTablePtr],y ;..the width table. Add the width of the
clc ;..character to the current horz position
adc TextHPos
sta TextHPos
bcc nextChar
inc TextHPos+1 ;we are in short mode, so take care of the
nextChar inx ;..high BYTE !
cpx TextCount
blt widthLoop
longm ;back to long mode
lda TextCount ;move TextOffset past the characters
addl TextOffset ;..we just processed.
lda AmountLeft ;are there any more "parts" to process ?
bne mainLoop ;..yep = go back to the main loop
bra foundChar ;Nope, we found our character - goto foundChar
;---------------------------------------------------------------
doTab longm ;goto long mode for Tab processing
jsr MoveOverTab
sta TextHPos ;store the new HPos
sep #$20 ;set the processor to short mode
bra nextChar ;back to short mode and off to the next char
;---------------------------------------------------------------
foundChar jsr AdjustForJust
clc
adc TextHPos
sta TextHPos
lda FixExtraSpace ;if no fractional adjustment then we are
ora FixExtraSpace+2 ;..done
beq skipAdjust
jsr FindLineStart
jsr FindTextPtr
ldx #0
ldy LineOffset
@loop dey
beq @done
lda [TextPtr],y
cmp #' '
bne @nope
inx
@nope cmp #TAB
bne @loop
@done PushLongSpace ;space for the multiply
PushZLong FixExtraSpace ;the fractional pixel amount for spaces
phx ;the number of spaces
pea $0000
_FixMul
plx ;discard the fraction
pla ;the carry will be set if X > $8000 and
cpx #$8000 ;..clr if less than $8000. This rounds
adc TextHPos ;..the fraction into the nearest integer
sta TextHPos
skipAdjust ldy #TERecord.ViewRect.left
lda TextHPos
clc
adc [RecordPtr],y
sta TextHPos
jsr FreeWidthTable
movl OriginalOffset,TextOffset
clc ;clear the carry to indicate we are on the
rts ;..screen
;---------------------------------------------------------------
ENDP
****************************************************************
****************************************************************
; the super handle comes in in A,X. the item that is operated on
; is the current one and the new length is in SuperLength. The
; extra amount is added to or subtracted from the NEXT item in
; the super array.
;---------------------------------------------------------------
ChangeSuperLength PROCNAME
stax TempLong ;save the passed super handle
jsr SetupSuperPtrs ;the SuperHandle comes in in A,X
;---------------------------------------------------------------
lda [TempPtr],y ;calculate (oldValue - newValue). leave
sec ;..the low word of the result on the
sbc SuperLength ;..stack and the high word in X-Reg.
pha
lda SuperLength ;also move the newValue into the array
sta [TempPtr],y
iny
iny
lda [TempPtr],y
sbc SuperLength+2
tax
lda SuperLength+2
sta [TempPtr],y
jsr checkForRemove ;remove this item if the new length is zero
bcs @skipAdd ;TRUE means the item was removed, so don't
lda SuperLocalIndex ;..move to the next item
clc
adc SuperItemSize
@skipAdd inc a ;start with the high word of the item
inc a
tay
lda [TempPtr],y
dey
dey
and [TempPtr],y ;if both the low and high words are $FFFF
inc a ;..then goto next block
beq nextBlock
;---------------------------------------------------------------
doItem pla ;get back the low part of the difference
clc ;add the difference to the next item
adc [TempPtr],y
sta [TempPtr],y
iny
iny
txa
adc [TempPtr],y
sta [TempPtr],y
brl checkForRemove ;remove this item if the length is zero
;---------------------------------------------------------------
;---------------------------------------------------------------
nextBlock ldy #2 ;update the length field in the first
lda 1,s ;..block
clc
adc [TempPtr]
sta [TempPtr]
txa
adc [TempPtr],y
sta [TempPtr],y
lda SuperMainIndex ;move the main index to the next block
clc
adc #4
sta SuperMainIndex
jsr GetLocalSuperHandle
sta TempPtr
stx TempPtr+2
bmi @atEnd ;is this the final end ?
jsr DerefTempPtr ;local handle goes to local ptr
ldy #2 ;update the length field of the new block
lda [TempPtr]
sec
sbc 1,s
sta [TempPtr]
phx
lda [TempPtr],y
sbc 1,s
sta [TempPtr],y
plx
ldy #SuperBlockRecord.firstItem
bra doItem
@atEnd rts
;---------------------------------------------------------------
;---------------------------------------------------------------
checkForRemove dey ;A-Reg contains the high word of the item
dey ;check for the item being zero
ora [TempPtr],y
beq @removeIt ;..if it is then remove it.
clc ;FALSE = did not remove an item
rts
@removeIt phx ;save the high word of the difference
bit StyleFlag
bpl @skipStyle
tya
clc
adc #4
tay
lda [TempPtr],y
sta TextStyleOffset
iny
iny
lda [TempPtr],y
sta TextStyleOffset+2
PushZLong TempPtr
jsr SetupStylePtr
ldy #2
lda [TempPtr]
bne @decIt
lda [TempPtr],y
dec a
sta [TempPtr],y
lda [TempPtr]
@decIt dec a
sta [TempPtr]
PullLong TempPtr
@skipStyle ldy #SuperBlockRecord.count
lda [TempPtr],y
dec a
sta [TempPtr],y
bne @insideBlock
lda #SuperBlockRecord.firstItem ;for reseting the pointers later
sta SuperLocalIndex
lda SuperMainIndex
sta DestPtr
clc
adc #4
sta SourcePtr
ldax TempLong
bra @crunchIt
@insideBlock lda SuperLocalIndex
sta DestPtr
clc
adc SuperItemSize
sta SourcePtr
jsr GetLocalSuperHandle
@crunchIt stz SourcePtr+2 ;zero the high words of the pointers
stz DestPtr+2
jsr CrunchHandle
ldax TempLong
jsr SetupSuperPtrs
plx
lda SuperLocalIndex
sec
rts
;---------------------------------------------------------------
ENDP
****************************************************************
InsertSuperItem PROCNAME
PushAX ;save the super handle
jsr FindSuperInfo ;find the right spot in the super array
ldy SuperMainIndex ;get the local handle into TempPtr
lda [MainSuperPtr],y
sta TempPtr
tax
iny
iny
lda [MainSuperPtr],y
sta TempPtr+2
pha ;one copy for set handle size
phx
pha ;..and one for get handle size
phx
jsr GetHandleSize
stax MoveLength
clc
adc SuperItemSize
bcc @1
inx
@1 jsr SetHandleSize
jsr DerefTempPtr ;the local handle is still in TempPtr
lda SuperLocalIndex
clc
adc SuperItemSize
pha ;save this value for later
adc TempPtr
sta SourcePtr ;calculate the source pointer
lda TempPtr+2
adc #0
sta SourcePtr+2
sta DestPtr+2
lda SourcePtr ;..and the destination pointer
clc
adc SuperItemSize
sta DestPtr
bcc @2
inc DestPtr+2
@2 lda MoveLength ;calculate the length to move
sec
sbc 1,s
plx
sta MoveLength
lda MoveLength+2
sbc #0
sta MoveLength+2
jsr BlockMove ;move it !!
ldy SuperLocalIndex ;adjust the length of the first item
lda TextOffset
sec
sbc SuperStart
sta TempLong
sta [TempPtr],y
iny
iny
lda TextOffset+2
sbc SuperStart+2
sta TempLong+2
sta [TempPtr],y
dey
dey
tya ;move the index to the next item
clc
adc SuperItemSize
tay
lda SuperLength ;adjust the length of the next item
sec
sbc TempLong
sta [TempPtr],y
iny
iny
lda SuperLength+2
sbc TempLong+2
sta [TempPtr],y
ldy #SuperBlockRecord.count ;increment the item count
lda [TempPtr],y
inc a
sta [TempPtr],y
PullAX ;restore the super handle
brl FindSuperInfo ;re-position things to the new item.
ENDP
****************************************************************
GetLocalSuperHandle PROCNAME
ldy SuperMainIndex
lda [MainSuperPtr],y
pha
iny
iny
lda [MainSuperPtr],y
tax
pla
rts
ENDP
****************************************************************
InsertStyleItem PROCNAME
ldy #TERecord.StyleSuper
jsr GetRecordLong
brl InsertSuperItem
ENDP
****************************************************************
ChangeStyleLength PROCNAME
lda #$FFFF
sta StyleFlag
ldy #TERecord.StyleSuper
jsr GetRecordLong
brl ChangeSuperLength
ENDP
****************************************************************
****************************************************************
FlipSelection PROCNAME
tempRgn1 equ 0
tempRgn2 equ 4
ldy #TERecord.SelectionActive
lda [RecordPtr],y
bne deactivate
ldy #TERecord.SelectionRect1
jsr CopyIntoTempRect
jsr InvertTempRect
ldy #TERecord.SelectionRect2
jsr CopyIntoTempRect
jsr InvertTempRect
ldy #TERecord.SelectionRect3
jsr CopyIntoTempRect
jsr InvertTempRect
done rts
deactivate jsr IsTheSelectionACaret
bne notCaret
PushLong #greyMask
_SetPenMask
ldy #TERecord.SelectionRect1
jsr CopyIntoTempRect
jsr InvertTempRect
PushLong #blackMask
_SetPenMask
bra done
notCaret PushZLong tempRgn1 ;save these temps
PushZLong tempRgn2
jsr GetNewRgn ;get two temporary regions
stax tempRgn1
jsr GetNewRgn
stax tempRgn2
ldy #TERecord.SelectionRect1
jsr CopyIntoTempRect
PushZLong tempRgn1
PushZPtr TempRect
_RectRgn
ldy #TERecord.SelectionRect2
jsr CopyIntoTempRect
PushZLong tempRgn2
PushZPtr TempRect
_RectRgn
PushZLong tempRgn1
PushZLong tempRgn2
PushZLong tempRgn1
_UnionRgn
ldy #TERecord.SelectionRect3
jsr CopyIntoTempRect
PushZLong tempRgn2
PushZPtr TempRect
_RectRgn
PushZLong tempRgn1
PushZLong tempRgn2
PushZLong tempRgn1
_UnionRgn
PushWord #$8002 ;use not X-OR mode
_SetPenMode
PushWord #0 ;black pattern
_SetSolidPenPat
PushZLong tempRgn1
_FrameRgn
PushZLong tempRgn1
_DisposeRgn
PushZLong tempRgn2
_DisposeRgn
PullLong tempRgn2 ;restore these temps
PullLong tempRgn1
rts
greyMask dc.w $AA55,$AA55
dc.w $AA55,$AA55
blackMask dc.w $FFFF,$FFFF
dc.w $FFFF,$FFFF
ENDP
****************************************************************
****************************************************************
CheckForFastReplace PROCNAME
sec
rts
jsr GetTextLength
cpx #0
bne @1
cmp #2
blt notFast
@1
jsr GetJust ;if the text is not left justified then
cmp #leftJust ;..we must redraw the entire line
bne notFast
lda RemovedHeight
ora RemovedHeight+2
bne notFast
lda RemovedAscent
ora RemovedAscent+2
bne notFast
ldy InputTextLength+2
bne notFast
ldy InputTextLength
bmi notFast
@loop dey
bmi @2
lda [InputTextPtr],y
and #$00FF
cmp #$0D
beq notFast
cmp #PAGE_BREAK
beq notFast
bra @loop
@2
jsr GetRightMargin
clc
ldy #TERecord.ViewRect.left
adc [RecordPtr],y
sta LineRightEdge
jsr GetSelectionStart
jsr FindLineStart
lda TextOffset
ora TextOffset+2
beq @skipFirst
decl TextOffset
jsr checkLine
@skipFirst
jsr GetSelectionStart
jsr checkLine
clc
rts
;---------------------------------------------------------------
notFast sec
rts
;---------------------------------------------------------------
;---------------------------------------------------------------
checkLine jsr FindLineStart
PushZWord LineAscent
PushZWord LineHeight
jsr FindAndInstallStyle
lda #0 ;clear the maximum text height and ascent
tax
ldy #TERecord.MaxTextHeight
jsr SetRecordLong
lda LineRightEdge
sta TextHPos
jsr HPosToOffset
lda LineRightEdge ;compare the right edge with our position
cmp TextHPos
bge @1
decl TextOffset
@1 jsr FindTextPtr
lda [TextPtr]
and #$00FF
cmp #CR
bne @2
incl TextOffset
@2
PullAX
ldy #TERecord.MaxTextHeight
cmp [RecordPtr],y
bne @nope
txa
ldy #TERecord.MaxTextAscent
cmp [RecordPtr],y
bne @nope
jsr IsTextOffsetAtEnd
beq @checkEnd
jsr FindLineInfo
lda TextOffset
cmp SuperStart
bne @nope
lda TextOffset+2
cmp SuperStart+2
bne @nope
@done rts
@checkEnd decl TextOffset
jsr FindTextPtr
lda [TextPtr]
and #$00FF
cmp #CR
beq @ccc
ldy #TERecord.LineAtEndFlag
lda [RecordPtr],y
bpl @nope
bra @done
@ccc ldy #TERecord.LineAtEndFlag
lda [RecordPtr],y
bmi @nope
bra @done
@nope pla ;go back one level
sec
rts
;---------------------------------------------------------------
ENDP
****************************************************************
;---------------------------------------------------------------
&index SETA 80
WHILE >&index > 0 DO
lda |&index,y
sta >&index,x
&index SETA &index-1
ENDWHILE
;---------------------------------------------------------------
****************************************************************
Entry1Proc PROC
EXPORT QuickEntry
EXPORT QuickExit
EXPORT StandardEntry
EXPORT StandardExit
;---------------------------------------------------------------
DSECT 1
TEDirectPtr long
UserDirectPage word
RPart1 word
RPart2 word
RPart3 word
UserStuff word
;---------------------------------------------------------------
ErrorCode equ 0
;---------------------------------------------------------------
RetSave equ 0
;---------------------------------------------------------------
;---------------------------------------------------------------
QuickEntry jsl IncBusyFlg ;increment busy flag (doesn't change ANYTHING)
plx ;pull the return address in X-Reg
phd ;save the user's direct page
tcd ;set ours from our WAP
beq notStarted ;if zero, then we are not started
stx TempWord ;use TempWord to hold the return address
tyx ;check to see if the number of parameters
beq @skipMove ;..is zero.
clc ;make a pointer to our parameter
adc #ParameterSpace-2 ;..area in our direct page and save it
pea $0000 ;the high word is zero
pha
tsc ;get the current stack pointer
phx ;save the number of parameters for adjust
phd ;save our direct page
phx ;save the number of parameters for move
tcd ;set direct page to the old stack pointer
@loop lda UserStuff-2,x ;copy our parameters to OUR direct page
txy
sta [TEDirectPtr],y
dex
dex
bne @loop
@stripIt plx ;get back the number of parameters
lda RPart3 ;copy the user's direct page and the two
sta RPart3,x ;..return addrs over the parameters
lda RPart2
sta RPart2,x
lda RPart1
sta RPart1,x
lda UserDirectPage
sta UserDirectPage,x
tdc ;get the original stack pointer
pld ;restore our direct page
clc ;adjust the stack pointer by
adc 1,s ;..the number of parameters
adc #4 ;skip over the allocated pointer
tcs ;and set it back.
@skipMove phb ;save the user's data bank
phk ;set our data bank.
plb
pei TempWord
rts ;return to caller
notStarted tsc
tcd
lda RPart3-4 ;copy the user's direct page and the two
sta RPart3-4,x ;..return addrs over the parameters
lda RPart2-4
sta RPart2-4,x
lda RPart1-4
sta RPart1-4,x
lda UserDirectPage-4
sta UserDirectPage-4,x
phx
tdc ;adjust the stack
clc
adc 1,s
tcs
phb ;save the user's data bank
phk ;set our data bank.
plb
ldx #teNotStarted ;load the not started error
;---------------------------------------------------------------
QuickExit plb ;restore the original data bank
pld ;restore original direct page
txa ;put the error code into A
cmp #1 ;set the carry flag
jml DecBusyFlg ;decrement busy flag and return to caller
;---------------------------------------------------------------
StandardEntry plx ;pull off the return address
phd ;save the user's direct page
tcd ;set ours from our WAP
beq notStarted ;if zero, then we are not started, so use
stx RetSave ;..quick entry to exit.
pld
jsr QuickEntry ;setup TextEdit. number of parameters in Y
lda RecordHandle
ora RecordHandle+2
bne useThisOne
PushLongSpace
_FindActiveCtl
tax ;put the error code in the X-Reg
pla
sta RecordHandle
pla
sta RecordHandle+2
bcs QuickExit
useThisOne
jsr LockRecordHandle ;lock the main record handle
PushLongSpace ;save the current port
_GetPort
jsr SetWindowPort
pei RetSave
rts
;---------------------------------------------------------------
StandardExit stx ErrorCode
_SetPort
jsr UnlockRecordHandle
ldx ErrorCode
bra QuickExit
;---------------------------------------------------------------
ENDP
****************************************************************
DSECT WorkArea
dstPortPtr long ;these are for the low level drawing
srcPtr long ;..routines
dstPtr long
srcWidth word
dstWidth word
numberOfWords word
numberOfLines word
leftMask word
rightMask word
****************************************************************
FindWordEnd PROCNAME
bra FindWordEndNew
decl TextOffset
jsr FindTextPtr
lda [TextPtr]
jsr IsItAWordBreak
bcs alreadyThere
@loop incl TextOffset
jsr IsOffsetAtEnd
beq atEnd
jsr FindTextPtr
lda [TextPtr]
jsr IsItAWordBreak
bcc @loop
atEnd rts
alreadyThere incl TextOffset
rts
ENDP
****************************************************************
* the value to be draw comes in in A
****************************************************************
DebugHexWord PROC EXPORT
phb ;save the data bank
phk ;set it to ours
plb
PushLongSpace
pha
_HexIt
PullLong tempStr
PushLong #theRect
_GetPen
PushLong #theInfo
_GetFontInfo
PushWordSpace
PushLong #tempStr
_CStringWidth
pla
clc
adc theRectLeft
sta theRectRight
lda theRectTop
clc
adc theInfoAscent
adc theInfoDescent
sta theRectBottom
PushLong #theRect
_EraseRect
PushWord #0
PushWord theInfoAscent
_Move
PushLong #tempStr
_DrawCString
lda #30
jsr DebugDelay
plb ;restore the data bank
rts
origTicks ds.l 1
theRect
theRectTop ds.w 1
theRectLeft ds.w 1
theRectBottom ds.w 1
theRectRight ds.w 1
theInfo
theInfoAscent ds.w 1
theInfoDescent ds.w 1
theInfoWidMax ds.w 1
theInfoLeading ds.w 1
tempStr ds.b 4
dc.b 0
ENDP
****************************************************************
DebugDelay PROC
sta origTicks
stz origTicks+2
PushLongSpace
_TickCount
pla
clc
adc origTicks
sta origTicks
pla
adc origTicks+2
sta origTicks+2
@loop PushLongSpace
_TickCount
PullAX
cmpl origTicks
blt @loop
rts
origTicks ds.l 1
ENDP
****************************************************************
CalculateRemovedHeight PROCNAME
;---------------------------------------------------------------
stzl RemovedHeight ;this is for removing lines
jsr GetSelectionLength
lda SelectionLength
ora SelectionLength+2
bne doIt
rts
;---------------------------------------------------------------
doIt ldy #TERecord.LineSuper
jsr FindSuperInfo
jsr GetSuperMaxIndex
ldy #SuperHandle.cachedIndex ;get the current index for the selection
lda [SuperRecordPtr],y ;..start into Y-Reg
inc a ;start with the high word
inc a
tay
lda TextOffset ;check to see if we are starting on the
cmp SuperStart ;..first item
bne @notAtStart
lda TextOffset+2
cmp SuperStart+2
beq itemLoop
@notAtStart sty TempWord
jsr GetLongSuperCount
stax SuperLength
jsr adjustSelection
bcc allDone
ldy TempWord
bra enterLoop
;---------------------------------------------------------------
ItemLoop lda [TempPtr],y
bmi deletedItem
lda [TempPtr],y
sta SuperLength+2
dey
dey
lda [TempPtr],y
sta SuperLength
jsr adjustSelection
bcc allDone
iny
iny
enterLoop iny
iny
lda [TempPtr],y
addl RemovedHeight
tya
clc
adc #SuperItemSize-2
bra nextItem
deletedItem tya
clc
adc #SuperItemSize
nextItem tay
cpy SuperMaxIndex
blt ItemLoop
jsr MoveToNextHandle
bcs allDone
ldy #SuperBlock.RecordSize+2
bra ItemLoop
;---------------------------------------------------------------
allDone rts
;---------------------------------------------------------------
;---------------------------------------------------------------
adjustSelection lda SelectionLength
sec
sbc SuperLength
sta SelectionLength
lda SelectionLength+2
sbc SuperLength+2
sta SelectionLength+2 ;carry remains set if we are continuing
ora SelectionLength ;carry is clear if we are done
rts ;..the Z-Flag is set if we are done
;---------------------------------------------------------------
ENDP
****************************************************************
SplitBlockList PROCNAME Export
;---------------------------------------------------------------
jsr CachedBlockToPtr ;set TempPtr to our current block and
movl BlockHandle,TempLong ;..save the block handle in TempLong
@loop1 ldy #TextBlock.textLength+2 ;move back through all the previous blocks
lda [TempPtr],y ;..including the current one and see if
bne splitBlock ;..any of them are too big. If they are
ldy #TextBlock.textLength ;..then split just one of them
lda [TempPtr],y
cmp #MaxBlockSize
bge splitBlock
jsr MoveToPrevBlock
bcc @loop1
movl TempLong,BlockHandle ;restore our original block handle, then
jsr BlockHandleToPtr ;..move through all the blocks after this
bra @enter2 ;..one to see if any of these are too big.
@loop2 ldy #TextBlock.textLength+2 ;..If one is, then split it.
lda [TempPtr],y
bne splitBlock
ldy #TextBlock.textLength
lda [TempPtr],y
cmp #MaxBlockSize
bge splitBlock
@enter2 jsr MoveToNextBlock
bcc @loop2
exit rts ;everything was small, so exit
;---------------------------------------------------------------
splitBlock ldx #$FFE0 ;find the maximum number of characters
ldy #TextBlock.textLength+2 ;..to search through
lda [TempPtr],y
bne @1
dey
dey
lda [TempPtr],y
cmp #$FFE0
bge @1
tax
@1 ldy #TextBlock.textStart+SplitBlockSize
shortm ;look for the first carriage return after
@loop lda [TempPtr],y ;..the splitting block size. Note that
cmp #CR ;..if we can't find a CR in the first
beq doIt ;..64K, we abort the split
iny
dex
bne @loop
longm
abortIt rts
;---------------------------------------------------------------
doIt longm ;back to long mode
cpy #$FEFF ;If our index is greater than this, we
bge abortIt ;..will break some other code later on
tya ;..that assumes no overflow from a word.
sec ;If our index is too big, then abort the
sbc #TextBlock.textStart ;..split. Otherwise adjust the index back
sta TempWord ;..to a text offset and this is the new
ldy #TextBlock.textLength ;..length of the old block. Now find the
lda [TempPtr],y ;..length of the NEW block.
sec
sbc TempWord
sta MoveLength
lda TempWord ;also set the new length of the old block
sta [TempPtr],y ;..in the record.
iny
iny
lda [TempPtr],y
sbc #0
sta MoveLength+2
lda #0 ;the high word of the new length is always
sta [TempPtr],y ;..zero
ldax MoveLength ;round off and adjust the new length. Then
and #$FF00 ;..get a handle of the proper size
clc
adc #256+TextBlock.textStart
bcc @1
inx
@1 jsr GetLargeHandle ;if we get a memory error, then abort the
bcs abortIt ;..split
stax TempLong ;save the new handle in TempLong and
jsr DerefAX ;..deref it into MemoryPtr
stax MemoryPtr
jsr BlockHandleToPtr ;reset TempPtr in case the block moved
ldy #TextBlock.nextHandle ;set the next handle field for both the
lda [TempPtr],y ;..new block and the old block
sta [MemoryPtr],y
lda TempLong
sta [TempPtr],y
iny
iny
lda [TempPtr],y
sta [MemoryPtr],y
lda TempLong+2
sta [TempPtr],y
ldy #TextBlock.prevHandle ;set the previous handle of the new block
lda BlockHandle
sta [MemoryPtr],y
iny
iny
lda BlockHandle+2
sta [MemoryPtr],y
ldy #TextBlock.textLength ;set the length of the new block
lda MoveLength
sta [MemoryPtr],y
iny
iny
lda MoveLength+2
sta [MemoryPtr],y
ldy #TextBlock.flags ;clear the flags for the new block
lda #0
sta [MemoryPtr],y
lda TempWord ;find the source pointer for moving the
clc ;..text from the old block to the new one
adc #TextBlock.textStart
adc TempPtr
sta SourcePtr
lda TempPtr+2
adc #0
sta SourcePtr+2
lda #TextBlock.textStart ;the dest pointer is the pointer to the
clc ;..start of the new block adjusted for
adc MemoryPtr ;..the header
sta DestPtr
lda MemoryPtr+2
adc #0
sta DestPtr+2
jsr BlockMove ;move the text
PushZLong BlockHandle ;set the size of the old handle to free
ldx #0 ;..up memory
lda TempWord
and #$FF00
clc
adc #256+TextBlock.textStart
jsr SetHandleSize
jsr BlockHandleToPtr ;reset TempPtr in case the block moved
jsr MoveToNextBlock ;this moves to the newly created block
jsr MoveToNextBlock ;find the next block and if there is one
bcs @allDone ;..then set the prev handle field of it
ldy #TextBlock.prevHandle ;..to the new block
lda TempLong
sta [TempPtr],y
iny
iny
lda TempLong+2
sta [TempPtr],y
@allDone rts
;---------------------------------------------------------------
ENDP
****************************************************************
* this routine concatenates two handles
****************************************************************
HandAndHand PROCNAME Export
;---------------------------------------------------------------
DefineStack
origD word
returnAddr word
srcHandle long
dstHandle long
;---------------------------------------------------------------
phd ;save the old direct page
tsc ;setup our new direct page
tcd
ldy #HandleRecord.length ;get the size of the destination handle
lda [dstHandle],y
pha ;save the low word of the old length
clc
adc [srcHandle],y
tax
iny
iny
lda [dstHandle],y
pha ;save the high word of the old length
adc [srcHandle],y
pha ;Push the new size for set handle size
phx
PushZLong dstHandle
_SetHandleSize
bcs error
lda [dstHandle],y ;add the size of the original dest
tax ;..handle and put it in dest handle
pla
clc
adc [dstHandle]
sta dstHandle
txa
adc 1,s
sta dstHandle+2
plx
ldy #2
lda [srcHandle],y
tax
lda [srcHandle]
PushAX
PushZLong dstHandle ;now a pointer to the end of the old dest
ldy #HandleRecord.length+2 ;get the size of the source handle
lda [srcHandle],y
pha
dey
dey
lda [srcHandle],y
pha
PushWord #%0000100000000101
jsl $E10200 ;use the memory mover
lda returnAddr
sta dstHandle+2
clc ;indicate no error
;---------------------------------------------------------------
done pld
pla ;pull off 8 bytes of garbage
pla
pla
pla
rts
;---------------------------------------------------------------
error tax
pla ;cleanup the stack
pla
sec
bra done
;---------------------------------------------------------------
ENDP
****************************************************************
Save0_4 PROCNAME Export
ply
pei 2
pei 0
phy
rts
ENDP
****************************************************************
Restore0_4 PROCNAME Export
pha
lda 5,s
sta 2
pla
sta 3,s
pla
sta 0
pla
rts
ENDP
****************************************************************
IncRecordLong PROCNAME Export
lda [RecordPtr],y
inc a
sta [RecordPtr],y
bcc skipHigh
iny
iny
lda [RecordPtr],y
inc a
sta [RecordPtr],y
skipHigh rts
ENDP
moveGrowBox PushLongSpace ;find the new top/left of the grow box
_GrowSize ;..and move it to this position
ldy #GrafPort.portRect.bottom
lda [TempPtr],y
inc a
sec
sbc 1,s ;leave the new Y-Pos on the stack
sta 1,s
ldy #GrafPort.portRect.right
lda [TempPtr],y
inc a
sec
sbc 3,s ;leave the new X-Pos on the stack
sta 3,s
jsr GetGrowBoxHandle ;push the control handle
PushAX
_MoveControl
****************************************************************
TEScroll PROCNAME Export
;---------------------------------------------------------------
DSECT ParameterSpace
xRecordHandle long
horzAmount long
vertAmount long
theScrollVerb word
;---------------------------------------------------------------
;---------------------------------------------------------------
ldy #14
jsr StandardEntry
ldx #teInvalidVerb ;check for a verb overflow. If the verb
lda theScrollVerb ;..is ok, then jump thru the table.
cmp #6
bge error
asl a
tax
jmp (table,x)
;---------------------------------------------------------------
doTopOffset nop
doCenterOffset nop
doTopLine nop
doCenterLine nop
;---------------------------------------------------------------
doSetValue ldy #TERecord.VertScrollPos ;get the difference between the new value
lda vertAmount ;..and the old one and store it back in
sec ;..vertAmount.
sbc [RecordPtr],y
sta vertAmount
iny
iny
lda vertAmount+2
sbc [RecordPtr],y ;then, fall through into doOffsetValue
sta vertAmount+2 ;..to do the actual scroll
doOffsetValue ldax vertAmount ;A-Reg and X-Reg contain the amount to scroll
jsr ScrollByAmount ;..Then do it and fall thru into goodExit
;---------------------------------------------------------------
goodExit ldx #0 ;no error
error brl StandardExit
;---------------------------------------------------------------
;---------------------------------------------------------------
table dc.w doTopOffset
dc.w doCenterOffset
dc.w doTopLine
dc.w doCenterLine
dc.w doSetValue
dc.w doOffsetValue
;---------------------------------------------------------------
ENDP
****************************************************************
;---------------------------------------------------------------
checkitnow
ldy #TERecord.LastErrorCode
lda [RecordPtr],y
bne @error
jsr CachedBlockToPtr
lda TempPtr
ora TempPtr+2
beq @break
rts
@break brk $49
rts
@error brk $48
rts
;---------------------------------------------------------------
****************************************************************
WalkText PROCNAME Export
DSECT ParameterSpace
xRecordHandle long
CallBackPtr long
CallBackData long
TheVerb word
iTheLength long ; use some temp space in parameter area
iTheTemp long ; use some more temps!
MaxVerb equ $000F
TEInvalidCallBack equ $0024
TEBadLength equ $0025
;---------------------------------------------------------------
lda TheVerb ;first validate the verb
and #$00FF
cmp #MaxVerb
blt @VerbOK
ldx #teInvalidFlag
sec
rts
@VerbOK
lda CallBackPtr+1 ; next validate the callback pointer
beq @BadCallBack ; see if some bozo passed a nil
lda CallBackPtr+2
and #$00FF
cmp CallBackPtr+2 ; see if some bozo passed a random 4byte
beq @GoodCallBack
@BadCallBack ldx #teInvalidCallBack
sec
rts
;---------------------------------------------------------------
@GoodCallBack
; At this point we have done all the initializing that we can be expected to do...
;
; First position us at the very beginning of the text super block list...
jsr CachedBlockToPtr ;find the first block in the list
@loop1 jsr MoveToPrevBlock
bcc @loop1
; now at the top of the super block list, examine the verb to determine where to start
; and how long to go...
lda theVerb
and #$00FF ; strip off the flags byte..
asl a
tax
jsr (WalkTbl,x) ; calc the proper start/length
bcc @Loop ; start thru the loop if no error
ldx #teBadLength
sec
rts
;
; At this point textOffset is set to the proper starting location for us to run the list
; and the temp length variable is set to the length that we want to run.
;---------------------------------------------------------------
@loop jsr FindTextPtr ; set text ptr and block ptr to proper place...
; Now set up the data for our callback...
pha ; room for result
ldax TextOffset ; push block offset
PushAX
ldax BlockLength ; get the size of the current block
stax iTheTemp ; save it for later in the temp
ldax BlockStart ; see if we are at the beginning of a block..
cmp TextOffset ; by comparing to the text offset
bne @NotAtStart
cpx TextOffset+2
beq @AtStart
@NotAtStart
subl TextOffset,BlockStart,iTheTemp ; temp:=offset-blkStart
subl BlockLength,iTheTemp,iTheTemp ; temp:=Length-temp
@AtStart ldax iTheTemp ; temp now contains the size of the rest of the block
PushAX ; save the current block length...
ldax TextPtr ; push the BlockPointer
pushAX
ldax xRecordHandle ; and finally the record handle..
pushAX
jsl CallCallBack ; now call the callback routine!
jsr BlockHandleToPtr ; re-deref the current super handle
ldy #TextBlock.nextHandle+1 ; see if this was the last block
lda [tempPtr],y
beq @AtTheEnd ; if we are at the last block then just get out!
; bump textoffset and continue
addl TextOffset,iTheTemp,TextOffset ; offset := offset+temp
subl iTheLength,iTheTemp,iTheLength ; length:=length-temp
lda iTheLength+2
bmi @AtTheEnd ; if negative, then we are done..
ora iTheLength
beq @AtTheEnd ; or if its zero we are done!
bra @loop
;---------------------------------------------------------------
@AtTheEnd ldx #0
;---------------------------------------------------------------
allDone ;if the buffer was full, return buffer
cpx #1 ;..full error
rts
;---------------------------------------------------------------
CallCallBack
; This routine calls the routine passed by the programmer by cleverly
; stuffing its address-1 on the stack and RTLing
pha ; make room on the stack for 3 bytes..
phk
lda CallBackPtr+1
sta 2,s
lda CallBackPtr
dec a
sta 1,s
rtl
;---------------------------------------------------------------
doWholeRecord
; Set up the start to 0 and the length to the number of chars in the record
stzL TextOffset ; set the start to 0
jsr GetTextLength
stx iTheLength+2
sta iTheLength
doTestLength ora iTheLength+2 ; be sure we have data to run!
bne @ok
sec
rts
@ok clc ; flag that its ok data
rts
;---------------------------------------------------------------
doFromSelStart jsr GetSelectionStart ; set text offset first
dFSelCont stax TextOffset
jsr GetTextLength ; now, to calculate the remaining bytes
stax iTheLength
subl iTheLength,textOffset,iTheLength ; length:=length-offset
lda iTheLength
bra doTestLength
;---------------------------------------------------------------
doFromSelEnd jsr GetSelectionEnd
bra dfSelCont
;---------------------------------------------------------------
doSelectionOnly jsr GetSelectionStart
stax TextOffset
jsr GetSelectionLength
stax iTheLength
lda iTheLength
bra doTestLength
;---------------------------------------------------------------
doFromArbitrary ldax CallBackData ; programmer passed us the starting point
stax TextOffset
jsr GetTextLength
stax iTheLength
subl iTheLength,TextOffset,iTheLength ; length:=length-offset
bcs @LengthOK ; test here to see if subtract created
sec ; a negative number
rts ; if so flag an error and end.
@LengthOK lda iTheLength
bra doTestLength
;---------------------------------------------------------------
doGivenRange ldy #2
lda [CallBackData],y ; call back data for this is ptr
sta TextOffset+2 ; to the 2 longs of data
lda [callBackData]
sta TextOffset
iny
iny
lda [CallBackData],y
sta iTheLength
iny
iny
lda [CallBackData],y
sta iTheLength+2
; Now we must validate the length passed to be sure we don't crash
jsr GetTextLength ; test the offset first..
sec
sbc TextOffset
tay ; save it for a second..
txa
sbc TextOffset+2
bcc @BadOffset ; if carry clear out of record here!
tax
tya
sbc iTheLength ; now see if we are too long..
txa ; the result is un important..
sbc iTheLength+2
bcc @BadLength ; carry set here means they want too much data
@Cont lda iTheLength
brl doTestLength
@BadLength tya ; get the proper remaining chars in <A><X>
stax iTheLength
bra @cont
@BadOffset sec
rts
;---------------------------------------------------------------
WalkTbl dc.w doWholeRecord
dc.w doFromSelStart
dc.w doFromSelEnd
dc.w doSelectionOnly
dc.w doFromArbitrary
dc.W doGivenRange
;---------------------------------------------------------------
ENDP
****************************************************************