home *** CD-ROM | disk | FTP | other *** search
- ;/**************************************************************************/
- ;/* */
- ;/* Copyright (c) 1991 Primatech Inc. */
- ;/* */
- ;/* All Rights Reserved */
- ;/* */
- ;/**************************************************************************/
-
- ;/*------------------------------------------------------------*/
- ;/* filename - wrap.asm */
- ;/* */
- ;/* function(s) */
- ;/* TEditor::doWordWrapBuffer */
- ;/*------------------------------------------------------------*/
-
- ;Created: 12 November 1991 by Jeffrey A. Hottle
-
-
- IDEAL
- JUMPS
- MODEL LARGE, PROLOG
-
- INCLUDE "TVWRITE.INC"
-
- PUBLIC @TEditor@doWordWrapBuffer$qususns
-
- EXTRN @TEditor@changeBufSize$qs:PROC
-
- CR = 0Dh
- LF = 0Ah
-
- CODESEG
-
- MACRO AdvancePtr
- LOCAL @@OK
- inc BX
- cmp BX,[ES:DI+TEditorCurPtr]
- jne @@OK
- add BX,[ES:DI+TEditorGapLen]
- @@OK:
- ENDM
-
-
-
- ;ushort TEditor::doWordWrapBuffer( ushort start_ofs,
- ; ushort min_chars,
- ; int* line_delta )
- ;assume:
- ; line_delta is initialized
- ; start_ofs is beginning of a line
- ; at least 2 lines or min_chars will be processed
- ;
- PROC @TEditor@doWordWrapBuffer$qususns
-
- ARG thisPtr:FAR PTR, StartOfs:WORD, MinChars:WORD, LineDelta:PTR WORD
- USES DS,SI,DI
- LOCAL Delta:WORD, CharCt:WORD, LineCt:WORD, RealDS:WORD
- LOCAL BufChg:BYTE, LineChg:BYTE, LineStart:WORD, DelLastCR:BYTE
- LOCAL WrapPos:WORD, WrapDX:WORD, WrapCharCt:WORD
-
- ASSUME DS:nothing, ES:nothing
-
- xor AX,AX
- mov [Delta],AX
- mov [CharCt],AX
- mov [LineCt],AX
- mov [BufChg],AL
-
- mov [RealDS],DS ;save original DATASEG
-
- les DI,[thisPtr]
- lds SI,[ES:DI+TEditorBuffer] ;DS:SI = buffer
- mov BX,[StartOfs]
-
- ; update BX if it is sitting at the start of the gap
- cmp BX,[ES:DI+TEditorCurPtr]
- jne ScanLine
- add BX,[ES:DI+TEditorGapLen]
-
- ScanLine:
- ;----------------------------------
- ; scan to find line break position
- ;----------------------------------
- xor DX,DX ;DH = CR count, DL = previous buffer char
- xor CX,CX ;CX = current x position
- cld
- xor AX,AX
- mov [LineChg],AL
- mov [DelLastCR],AL
- mov [WrapPos],AX
- mov [LineStart],BX
- jmp short ScanSkip
- ScanNext:
- mov AH,AL ;save previous line character
- AdvancePtr ;advance pointer
- ScanSkip:
- mov DL,AL ;save previous buffer character
- cmp BX,[ES:DI+TEditorBufSize];check for end of buffer
- jae BufEnd
- inc CX ;advance column number
- inc [CharCt]
- mov AL,[SI+BX] ;get character from buffer
- cmp AL,CR ;is this character a CR?
- jne NotCR
- AdvancePtr
- cmp [BYTE PTR SI+BX],LF ;yes, is it CR+LF? (hard return)
- jne JustCR
- AdvancePtr ;hard return, skip LF
- inc [CharCt]
- jmp DelAllCR ;remove all soft returns from this line
- JustCR:
- inc DH ;bump soft-return count
- dec CX ;don't count this as a column
- jmp ScanSkip
- NotCR:
- cmp AL,' ' ;check for space
- je ScanNext
-
- cmp AH,' ' ;non-space, check prev for space or hyphen
- je SetBreak
- cmp AH,'-'
- je SetBreak
-
- cmp CX,[ES:DI+TEditorRMargin];no break here, check if past end of line
- jbe ScanNext ;not past end
-
- cmp [WrapPos],0 ;past end, have we found a break yet?
- jnz BreakPos ;yes
- jmp BreakPosGo ;no, use this position
-
- SetBreak:
- mov [WrapPos],BX
- mov [WrapDX],DX
- push AX
- mov AX,[CharCt]
- mov [WrapCharCt],AX
- pop AX
- cmp CX,[ES:DI+TEditorRMargin];is this the end of the line?
- jbe ScanNext ;no
-
- ;---------------------------------------------------------
- ; break position found, check if line already breaks here
- ;---------------------------------------------------------
- BreakPos:
- mov BX,[WrapPos] ;set current pointer back to wrap position
- mov DX,[WrapDX] ;get previous buffer char & CR count
- mov AX,[WrapCharCt] ;set proper character count
- mov [CharCt],AX
- BreakPosGo:
- dec [CharCt] ;adjust count for character after the break
- cmp DH,1 ;check for 1 CR found
- jne FixBuffer
- cmp DL,CR ;check if CR is previous char in buffer
- je NextLine ;it is, no change to buffer needed
- jmp FixBuffer
-
- ;----------------------------------------
- ; end of buffer, remove all soft returns
- ;----------------------------------------
- BufEnd:
- or DH,DH ;any soft-returns in this line?
- jz Success ;no, we're done
-
- ;--------------------------------------
- ; remove all soft returns in this line
- ;--------------------------------------
- DelAllCR:
- mov [DelLastCR],1
-
- ;----------------------------------------------------------------
- ; update buffer removing soft returns, setting new one if needed
- ;----------------------------------------------------------------
- FixBuffer:
- mov CX,BX ;save ending position
- or DH,DH ;are there any CRs?
- jz NoCR
- mov BX,[LineStart] ;get start-of-line position
- FindCR:
- cmp [BYTE PTR SI+BX],CR ;is this character a CR?
- je FoundCR
- AdvancePtr ;no, try next character
- jmp FindCR
- FoundCR:
- dec DH ;adjust CR count
- jnz DeleteIt ;not last one yet
- cmp [DelLastCR],0 ;delete last CR?
- jz LastCR
- DeleteIt:
- dec [Delta] ;adjust line delta value
- mov [LineChg],1
- mov [BufChg],1
-
- ; compress text at BX, updating ptr in CX and other object pointers
- call CompressBuf
- or DH,DH
- jnz FindCR
-
- LastCR:
- ; shift text (if needed) to put CR at end of line
- cmp [DelLastCR],0 ;do we want a CR on this line?
- jnz RightPlace ;no
- cmp DL,CR ;check if we have a CR in the right place
- je RightPlace
-
- ; shift text at BX thru CX and put CR in the hole
- mov [LineChg],1
- mov [BufChg],1
- call ShiftBuf
- mov BX,CX ;put CR in the hole
- mov [BYTE PTR SI+BX],CR
- AdvancePtr ;skip over that location
- jmp NextLine
-
- NoCR:
- cmp [DelLastCR],0 ;do we want a CR on this line?
- jnz RightPlace ;no
-
- ; expand buffer at end and insert CR in hole
- mov BX,CX
- mov AX,[RealDS]
- call ExpandBuf
- or AX,AX ;check for expand failure
- jz Failure
- mov [LineChg],1
- mov [BufChg],1
- inc [Delta] ;adjust line delta value
- mov [BYTE PTR SI+BX],CR
-
- RightPlace:
- mov BX,CX ;recover end-of-line pointer
-
- ;-----------------------------
- ; process next line if needed
- ;-----------------------------
- NextLine:
- inc [LineCt]
- cmp [LineCt],2 ;must do at least 2 lines
- jb ScanLine
- mov AX,[CharCt] ;must process at least MinChars characters
- cmp AX,[MinChars]
- jb ScanLine
- cmp [LineChg],0 ;trickle down if needed
- jz Success
- jmp ScanLine
-
- Failure:
- mov AX,wwsError ;failure return value
- jmp short Exit
- Success:
- mov AX,wwsNoWrap ;assume nothing happened
- cmp [BufChg],0
- jz Exit
- mov AX,wwsDidWrap ;something happened
- Exit:
- lds BX,[LineDelta] ;adjust line count
- mov CX,[Delta]
- add [BX],CX
-
- ret
-
- ENDP
-
-
- PROC NOLANGUAGE DecreasePtr NEAR
- push AX
- mov AX,[ES:DI+TEditorCurPtr]
- add AX,[ES:DI+TEditorGapLen]
- cmp BX,AX
- jne DecreaseOK
- sub BX,[ES:DI+TEditorGapLen]
- DecreaseOK:
- dec BX
- pop AX
- ret
- ENDP
-
-
- ;-----------------------------------------------------
- ; compress buffer (DS:SI) by removing character at BX
- ; updates pointer CX and various object data elements
- ; in: ES:DI = thisPtr
- ; DS:SI = buffer
- ; BX = pointer to character to remove
- ; CX = pointer to update
- ; out: BX points to character after deleted character
- ; CX updated if needed
- ; all others unchanged
- ;-----------------------------------------------------
- PROC NOLANGUAGE CompressBuf NEAR
-
- push AX
- push DX
-
- cmp BX,[ES:DI+TEditorCurPtr]
- jae CompressAfter
-
- ;-------------------------
- ; compress before the gap
- ;-------------------------
- push SI
- push DI
- push ES
- push CX
- mov CX,[ES:DI+TEditorCurPtr] ;compute length to move
- dec CX
- sub CX,BX
- add SI,BX ;set source and destination
- mov DI,SI
- inc SI
- push DS
- pop ES
- rep movsb ;shift the data
- pop CX
- pop ES
- pop DI
- pop SI
-
- ; convert BX and CX to data offsets
- call DataOfs
- xchg BX,CX
- call DataOfs
- xchg BX,CX
- mov DX,[ES:DI+TEditorBufLen]
-
- ; update object data elements
- inc [WORD PTR ES:DI+TEditorGapLen]
- dec [WORD PTR ES:DI+TEditorBufLen]
- dec [WORD PTR ES:DI+TEditorCurPtr]
-
- ; adjust insCount if needed
- mov AX,[ES:DI+TEditorCurPtr]
- sub AX,[ES:DI+TEditorInsCount]
- cmp AX,BX
- sbb [WORD PTR ES:DI+TEditorInsCount],0 ;dec InsCount if it does
-
- ; adjust pointers
- mov AX,-1 ;adjustment amount
- inc BX ;low end to adjust (DX is high end)
- call AdjustPointers ;adjust pointers CX, SelStart, SelEnd
- dec BX
-
- ; convert BX & CX back into buffer offsets
- call BufferOfs
- xchg BX,CX
- call BufferOfs
- xchg BX,CX
- jmp CompressDone
-
- ;------------------------
- ; compress after the gap
- ;------------------------
- CompressAfter:
- push SI
- push DI
- push ES
- push CX
- mov AX,[ES:DI+TEditorCurPtr] ;get pointer to first deleted character
- add AX,[ES:DI+TEditorGapLen]
- sub AX,[ES:DI+TEditorDelCount]
- mov CX,BX ;compute length to move
- sub CX,AX
- add SI,BX ;set source and destination
- mov DI,SI
- dec SI
- push DS
- pop ES
- std ;move backward for this
- rep movsb ;shift the data
- cld
- pop CX
- pop ES
- pop DI
- pop SI
-
- ; set data offsets of BX and CX pointers
- call DataOfs
- xchg BX,CX
- call DataOfs
- xchg BX,CX
-
- ; update object data elements
- mov AX,-1 ;adjustment amount
- mov DX,[ES:DI+TEditorBufLen] ;high end to adjust
- inc BX ;low end to adjust
- call AdjustPointers ;adjust pointers CX, SelStart, SelEnd
- dec BX
-
- inc [WORD PTR ES:DI+TEditorGapLen]
- dec [WORD PTR ES:DI+TEditorBufLen]
-
- ; change BX & CX back to buffer offsets
- call BufferOfs
- xchg BX,CX
- call BufferOfs
- xchg BX,CX
-
- CompressDone:
- pop DX
- pop AX
- ret
-
- ENDP
-
-
- ;--------------------------------------------------------
- ; expand buffer (DS:SI) before character at pointer BX
- ; updates pointer CX and various object data elements
- ; in: ES:DI = thisPtr
- ; DS:SI = buffer
- ; AX = original DS
- ; BX = pointer to expand location
- ; CX = pointer to update
- ; out: AX = 0 on failure
- ; DS:SI = new buffer location
- ; BX points to new character, but updated if needed
- ; CX updated if needed
- ; all others unchanged
- ;--------------------------------------------------------
- PROC NOLANGUAGE ExpandBuf NEAR
-
- push DX
-
- ;-------------------------------
- ; check if buffer is big enough
- ;-------------------------------
- mov DX,[ES:DI+TEditorGapLen]
- cmp DX,[ES:DI+TEditorDelCount]
- ja BufSizeOK
- mov DS,AX ;restore real DS for this function
- call GrowBuffer ;returns new buffer location in DS:SI
- or AX,AX ;check for failure
- jz ExpandDone ;failure
-
- ;-----------------------------------------------
- ; check if expansion is before or after the gap
- ;-----------------------------------------------
- BufSizeOK:
- cmp BX,[ES:DI+TEditorCurPtr]
- jae ExpandAfter
-
- ;-----------------------
- ; expand before the gap
- ;-----------------------
- push SI
- push DI
- push ES
- push CX
- mov CX,[ES:DI+TEditorCurPtr]
- add SI,CX ;set source and destination
- mov DI,SI
- dec SI
- push DS
- pop ES
- sub CX,BX ;compute length to move
- std ;move backward for this
- rep movsb ;shift the data
- cld
- pop CX
- pop ES
- pop DI
- pop SI
-
- ; convert BX and CX to data offsets
- call DataOfs
- xchg BX,CX
- call DataOfs
- xchg BX,CX
- mov DX,[ES:DI+TEditorBufLen]
-
- ; adjust insCount if needed
- mov AX,[ES:DI+TEditorCurPtr]
- sub AX,[ES:DI+TEditorInsCount]
- cmp AX,BX
- adc [WORD PTR ES:DI+TEditorInsCount],0 ;inc InsCount if it does
-
- dec [WORD PTR ES:DI+TEditorGapLen]
- inc [WORD PTR ES:DI+TEditorBufLen]
- inc [WORD PTR ES:DI+TEditorCurPtr]
-
- ; adjust pointers
- mov AX,1 ;adjustment amount
- call AdjustPointers ;adjust pointers CX, SelStart, SelEnd
-
- ; change BX & CX back to buffer offsets
- call BufferOfs
- xchg BX,CX
- call BufferOfs
- xchg BX,CX
- jmp ExpandDone ;NOTE: AX still non-0 from above
-
- ;----------------------
- ; expand after the gap
- ;----------------------
- ExpandAfter:
- push SI
- push DI
- push ES
- push CX
- mov AX,[ES:DI+TEditorCurPtr] ;get ptr to char before 1st deleted char
- add AX,[ES:DI+TEditorGapLen]
- sub AX,[ES:DI+TEditorDelCount]
- dec AX
- mov CX,BX ;compute length to move
- sub CX,AX
- add SI,AX ;set source and destination
- mov DI,SI
- inc SI
- push DS
- pop ES
- rep movsb ;shift the data
- pop CX
- pop ES
- pop DI
- pop SI
-
- ; convert BX and CX to data offsets
- call DataOfs
- xchg BX,CX
- call DataOfs
- xchg BX,CX
- mov DX,[ES:DI+TEditorBufLen]
-
- ; update object data elements
- dec [WORD PTR ES:DI+TEditorGapLen]
- inc [WORD PTR ES:DI+TEditorBufLen]
-
- ; adjust pointers
- mov AX,1 ;adjustment amount
- call AdjustPointers ;adjust pointers CX, SelStart, SelEnd
-
- ; change BX & CX back to buffer offsets
- call BufferOfs
- xchg BX,CX
- call BufferOfs
- xchg BX,CX
-
- ;NOTE: AX still non-0 from above (success return value)
-
- ExpandDone:
- pop DX
- ret
-
- ENDP
-
-
- ;----------------------------------------------------------------
- ; shift text in buffer (from BX+1 thru CX)
- ; in: ES:DI = thisPtr
- ; DS:SI = buffer
- ; BX = pointer to location to overwrite
- ; CX = pointer to ending location
- ; out: BX = updated but still points to start of affected area
- ; CX = pointer to the hole
- ; various object data members changed
- ;----------------------------------------------------------------
- PROC NOLANGUAGE ShiftBuf NEAR
-
- push AX
- push DX
-
- mov AX,[ES:DI+TEditorCurPtr]
- cmp BX,AX
- jae ShiftAfter ;all shifting occurs after gap
-
- ShiftBefore:
- ;---------------------------
- ; adjust InsCount if needed
- ;---------------------------
- mov DX,AX ;compute start of inserted area
- sub DX,[ES:DI+TEditorInsCount]
- cmp BX,DX ;check if BX in inserted area
- jb @@NotBX
- dec [WORD PTR ES:DI+TEditorInsCount]
- @@NotBX:
- cmp CX,AX ;check if CX in inserted area
- jae @@NotCX
- cmp CX,DX
- jb @@NotCX
- inc [WORD PTR ES:DI+TEditorInsCount]
- @@NotCX:
-
- ;--------------------------
- ; shift portion before gap
- ;--------------------------
- push CX ;save ending offset
- cmp CX,AX
- jb AllBefore
- dec AX
- mov [ES:DI+TEditorCurPtr],AX
- mov CX,AX ;fake ending offset for this part
- inc AX ;leave old value in AX
- AllBefore:
- push ES
- push SI
- push DI
- push CX
- sub CX,BX ;set move length
- add SI,BX ;set source and destination
- mov DI,SI
- inc SI
- push DS
- pop ES
- rep movsb ;move the data
- pop CX
- pop DI
- pop SI
- pop ES
-
- pop DX ;recover real ending pointer
- cmp CX,DX ;check if entire shift was before gap
- je ShiftAdj ;it was
- mov CX,DX ;was not, set real ending pointer
-
- ;-----------------------------
- ; shift portion after the gap
- ;-----------------------------
- ShiftAfter:
- push BX ;save real starting offset
- cmp BX,AX ;AX still old value of CurPtr from above
- jae AllAfter
- mov BX,AX ;fake starting offset for this part
- add BX,[ES:DI+TEditorGapLen]
- sub BX,[ES:DI+TEditorDelCount]
- dec BX
- AllAfter:
- push ES
- push SI
- push DI
- push CX
- sub CX,BX ;set move length
- add SI,BX ;set source and destination
- mov DI,SI
- inc SI
- push DS
- pop ES
- rep movsb ;move the data
- pop CX
- pop DI
- pop SI
- pop ES
-
- pop BX ;recover real starting offset
-
- ;----------------------------------
- ; adjust pointers to affected text
- ;----------------------------------
- ShiftAdj:
-
- ; convert BX and CX to data offsets
- call DataOfs
- xchg BX,CX
- call DataOfs
- xchg BX,CX
-
- ; adjust pointers
- mov AX,-1 ;adjustment amount
- mov DX,CX ;high end to adjust
- inc BX ;low end to adjust
- call AdjustPointers
- dec BX
-
- ; change BX & CX back to buffer offsets
- call BufferOfs
- xchg BX,CX
- call BufferOfs
- xchg BX,CX
-
- pop DX
- pop AX
- ret
-
- ENDP
-
-
- ;=========================================
- ; increase buffer size by at least 1 byte
- ; in: DS = original DS (DATASEG)
- ; BX,CX = buffer pointers
- ; out: AX = 0 on failure
- ; BX,CX = updated
- ; DS:SI = new buffer location
- ;=========================================
- PROC NOLANGUAGE GrowBuffer NEAR
-
- call DataOfs
- xchg BX,CX
- call DataOfs
- xchg BX,CX
-
- push BX ;save our registers
- push CX
- push DX
- push ES
-
- mov AX,1 ; changeBufSize(1)
- push AX
- push ES
- push DI
- call @TEditor@changeBufSize$qs
- add SP,6
- cbw
-
- pop ES ;restore our registers
- pop DX
- pop CX
- pop BX
-
- lds SI,[ES:DI+TEditorBuffer] ;get new buffer pointer
-
- call BufferOfs
- xchg BX,CX
- call BufferOfs
- xchg BX,CX
-
- ret ;AX = return value from changeBufSize()
- ENDP
-
-
- ;======================================
- ; convert buffer offset to data offset
- ; in: BX = buffer offset
- ; ES:DI = thisPtr
- ; out: BX = data offset
- ;======================================
- PROC NOLANGUAGE DataOfs NEAR
- cmp BX,[ES:DI+TEditorCurPtr]
- jb @@Exit
- sub BX,[ES:DI+TEditorGapLen]
- @@Exit:
- ret
- ENDP
-
-
- ;======================================
- ; convert data offset to buffer offset
- ; in: BX = data offset
- ; ES:DI = thisPtr
- ; out: BX = buffer offset
- ;======================================
- PROC NOLANGUAGE BufferOfs NEAR
- cmp BX,[ES:DI+TEditorCurPtr]
- jb @@Exit
- add BX,[ES:DI+TEditorGapLen]
- @@Exit:
- ret
- ENDP
-
-
- ;-----------------------------------------------------------------
- ; adjust pointers into edit buffer after text shift
- ; in: ES:DI = thisPtr
- ; AX = adjustment amount
- ; BX, DX = endpoints of affected data (data offsets)
- ; CX = pointer to adjust (in addition to SelStart & SelEnd)
- ; out: CX, SelStart & SelEnd updated
- ; other regs unchanged
- ;-----------------------------------------------------------------
- PROC NOLANGUAGE AdjustPointers NEAR
-
- call AdjPtr ;fix pointer CX
- push CX ;save it
-
- mov CX,[ES:DI+TEditorSelStart]
- call AdjPtr
- mov [ES:DI+TEditorSelStart],CX
-
- mov CX,[ES:DI+TEditorSelEnd]
- call AdjPtr
- mov [ES:DI+TEditorSelEnd],CX
-
- pop CX ;recover pointer CX
- ret
-
- ; called to adjust pointer CX
- AdjPtr:
- cmp CX,BX
- jb AdjOk
- cmp CX,DX
- ja AdjOk
- add CX,AX ;in range, adjust it
- AdjOk:
- ret
-
- ENDP
-
-
- ENDP ;doWordWrapBuffer
-
-
- END
-
-