antoine-source/appleworksgs/WP/Src/lines.aii
2023-03-04 03:45:20 +01:00

1 line
39 KiB
Plaintext
Executable File

*****************************************************************************************************
; WP Line Manipulation Routines
;
; This file contains the routines used by WP to manipulate the line handles data structure for
; paragraphs. The paragraph and line handle data strucutures are described below:
;
; The paragraph data structure is an array from 1..W_LastP of paragraph info blocks:
;
; W_pBlockHand gequ 0 : handle to the block that the par is in
; W_pOffset gequ 4 : offset into this block that starts the par
; W_pAttr gequ 6 : attribute word for the par
; W_pRulerHand gequ 8 : handle to the ruler that governs this par
; W_pPixels gequ 12 : number of pixels tall this par is
; W_pLineHand gequ 14 : handle to the line struct for this par (Purgeable)
; W_pLastLine gequ 18 : number of last line in the par+1, cr is 0
; W_pBytes gequ 20 : equate for size of paragraph block.
;
; The linehandle will always have a header as follows
;
; W_MaxLine gequ 0
; W_LineHeader gequ 4
;
; The LineHandle in the paragraph record is an array from 0..W_lastline-1. Each record looks like:
;
; W_lOffset gequ 0
; W_lFont gequ 2
; W_lSize gequ 4
; W_lStyle gequ 5
; W_lColor gequ 6
; W_lAscent gequ 8
; W_lDescent gequ 10
; W_lHeight gequ 12
; W_lLeading gequ 14
; lREcSize gequ 16
;
*****************************************************************************************************
load 'macros.dump'
include 'driver.equ'
include 'wp.equ'
IMPORT D_BeachBall
IMPORT D_Deref
IMPORT D_GetStats
IMPORT D_GetWdth
IMPORT D_GrowLHandle
IMPORT D_MainZPage
IMPORT D_NeedHandle
IMPORT D_MustHandle
IMPORT D_MustGrowL
IMPORT D_NoAlert
IMPORT D_SelectFont
IMPORT D_UnLock
IMPORT W_DateStr
IMPORT W_DeepShit
IMPORT W_EndColor
IMPORT W_EndFont
IMPORT W_EndPtr
IMPORT W_EndStyle
IMPORT W_GetAddr
IMPORT W_GetLeft
IMPORT W_GetParRec
IMPORT W_Hand
IMPORT W_Indent
IMPORT W_JustBits
IMPORT W_JustExtra
IMPORT W_JustPtr
IMPORT W_JustSpaces
IMPORT W_LastP
IMPORT W_LeftMargin
IMPORT W_MaxAscent
IMPORT W_MaxDescent
IMPORT W_MaxLeading
IMPORT W_NumTabs
IMPORT W_PageStr
IMPORT W_ReadRuler
IMPORT W_RightMargin
IMPORT W_RulBits
IMPORT W_STColor
IMPORT W_STFont
IMPORT W_STLIne
IMPORT W_STPtr
IMPORT W_STStyle
IMPORT W_Tabs
IMPORT W_TimeStr
ENTRY W_CalcLineHeight
ENTRY W_CutLine
ENTRY W_GetLineRec
ENTRY W_UseTab
*****************************************************************************************************
; W_MakeLines ( Paragraph:word )
;
; This routine is called to generate all the textual information for the given paragraph. This
; routine will return an error if the line handle could not be allocated ( either because there is
; is not enough memory or because more than 4k lines exit in the paragraph ).
W_MakeLines PROC EXPORT
;Using wpglobals
input par:w
local ptr:l,LineHand:l,LinePtr:l,MaxLine:w
local ParRec:l,LineRec:l,LineBeg:l,pixels:w
error err
begin
; Get pointer to paragraph record and check if page break paragraph. If so no lines to make so just
; exit.
stz err
rcall W_GetParRec,in=(par:a),out=(ParRec:ax)
cmpw [ParRec]:#W_pAttr,#W_PgBrk
jeq exit
; Get ruler information for the paragraph.
movelong [ParRec]:#W_pRulerHand,ax
jsl W_ReadRuler
; Get line handle for paragraph. If no line handle exists then set paragraph line count to be
; initially 1.
movelong [ParRec]:#W_pLineHand,LineHand
cpzl LineHand
bne chknil
moveword #1,[ParRec]:#W_pLastLine
bra getlinehand
; If line handle has been purged then dispose of old handle and fall through to create new one.
chknil cpzl [LineHand]
jne NotPurge
tool _DisposeHandle,in=([ParRec]:#W_pLineHand:l)
; Ask for line handle large enough to hold all the lines in the paragraph. If we can't get it
; we're in trouble so use must handle. Note: Will fail if we have more than 4k lines in the
; paragraph. Line handle will be allocated as most purgeable status.
getlinehand cmpw [ParRec]:#W_pLastLine,#$0FFF
bge abort
moveword #1,>D_NoAlert
moveword [ParRec]:#W_pLastLine,a
inc a
asl a
asl a
asl a
asl a
clc
adc #W_LineHeader
ldx #0
call D_MustHandle,in=(ax:l,#$300:w),out=(LineHand:l),err=err
moveword #0,>D_NoAlert
bcc gotline
; Really bad error has occurred. Just return with error -1 (handled) and hope we recover.
abort moveword #-1,err
sta W_DeepShit
tool _SysBeep
movelong #0,[ParRec]:#W_pLineHand
IF (Developing) THEN
setborder #3
ENDIF
brl unlocktext
; Successfully got the line handle (whew!) so put it in the paragraph. Put line count into start
; of line handle.
gotline movelong LineHand,[ParRec]:#W_pLineHand
movelong [LineHand],LinePtr
moveword [ParRec]:#W_pLastLine,[LinePtr]
; Line handle exists. Loop through all lines getting line information as we go along. Lock down
; the line handle and the paragraph text block. Get the max line count. Get pointer to start of
; text block where paragraph font information is.
NotPurge rcall D_Deref,in=(LineHand:ax),out=(LinePtr:ax)
rcall D_Deref,in=([ParRec]:ax)
moveword [LinePtr],MaxLine
rcall W_GetAddr,in=(par:a,#0:x),out=(ptr:ax)
; Set up CutLine global variables.
addlong #W_TextHeader,ptr,W_STPtr
stz W_STLIne
moveword [ptr],W_STFont
moveword [ptr]:#2,W_STStyle
moveword [ptr]:#4,a
and #$ff
sta W_STColor
stz pixels
; Call cutline to determine the end values for the line we specified above. The global variables for
; the end font/style/color/ptr and max ascent/descent/leading will be set. Get pointer to the lines
; record.
LineLoop jsl W_CutLine
; jsl D_BeachBall
rcall W_GetLineRec,in=(LinePtr:ax,W_STLine:y),out=(LineRec:ax)
; Fill in line record information for current line.
subword W_STPtr,ptr,[LineRec]:#W_lOffset
moveword W_STFont,[LineRec]:#W_lFont
moveword W_STStyle,[LineRec]:#W_lStyle
moveword W_STColor,[LineRec]:#W_lColor
moveword W_MaxAscent,[LineRec]:#W_lAscent
moveword W_MaxDescent,[LineRec]:#W_lDescent
clc
adc W_MaxAscent
moveword a,[LineRec]:#W_lHeight
moveword W_MaxLeading,[LineRec]:#W_lLeading
; Adjust current pixel position by the height of the line (takes into account line spacing).
movelong LineRec,ax
jsl W_CalcLineHeight
addword a,pixels,pixels
; Setup values for start of next line to be same as end of last line.
moveword W_EndFont,W_STFont
moveword W_EndStyle,W_STStyle
moveword W_EndColor,W_STColor
movelong W_EndPtr,LineBeg
movelong W_EndPtr,W_STPtr
; If carriage return then we are done getting lines for the paragraph so branch.
lda [LineBeg]
and #$ff
cmp #cr
beq DoneLoop
; Bump the line count. If we have not exceed the line count for the paragraph go back and process the
; next line.
inc W_STLIne
cmpw W_STLIne,MaxLine
jcc LineLoop
; Paragraph has grown. We need to enlarge the line handle to hold new line record information. Try to
; grow line handle by enough room for 10 more lines (160 bytes). If we can't get it we are in real
; trouble. If we will exceed the 4k lines limit then abort.
addword #10,MaxLine,MaxLine
cmp #$0FFF
bge goabort
inc a
asl a
asl a
asl a
asl a
clc
adc #W_LineHeader
ldx #0
; Try to grow the line handle. If we succeed then save new line count in line handle and go back for
; next line. Else abort.
call D_MustGrowL,in=(ax:l,LineHand:l),out=(LinePtr:l),err=err
bcs goabort
moveword MaxLine,[LinePtr]
brl LineLoop
goabort brl abort
; Have successfully grown and filled line handle for the paragraph except for last line. Set offset
; for start of last line. Update the line count and pixel size for the paragraph.
DoneLoop movelong LinePtr,ax
ldy W_STLIne
iny
jsl W_GetLineRec
movelong ax,LineRec
subword LineBeg,ptr,[LineRec]
lda W_STLIne
inc a
moveword a,[ParRec]:#W_pLastLine
moveword pixels,[ParRec]:#W_pPixels
; Unlock the line and paragraph handles.
rcall D_Unlock,in=(LineHand:ax)
unlocktext rcall D_Unlock,in=([ParRec]:ax)
exit return
ENDP
*****************************************************************************************************
; W_ValidLines ( Paragraph:word )
;
; This routine is called to generate all the textual information for the given paragraph. If the
; paragraph is not a page break and its line handle has been purged then it will call MakeLines to
; do the actual work of rebuilding the line information for this paragraph.
W_ValidLines PROC EXPORT
;Using wpglobals
input par:w
local LineHand:l,parptr:l
error err
begin
; Get pointer to paragraph and see if its a page break. If so then its valid so exit.
stz err
rcall W_GetParRec,in=(par:a),out=(parptr:ax)
cmpw [parptr]:#W_pAttr,#W_PgBrk
beq exit
; Get line handle for paragraph. If no line handle exists or the handle has been purged then make
; new line information.
movelong [parptr]:#W_pLineHand,LineHand
cpzl LineHand
beq notvalid
cpzl [LineHand]
bne exit
; Line information is no longer valid call make lines to update it.
notvalid call W_MakeLines,in=(par:w),err=err
exit return
ENDP
*****************************************************************************************************
; W_CutLine ( )
;
; This routine is called to cut the line described in the following global variables:
;
; W_STFont word ; starting font
; W_STStyle byte ; starting style
; W_STSize byte ; starting font size
; W_STColor word ; starting text color
; W_STPtr long ; pointer to start of line text
; W_STLine word ; starting line
;
; The following globals will have been set on return from this routine:
;
; W_EndFont word ; ending font
; W_EndStyle byte ; ending style
; W_EndSize byte ; ending font size
; W_EndColor word ; ending text color
; W_EndPtr long ; pointer to end of line text
;
; W_MaxAscent word ; max ascent found in line
; W_MaxDescent word ; max descent found in line
; W_MaxLeading word ; max leading found in line
;
; W_JustPtr long ; pointer used for justification
; W_JustBits word ;
; W_JustSpaces word ; number of spaces to use for justify
; W_JustExtra long ; extra pixels to justify
W_CutLine PROC EXPORT
;Using wpglobals
local CurH:w,ChrPtr:l,LastH:w,lflag:w,lflag2:w,WasLastSp:w
local tFont:w,tstyle:w,tcolor:w,StringPtr:l
local tAscent:w,tDescent:w,tLeading:w
begin
; Setup default values for tFont/tStyle/tColor & EndFont/EndStyle/EndColor. Then select the font.
stz WasLastSp
lda W_STFont
sta tFont
sta W_EndFont
ldx W_STStyle
stx tstyle
stx W_EndStyle
ldy W_STColor
sty tcolor
sty W_EndColor
jsl D_SelectFont
; Get stats for current font.
jsl D_GetStats
sta W_MaxAscent
stx W_MaxDescent
sty W_MaxLeading
; Clear temp values for ascent, descent, and leading.
stz tAscent
stz tdescent
stz tleading
; Set flags so first character will determine height.
moveword #1,lflag
stz W_JustSpaces
stz lflag2
; Setup initial values of various pointers to be same as start of text.
movelong W_StPtr,ax
movelong ax,ChrPtr
movelong ax,W_JustPtr
movelong ax,W_EndPtr
; Get current horizontal position for the line and set last position to it as well.
lda W_STLIne
jsl W_GetLeft
sta CurH
sta LastH
; All flags and variables now initialized. Loop through characters in line adjusting pointers and
; global variables as we cut the line. If character is not one of the supported characters then
; branch else if special character jump to handler.
ChrLoop lda [ChrPtr]
and #$ff
cmp #SP
beq isspace
bcs RegChr
cmp #CR+1
bcc isspecial
brl BadChar
isspace brl HitSP
isspecial asl a
tax
jmp (ChrTable,x)
; Bad character detected in WP; used to die now will treat character as a normal character. Set gray
; border if developing to say we caught an old error and survived! Character will be changed to a
; DEL char.
BadChar
IF (Developing) THEN
setborder #3
ENDIF
lda #$FF
sta [ChrPtr]
; Regular character entered call check stuff to adjust values for ascent/descent/leading as needed.
; Make sure to preserve character in A-reg. Get width of character and adjust the current horizontal
; position.
RegChr pha
jsr CheckStuff
pla
jsl D_GetWdth
clc
adc CurH
sta CurH
; Check if current horizontal has exceeded the right margin. If not bump the character pointer and
; go back for next character.
chkright cmpw CurH,W_RightMargin
bcs pastmarg
incl ChrPtr
bra ChrLoop
; We have gone past the right margin. Check to see if the current character is a space; branch if
; not. Else check if last character was a space ( ie two spaces in a row ); if not just set last
; space to where last horizontal was and branch back to the character loop.
pastmarg lda [ChrPtr]
and #$ff
cmp #sp
bne NoEndSpace
lda WasLastSp
bne WrapExSpace
moveword LastH,WasLastSp
brl ChrLoop
; Comes here if two spaces were kept past the margin. Dont count space length before doing a regular
; word wrap. ( Extra space was wrapped ).
WrapExSpace moveword WasLastSp,LastH
bra RegWordWrap
; If start pointer is no longer same as end pointer then treat as regular word wrap.
NoEndSpace cmpw W_STPtr,W_EndPtr
bne RegWordWrap
; If no spaces on the line then use character that exceeded the right margin.
addlong #1,ChrPtr,W_EndPtr
movelong W_EndPtr,W_JustPtr
moveword CurH,LastH
moveword tAscent,W_MaxAscent
moveword tDescent,W_MaxDescent
moveword tLeading,W_MaxLeading
moveword tfont,W_EndFont
moveword tstyle,W_EndStyle
moveword tcolor,W_EndColor
; This is the regular word wrap exit. Just bits will get the number of pixels difference between
; the last seen horizontal position and the right margin. Check if we are in full justification
; mode. If so calculate the extra space that will be needed per blank to justify the line.
RegWordWrap subword W_RightMargin,LastH,W_JustBits
lda W_RulBits
and #W_r_full
beq killjust
; Check if single word on line ( just spaces <= 1 ). If so then zero extra justification space.
stzl W_JustExtra
cmpw W_JustSpaces,#2
blt exit
; At least two spaces exist on line so get justification amount needed for drawing line.
spacelong
pushword W_JustBits
lda W_JustSpaces
dec a
pha
_FixRatio
pullLong W_JustExtra
bra exit
; Move end pointer to just ptr for no justification.
killjust movelong W_EndPtr,W_JustPtr
exit return
;...................................................................................................;
; Check if ascent/descent/leading need to be changed. Iflag will be set when a change has been
; detected to font/style/size. Get the ascent/descent/size for the current font and adjust the
; running values if they are too small.
CheckStuff ldy lflag
beq NoHtChan
stz lflag
lda tfont
ldx tstyle
ldy tcolor
jsl D_SelectFont
jsl D_GetStats
cmp tAscent
bcc NotMaxA
sta tAscent
NotMaxA cpx tDescent
bcc NotMaxD
stx tDescent
NotMaxD cpy tLeading
bcc NoHtChan
sty tLeading
NoHtChan rts
;...................................................................................................;
; get new font and set both changed flags. bump character pointer by 3.
fChange moveword [ChrPtr]:#1,tFont
lda #3
bra bumpflags
;...................................................................................................;
; get new style and set both changed flags. bump character pointer by 2.
StyleChange ldy #1
lda [ChrPtr],y
shortm
sta tStyle
longm
bra bump2
;...................................................................................................;
; get new size and set both changed flags. bump character pointer by 2.
SizeChange ldy #1
lda [ChrPtr],y
shortm
sta tStyle+1
longm
bump2 lda #2
bra bumpflags
;...................................................................................................;
; get new color and set something changed flag. bump character pointer by 2.
ColorChange ldy #1
lda [ChrPtr],y
and #$ff
sta tColor
lda #2
bra bumpflag2
;...................................................................................................;
; set change flags and bump character pointer by value in A-reg.
bumpflags inc lflag
bumpflag2 inc lflag2
addwl a,ChrPtr
brl ChrLoop
;...................................................................................................;
; Tab character encountered. Bump current horizontal if not past right margin. Adjust justification
; values and cut line output variables.
HitTab jsr CheckStuff
addlong #1,ChrPtr,W_EndPtr
movelong W_EndPtr,W_JustPtr
; Get position of next tab. If zero is returned then tab would go past the right margin and we should
; treat the tab as carriage return for a soft line wrap, otherwise adjust current horizontal position.
call W_UseTab,in=(tfont:w,tstyle:w,tcolor:w,CurH:w,ChrPtr:l),out=(a:w)
jeq HitCr
sta CurH
; Tab found so clear number of justification spaces, and changed flag.
stz W_JustSpaces
stz lflag2
; Update the cut line out values. The current horizontal position is the last break position since
; we can break on tabs or spaces. If we were to break the max values for ascent/descent/leading
; would be the current running values and the font/style/color at the end of the line would be the
; current values.
moveword CurH,LastH
moveword tAscent,W_MaxAscent
moveword tDescent,W_MaxDescent
moveword tLeading,W_MaxLeading
moveword tfont,W_EndFont
moveword tstyle,W_EndStyle
moveword tcolor,W_EndColor
brl chkright
;...................................................................................................;
; Page/Date/Time width character encountered. Set pointer to string then do width.
PageWidth movelong #W_PageStr,StringPtr
bra DoWidth
DateWidth movelong #W_DateStr,StringPtr
bra DoWidth
TimeWidth movelong #W_TimeStr,StringPtr
DoWidth jsr CheckStuff
tool _StringWidth,in=(StringPtr:l),out=(a:w)
addword a,CurH,CurH
brl chkright
;...................................................................................................;
; Carriage return encountered. Set end pointer and justification pointer to location of carriage
; return.
HitCr movelong ChrPtr,ax
movelong ax,W_JustPtr
movelong ax,W_EndPtr
; Update ascent/descent/leading values if they have changed. Update ending font/style/color. Put
; difference between right margin and current horizontal position into just bits then exit. Note:
; last line of paragraphs is not justified ( this is what we want ).
lda tascent
ora tDescent
ora tLeading
beq MaxsOk
moveword tAscent,W_MaxAscent
moveword tDescent,W_MaxDescent
moveword tLeading,W_MaxLeading
MaxsOk moveword tfont,W_EndFont
moveword tstyle,W_EndStyle
moveword tcolor,W_EndColor
subword W_RightMargin,CurH,W_JustBits
brl exit
;...................................................................................................;
; Space detected. Increment the number of spaces count for justification. Point the end pointer just
; paste the space character. Set the last seen horizontal break location to the current horizontal
; position where the space was found.
HitSp inc W_JustSpaces
addlong #1,ChrPtr,W_EndPtr
moveword CurH,LastH
; If Iflag2 has not been set then no changes have occurred yet so skip setting new values, else clear
; the flag and set the latest return values.
lda lflag2
beq SkipStuff
stz lflag2
moveword tAscent,W_MaxAscent
moveword tDescent,W_MaxDescent
moveword tLeading,W_MaxLeading
moveword tfont,W_EndFont
moveword tstyle,W_EndStyle
moveword tcolor,W_EndColor
; Handle space as regular character at this point.
SkipStuff lda #sp
brl RegChr
;...................................................................................................;
; Routines to handle the character found. Note uses BadChar if character is undefined and HitSp if
; character is a space.
ChrTable DC.W BadChar,fChange ;0,1
DC.W styleChange,SizeChange ;2,3
DC.W ColorChange,PageWidth ;4,5
DC.W DateWidth,TimeWidth ;6,7
DC.W BadChar,HitTab ;8,9
DC.W BadChar,BadChar ;a,b
DC.W BadChar,HitCR ;c,d
ENDP
*****************************************************************************************************
; W_GetLRecPtr ( par:word, line:word ): LineRecPtr:ax
;
; This routine will return a pointer to the record for the given line of the given paragraph. If
; unable to validate lines for the paragraph then return error #-1.
W_GetLRecPtr PROC EXPORT
input par:w,line:w
local ParRec:l,Hand:l
output LineRec:l
error err
begin
stzl LineRec
call W_ValidLines,in=(par:w),err=err
bcs exit
rcall W_GetParRec,in=(par:a),out=(parrec:ax)
movelong [ParRec]:#W_pLineHand,Hand
ldy #2
lda [Hand],y
tax
lda [Hand]
ldy line
jsl W_GetLineRec
movelong ax,LineRec
exit return
ENDP
*****************************************************************************************************
; W_GetLineRec ( LinePtr:ax, Line:y ): LineRecPtr:ax
;
; This routine will return a pointer in A,X to the record for the given line. LinePtr points to
; the start of the line handle to be used.
W_GetLineRec PROC EXPORT
pha
tya
asl a
asl a
asl a
asl a
adc #W_LineHeader
clc
adc 1,s
bcc exit
inx
exit ply
rtl
ENDP
*****************************************************************************************************
; W_UseTab ( CurFont:word, CurStyle:word, CurColor:word, CurH:word, CurPtr:long ):NextH:word
;
; This routine will return horizontal position where placing text should continue given the
; current font/style/color horizontal position and a pointer to the text. If the tab places us past
; the right margin then return 0 for the next horizontal pixel position. CurH is where text up to
; CurPtr ends horizontally. CurPtr should point past the tab.
;
; CAUTION: This routine can change the current font
; NOTE: This routine assumes that the text block for the paragraph has been locked down.
W_UseTab PROC EXPORT
;Using wpglobals
input CurFont:w,CurStyle:w,CurColor:w,CurH:w,CurPtr:l
local xTab:w,CurTab:l,TextWidth:w,Room:w,StringPtr:l
local FontChange:w,Indent:w
output NextH:w
begin
; Clear return value and font change flag.
stz NextH
stz fontChange
jsr selectfont
; Check if center or right justification if so branch and treat tab as just another space.
lda W_RulBits
and #W_r_full+W_r_left
jeq MakeItSpace
; Get the number of tabs in ruler. If none then return with zero for horizontal, else get max tab
; offset.
lda W_NumTabs
jeq MakeCurH
asl a
asl a
sta xTab
; Find tab in table if not found then return with past right margin (0) value for NextH.
ldx #0
LookTab cmpw CurH,W_Tabs:x
bcc GetIndent
inx
inx
inx
inx
cpx xTab
bcc LookTab
brl exit
; Determine whether to use indent margin or left margin as a possible tab stop.
GetIndent moveword W_Indent,Indent
cmp W_LeftMargin
bge FoundTab
moveword W_LeftMargin,Indent
; Found tab. If current horizontal position is less than indent margin and indent margin is less than
; the tab we found then use indent margin instead of tab, else use tab position for CurTab.
FoundTab cmpw CurH,Indent
bge NoUseIndent
cmpw Indent,W_Tabs:x
bge NoUseIndent
moveword Indent,CurTab
stz CurTab+2
bra GotCurTab
NoUseIndent movelong W_Tabs:x,CurTab
; Check if found tab position will extend past the current right margin if so just return with 0 for
; NextH.
GotCurTab cmpw CurTab,W_RightMargin
jge exit
; Set NextH to found tab position. If tab is a left tab then we are done. If tab is decimal or right
; tab we still have some work to do.
moveword CurTab,NextH
lda CurTab+2
jeq exit
; Point to next character. Determine how much room exists between the tab and the current horizontal
; position. Clear text width so far accumulated.
incl CurPtr
subword CurTab,CurH,Room
stz TextWidth
; Main character loop. Check if decimal found (for decimal tabs). If not then branch to handle char.
; If period found and decimal tab then adjust for the tab and exit, else treat the period as a
; regular character.
ChrLoop lda [CurPtr]
and #$ff
cmp #'.'
bne noPer
ldy CurTab+2
bpl RegChr
brl AdjustTab
; Check if character is valid, special character, or bad character and branch to the correct
; handler.
NoPer cmp #sp
bcs RegChr
cmp #cr+1
bcs badchar
UseTable asl a
tax
jmp (ChrTable,x)
; Bad character detected in WP; used to die now will treat character as a normal character. Set gray
; border if developing to say we caught an old error and survived! Character will be changed to a
; DEL char.
BadChar
IF (Developing) THEN
setborder #3
ENDIF
lda #$FF
sta [CurPtr]
; Regular character encountered. If font changes have been detected then select font before getting
; width of character. Get width of character and add it to the running text width. If width exceeds
; the room available then simply return with the tab position as found, else point to next character
; and go back for more.
RegChr pha
lda FontChange
beq NoSelf
jsr selectfont
NoSelf pla
jsl D_GetWdth
clc
adc TextWidth
sta TextWidth
GotTW cmp Room
bge MakeCurH
incl CurPtr
brl ChrLoop
; Tab character encountered. Make sure current font selected. If we ran out of room before the tap
; then return with NextH set to zero. Else return with NextH = CurH + (Room-TextWidth).
AdjustTab jsr selectfont
lda Room
sec
sbc TextWidth
bmi exit
clc
adc CurH
sta NextH
bra exit
; Treat the tab as a space character. Get the width of a space character and set NextH accordingly,
; unless it will exceed the right margin in which case we should return zero.
MakeItSpace lda #sp
jsl D_GetWdth
addword a,CurH,a
cmp W_RightMargin
bcs MakeCurH
sta NextH
bra exit
; Set return value to current horizontal value and return to caller.
MakeCurH moveword CurH,NextH
exit jsr selectfont
return
;...................................................................................................;
; get new font and bump character pointer by 3.
FChange ldy #1
lda [CurPtr],y
sta CurFont
lda #3
bra bumpptr
;...................................................................................................;
; get new size and bump character pointer by 2.
SizeChange ldy #1
lda [CurPtr],y
shortm
sta CurStyle+1
longm
bra bumpby2
;...................................................................................................;
; get new style and bump character pointer by 2.
StyleChange ldy #1
lda [CurPtr],y
shortm
sta CurStyle
longm
bra bumpby2
;...................................................................................................;
; get new color and bump character pointer by 2.
ColorChange ldy #1
lda [CurPtr],y
and #$ff
sta CurColor
bumpby2 lda #2
;...................................................................................................;
bumpptr addwl a,CurPtr
moveword #1,FontChange
brl ChrLoop
;...................................................................................................;
; Page/Date/Time width character encountered. Set pointer to string then do width.
PageWidth movelong #W_PageStr,StringPtr
bra DoWidth
DateWidth movelong #W_DateStr,StringPtr
bra DoWidth
TimeWidth movelong #W_TimeStr,StringPtr
DoWidth tool _StringWidth,in=(StringPtr:l),out=(a:w)
addword a,TextWidth,TextWidth
brl GotTW
;...................................................................................................;
; Select the current font, style, and color.
selectfont rcall D_SelectFont,in=(CurFont:a,CurStyle:x,CurColor:y)
rts
;...................................................................................................;
ChrTable DC.W BadChar,FChange ;0,1
DC.W StyleChange,SizeChange ;2,3
DC.W ColorChange,PageWidth ;4,5
DC.W DateWidth,TimeWidth ;6,7
DC.W BadChar,AdjustTab ;8,9
DC.W BadChar,BadChar ;a,b
DC.W BadChar,AdJustTab ;c,d
;...................................................................................................;
ENDP
*****************************************************************************************************
; W_CalcLineHeight ( LineRecPtr:ax ): Height:a, Descent:x
;
; This routine will return the height and descent for the given line. The routine will take into
; account the current line spacing.
W_CalcLineHeight PROC EXPORT
;Using wpglobals
;Using D_GlobalData
ptr equ 0
W_Leading equ 4
W_HeightNL equ 6
height equ 8
descent equ 10
tay
phd
lda >D_MainZPage
tcd
sty ptr
stx ptr+2
moveword [ptr]:#W_lHeight,W_HeightNL
addword [ptr]:#W_lLeading,W_HeightNL,height
moveword [ptr]:#W_lDescent,descent
lda W_RulBits
and #W_r_single
bne exit
lda W_HeightNL
lsr a
addword a,height,height
lda W_RulBits
and #W_r_double
bne exit
lda W_HeightNL
lsr a
addword a,height,height
exit lda height
ldx descent
pld
rtl
ENDP
*****************************************************************************************************
; W_FindFont ( par:word, line:word, offset:word ): font:long, color:word
;
; This routine will return font and color for the given paragraph line and the given offset.
;
; NOTE: This routine will return an error if GetLRecPtr can not get a pointer to the line record.
W_FindFont PROC EXPORT
;Using wpglobals
input Par:w,line:w,offset:w
local LineRec:l,StartPtr:l,MaxLook:w,ParRec:l
output font:l,color:w
error err
begin
; Get pointer to paragraph record.
stz err
rcall W_GetParRec,in=(par:a),out=(parrec:ax)
; If paragraph is a page break then look at next paragraph line 0 to get the font and color.
cmpw [ParRec]:#W_pAttr,#W_PgBrk
bne NotPB
inc par
stz line
moveword #W_TextHeader,offset
; Get pointer to line record for the given paragraph line. From the line record extract the default
; font, style, and color to use for the line.
NotPB call W_GetLRecPtr,in=(par:w,line:w),out=(LineRec:l),err=err
jcs exit
moveword [LineRec]:#W_lFont,font
moveword [LineRec]:#W_lStyle,font+2 ;STYLE
moveword [LineRec]:#W_lColor,color
; Get pointer to start of line text.
moveword [LineRec]:#W_lOffset,x
stx MaxLook
lda par
jsl W_GetAddr
movelong ax,StartPtr
; Determine maximum number of character we wish to look at by subtracting the given offset into the
; line from the starting offset of the line in the text block.
subword offset,MaxLook,MaxLook
; Until we get to the point in the line that we want accumulate font/style/color changes.
ldy #0
ChrLoop cpy MaxLook
jcs exit
lda [StartPtr],y
and #$ff
iny
cmp #sp
bcs ChrLoop
cmp #cr+1
bcs BadChar
asl a
tax
jmp (ChrTable,x)
; Bad character detected in WP; used to die now will treat character as a normal character. Set gray
; border if developing to say we caught an old error and survived! Character will be changed to a
; DEL char.
BadChar
IF (Developing) THEN
setborder #3
ENDIF
dey
lda #$FF
sta [StartPtr],y
iny
bra Chrloop
; Font change encountered. Save new running font and point Y-reg past font info.
FChange lda [StartPtr],y
sta Font
iny
iny
brl ChrLoop
; Size change encountered. Save new running size and point Y-reg past size info.
SizeChange lda [StartPtr],y
shortm
sta Font+3
longm
iny
brl ChrLoop
; Style change encountered. Save new running style and point Y-reg past style info.
StyleChange lda [StartPtr],y
shortm
sta Font+2
longm
iny
brl ChrLoop
; Color change encountered. Save new running color and point Y-reg past color info.
ColorChange lda [StartPtr],y
and #$ff
sta color
iny
brl ChrLoop
exit return
;...................................................................................................;
ChrTable DC.W BadChar,FChange ;0,1
DC.W StyleChange,SizeChange ;2,3
DC.W ColorChange,ChrLoop ;4,5
DC.W ChrLoop,ChrLoop ;6,7
DC.W BadChar,ChrLoop ;8,9
DC.W BadChar,BadChar ;a,b
DC.W BadChar,ChrLoop ;c,d
;...................................................................................................;
ENDP
*****************************************************************************************************
; W_ReadFont ( font:long, color:word, StartPtr:long, EndPtr:long ): font:long, color:word
;
; This routine will return font and color for the text between the two given pointers.
W_ReadFont PROC EXPORT
input InFont:l,InCol:w,StartPtr:l,Ptr2:l
local MaxLook:w
output font:l,color:w
begin
; Initialize starting font and color from inputs and determine maximum number of characters to be
; examined.
movelong InFont,font
moveword InCol,color
subword Ptr2,StartPtr,MaxLook
; Until we get to the point in the line that we want accumulate font/style/color changes.
ldy #0
ChrLoop cpy MaxLook
jcs exit
lda [StartPtr],y
and #$ff
iny
cmp #sp
bcs ChrLoop
cmp #cr+1
bcs BadChar
asl a
tax
jmp (ChrTable,x)
; Bad character detected in WP; used to die now will treat character as a normal character. Set gray
; border if developing to say we caught an old error and survived! Character will be changed to a
; DEL char.
BadChar
IF (Developing) THEN
setborder #3
ENDIF
dey
lda #$FF
sta [StartPtr],y
iny
bra Chrloop
; Font change encountered. Save new running font and point Y-reg past font info.
FChange lda [StartPtr],y
sta Font
iny
iny
brl ChrLoop
; Size change encountered. Save new running size and point Y-reg past size info.
SizeChange lda [StartPtr],y
shortm
sta Font+3
longm
iny
brl ChrLoop
; Style change encountered. Save new running style and point Y-reg past style info.
StyleChange lda [StartPtr],y
shortm
sta Font+2
longm
iny
brl ChrLoop
; Color change encountered. Save new running color and point Y-reg past color info.
ColorChange lda [StartPtr],y
and #$ff
sta color
iny
brl ChrLoop
exit return
;...................................................................................................;
ChrTable DC.W BadChar,FChange ;0,1
DC.W StyleChange,SizeChange ;2,3
DC.W ColorChange,ChrLoop ;4,5
DC.W ChrLoop,ChrLoop ;6,7
DC.W BadChar,ChrLoop ;8,9
DC.W BadChar,BadChar ;a,b
DC.W BadChar,ChrLoop ;c,d
;...................................................................................................;
ENDP
*****************************************************************************************************
; W_UpdateLines ( par:word, line:word, amount:word )
;
; This routine will add the given amount to the offset into the text block of every line after the
; given line. ( useful for inserting text on the line and keeping all the other lines correct ).
;
; Note: Can return an error if valid lines fails.
W_UpdateLines PROC EXPORT
input par:w,line:w,amount:w
local ParRec:l,LineRec:l,LineHand:l,lines:w
error err
begin
; Make sure line handle contains valid lines for the given paragraph. If error then abort and hope
; for the best.
call W_ValidLines,in=(par:w),err=err
jcs exit
; Get pointer to paragraph record. Get number of lines in the paragraph. Get pointer to the given
; line's record.
rcall W_GetParRec,in=(par:a),out=(ParRec:ax)
moveword [ParRec]:#W_pLastLine,lines
movelong [ParRec]:#W_pLineHand,LineHand
movelong [LineHand],LineRec
rcall W_GetLineRec,in=(LineRec:ax,line:y),out=(LineRec:ax)
; Add amount to each line's offset after the given line.
ldy #W_lOffset
Loop inc line
tya
clc
adc #W_lBytes
tay
addword Amount,[LineRec]:y,[LineRec]:y
cmpw line,lines
bcc Loop
exit return
ENDP
*****************************************************************************************************
; W_CutLine2 ( par:word, line:word )
;
; This routine will setup the entry values to CutLine for the given line and paragraph and then
; will call CutLine to determine where the given paragraph line should be cut and what its end line
; attributes are. (see CutLine for more details)
;
; NOTE: This routine can return an error if the line handle does not exist for the paragraph.
W_CutLine2 PROC EXPORT
;Using wpglobals
input par:w,line:w
local ptr:l,LineHand:l,LineRecPtr:l
error err
begin
; Get pointer to current paragraph record and put its ruler info in the ruler globals.
moveword #1,err
rcall W_GetParRec,in=(par:a),out=(ptr:ax)
rcall W_ReadRuler,in=([ptr]:#W_pRulerHand:ax)
; Make sure line handle exists else return with error set.
movelong [ptr]:#W_pLineHand,LineHand
cpzl LineHand
jeq exit
ldy #2
lda [LineHand]
ora [LineHand],y
jeq exit
stz err
; Set starting font/style/color and starting ptr/line values for cutline to use. If line handle does
; not exist or has been purged then return with error set.
rcall W_GetLineRec,in=([LineHand]:ax,line:y),out=(LineRecPtr:ax)
moveword [LineRecPtr]:#W_lFont,W_STFont
moveword [LineRecPtr]:#W_lStyle,W_STStyle
moveword [LineRecPtr]:#W_lColor,W_STColor
moveword [LineRecPtr]:#W_lOffset,a
tax
lda par
jsl W_GetAddr
movelong ax,W_STPtr
moveword line,W_STLIne
; Set just ptr and end ptr to start of next line.
moveword [LineRecPtr]:#W_lOffset+W_lBytes,a
tax
lda par
jsl W_GetAddr
movelong ax,W_JustPtr
movelong ax,W_EndPtr
; Cut line to do the actual work of determining where this paragraph line should be cut.
jsl W_CutLine
exit return
ENDP
*****************************************************************************************************
; W_GetLineAddr ( par:word, line:word ) ptr:long
;
; This routine will return a pointer to the start of the given paragraph line's text.
;
; Note: This routine can return an error if ValidLines fails.
W_GetLineAddr PROC EXPORT
input par:w,line:w
local ptr:l,LineHand:l,LinePtr:l
output LineAddr:l
error err
begin
; Make sure paragraph lines are valid. If can't make lines valid we're in trouble error on up.
call W_ValidLines,in=(par:w),err=err
jcs exit
; Get pointer to start of line's text.
rcall W_GetParRec,in=(par:a),out=(ptr:ax)
movelong [ptr]:#W_pLineHand,LineHand
movelong [LineHand],LinePtr
rcall W_GetLineRec,in=(LinePtr:ax,Line:y),out=(ptr:ax)
moveword [ptr]:#W_lOffset,x
lda par
jsl W_GetAddr
movelong ax,LineAddr
exit return
ENDP
*****************************************************************************************************
; W_GetEndLine ( par:word, line:word ): offset:word
; W_GetLineOffset ( par:word, line:word ): offset:word
; W_GetBegLine ( par:word, line:word ): offset:word
;
; The following shared code is used by the above three routines to return the requested offset
; into the given paragraph line's text.
;
; Note: These routine can return errors if the paragraph line handle could not be validated.
W_GetEndLine PROC EXPORT
EXPORT W_GetLineOffset
EXPORT W_GetBegLine
; Get end by bumping line count first to next line.
lda 4,s
inc a
sta 4,s
W_GetLineOffset
W_GetBegLine
input par:w,line:w
local ptr:l,LineHand:l,LinePtr:l
output offset:w
error err
begin
; Make sure that valid line handle exists for this paragraph. If we can't make a valid line handle
; then we are in serious trouble pass the error on up.
call W_ValidLines,in=(par:w),err=err
bcs exit
; Get offset for the given line from its line record information.
rcall W_GetParRec,in=(par:a),out=(ptr:ax)
movelong [ptr]:#W_pLineHand,LineHand
movelong [LineHand],LinePtr
rcall W_GetLineRec,in=(LinePtr:ax,Line:y),out=(ptr:ax)
moveword [ptr]:#W_lOffset,offset
exit return
ENDP
*****************************************************************************************************
; W_NextLine ( par:word, line:word ) par:word, line:word
;
; This routine will return the paragraph and line for the line following the given paragraph line.
; An error will be returned if this is already the last line of the last paragraph.
W_NextLine PROC EXPORT
;Using wpglobals
input par:w,line:w
output OPar:w,OLine:w
local ParRec:l
error err
begin
; Bump line count. If it the given paragraph has enough lines we're done.
stz err
moveword par,OPar
moveword line,OLine
inc OLine
rcall W_GetParRec,in=(par:a),out=(ParRec:ax)
cmpw Oline,[ParRec]:#W_pLastLine
bcc exit
; Else bump the paragraph count. If we were already on the last paragraph then return error set.
inc OPar
stz OLine
cmpw W_LastP,OPar
bcs exit
inc err
exit return
ENDP
END