        PAGE    60,132
;***************************************************************************
; General comments
;***************************************************************************
; The following comprises the disassembled and documented version of DOS-ED
; as it exists on Compuserve's XA6 data base.  If one reassembles this
; program one will obtain the exact version of DOS-ED.COM that exists on
; that database.  No attempt has been made to make improvements to this code
; other than to indicate in the margin were some could (and probably should)
; be made.  If you notice that the program sizes are different between this
; reassembled and relinked version and the version that has been generated
; from the HEX file on CIS, that is because there is some trailing garbage
; on the CIS file.  You can strip it off in the debugger and the files will
; compare exactly.
;
; Even after disassembling and documenting this code I have a few questions
; about what was being done in places.  If my comments seem spurious at
; times, then just take them with a grain of salt.  They should help you
; understand this code for the most part.
;
; When linking this program you should expect to receive a No Stack warning
; message along with an Unsatisfied external error on DOS_RETURN.  These
; are normal and should be ignored.
;
; DOS-ED is a fine piece of programming performed by Jack Gersbach.
; This disassembly and documentation was done by myself.
;                                     - Scott W. Killen
;
;***************************************************************************
; Definitions and commentary on conventions in coding
;***************************************************************************
; Register usage:  (Most common (but not exclusive) uses are listed)
; AX, DX, CX - Used for many reasons
; DH - Usually current row on crt
; DL - Usually current col on crt
; SI - Usually points to offset of current character in input buffer (first character is offset 0)
; DI - Usually has the value of one of the following:
;      * The number of characters currently in the input buffer   *or*
;      * Points to a destination in the text holding buffer
; BX - Usually contains the address at which the first character in the input buffer is located.
;         (The two characters before this are the max buffer size and length of string
;          characters.)
; BP - Usually a register of flags organized as bits |01234567| where:
;      Bits 0-3 have no function
;      Bit 4 - Off means the input buffer has been altered since interrupt processing began.
;              On means *only* lateral cursor positioning commands have been issued since interrupt
;                 processing began.
;      Bit 5 - Off means previous line from holding buffer, On means original line
;      Bit 6 - Off means no changes to current line in input buffer, On means changes have been made
;      Bit 7 - Applies to the redisplay of lines on the screen after an intra-line edit operation
;                 Off means line wasn't shortened therefore no trailing blanks needed
;                 On means line is now shorter and blanks are needed over trailing characters
;
; Memory Usage:
; ES:[0450H] - Contains current cursor position in Bios data area
; ES:[044AH] - Contains # of columns of current crt screen in Bios data area
; ES:[0417H] - Keyboard flag, containing insert, shift, num lock, scroll lock etc in Bios data area
;                   insert flag bit is 80h
;
; CS:[inline_mod1+1] - Jump return address to normal DOS funcion processing
; CS:[inline_mod2+1] - Current cursor definition (start/stop lines)
; CS:[inline_mod3+1] - Screen location of end of line (row/col)
; CS:[inline_mod4+2] - Higher of DS or CS on entry into interrupt.
; CS:[inline_mod5+2] - Maximum size of input buffer
;
; start_off  - Offset of start of input buffer on screen (example if prompt is A> then screen column position
;                   of input buffer start would be 2
; current_col - Current column position on screen (1st column is 0)
; last_entry - Address (offset) of last string accessed in text buffer
; next_entry - Address (offset) of next available block in text buffer
; buffer_bot - Base address of text buffer
; buffer_top - Top address of text buffer
; aux_last  \
; aux_next   \ Same as previous four except for auxiliary buffer
; aux_bot    /
; aux_top   /
;

; Character equates
ACK              equ  06h  ; Acknowledge character (Cntrl F)
BELL             equ  07h  ; Bell character        (Cntrl G)
BACKSPACE        equ  08h  ; Backspace character
TAB              equ  09h  ; Tab character
ESC              equ  1Bh  ; Escape character
BLANK            equ  20h  ; Space character
CR               equ  0dh  ; carriage return
LF               equ  0ah  ; Line feed
HAT              equ  5eh  ; "^" character
SMALLA           equ  61h  ; "a" character
LEFT_CURLY_BRACE equ  7Bh  ; "{" character
CNTL_BACKSPACE   equ  7fh  ; Control and backspace pressed simultaneously

; Masks
INSERT_ON_MASK   equ  80h  ; Insert key bit on, corresponding to keyboard status word
INSERT_OFF_MASK  equ  7fh  ; Insert key bit off, corresponding to keyboard status word
LENGTH_BYTE_MASK equ  80h  ; Mask to identify the text string length bit in text buffer
LENGTH_OFF_MASK  equ  7fh  ; Mask to turn of the length byte identifier
UPPER_CASE_MASK  equ  40h  ; Convert control character to upper case character
LOWER_CASE_MASK  equ  20h  ; Convert upper case character to lower case character

; Physical characteristics
ROWS_ON_CRT       equ 19h               ; Ordinal number of lines on crt
LAST_ROW_ON_CRT   equ  ROWS_ON_CRT - 1  ; Offset of last line on crt (top line is line 0)
MONO_CUR_DEF      equ  0B0Ch            ; Start, stop lines of cursor
MONO_CUR_STOP     equ  0Ch              ; Stop line for standard cursor
GRAPHICS_CUR_DEF  equ  0607h            ; Start, stop lines of cursor for graphics device
GRAPHICS_CUR_STOP equ  07h              ; Stop line for standard cursor for graphics device
TEXT_BUFFER_START equ 60h               ; Start address for text holding buffer
TEXT_BUFFER_END   equ 160h              ; End address for text holding buffer
TEXT_BUFFER_SIZE  equ TEXT_BUFFER_END - TEXT_BUFFER_START ; Extent of text buffer
BOTH_BUFFS_SIZE   equ TEXT_BUFFER_SIZE + TEXT_BUFFER_SIZE ; Combined buffer size
AUX_BUFFER_START  equ 160h              ; Auxiliary holding buffer start address
AUX_BUFFER_END    equ 260h              ; Auxilliary holding buffer end address
                                        ; *NOTE* TEXT_BUFFER_END - TEXT_BUFFER_START =
                                        ;        AUX_BUFFER_END - AUX_BUFFER_START

; Bios interrupt 10 functions
SET_CURSOR_TYPE  equ  01h
SET_CURSOR_POSN  equ  02h
READ_CURSOR_POSN equ  03h
READ_VIDEO_STATE equ  0fh

; Dos interrupt 21 functions
INPUT_CHR_NOECHO  equ  08h
OUTPUT_CHR        equ  02h

;***************************************************************************
; BIOS data segment definition
;***************************************************************************
BIOSEG  SEGMENT at 0h
        org 417h
        kbd_flag     db  ?
        org 44ah
        crt_cols     dw  ?
        org 450h
        cursor_posn  dw  ?
BIOSEG  ends

;***************************************************************************
; DOS-ED code segment begins
;***************************************************************************
CSEG    SEGMENT
        ASSUME CS:CSEG
        ORG 100H
DOSED   PROC NEAR

        MOV     SI,offset loadlabel    ; Source of code to move is at loadlable
        MOV     DI,offset initialize   ; Destination is at end of file at initialize
        MOV     CX,offset line_table   ; Above the code to be moved is linetable
        SUB     CX,SI                  ; The difference is the amount of code to be moved
        repz MOVSB                     ; Move it!!
        JMP     initialize             ; Now go do it.

loadlabel:
        XOR     AX,AX                       ; Clear AX
        MOV     DS,AX                       ; Prepare to save original interrupt
        MOV     SI,0084H                    ; Source for INT 21h as provided for in the interrupt table
        MOV     DI, offset [inline_mod1+1]  ; Destination in the code segment for moving this pointer
        MOVSW                               ; Move the two word address
        MOVSW
        MOV     AX, offset entry_point ; Move this programs starting address into the dos interrupt slot
        MOV     [SI-04H],AX            ; Move offset in line
        MOV     [SI-02H],CS            ; Move segment value in line
        MOV     DI, TEXT_BUFFER_START  ; Working buffer begins at offset 60h which is Formatted parameter
        MOV     CX, BOTH_BUFFS_SIZE    ;   area 1 in the Program Segment Prefix.
        MOV     AL, CR                 ; Fill 512 bytes with CR characters.  Note that this technique uses
        repz STOSB                     ;   161 bytes of PSP for storage!  Very Clever!
        MOV     DX, offset initialize  ; Dos may load above this address
        INT     27H                    ; Terminate but stay resident

line_table      db  300 dup (?)

entry_point:
        CMP     AH,0AH               ; Is this function 10?
        JE      wrapper              ; Nope, continue with normal Dos 21 interrupt
        EXTRN   DOS_RETURN:FAR

inline_mod1:
        JMP     DOS_RETURN           ; This code is modified in line!
                                     ;    Go to normal Dos function handling.

wrapper:
        PUSH    AX
        PUSH    BX
        PUSH    CX
        PUSH    DX
        PUSH    SI
        PUSH    DI
        PUSH    BP
        PUSH    DS
        PUSH    ES
        STI
        CALL    begin_dosed
        POP     ES
        POP     DS
        POP     BP
        POP     DI
        POP     SI
        POP     DX
        POP     CX
        POP     BX
        POP     AX
        MOV     AL,00H
        IRET

;***************************************************************************
; Extended keystroke recognition and branching tables
;***************************************************************************
                ; Table 1 of extended keyboard function codes
table1:
t1_1    db  0fh ; Back Tab
t1_2    db  47h ; Home key
t1_3    db  48h ; Up arrow
t1_4    db  4bh ; Left arrow
t1_5    db  4dh ; Right arrow
t1_6    db  4fh ; End key
t1_7    db  50h ; Down Arrow
t1_8    db  53h ; Del key
t1_9    db  73h ; Cntrl Left Arrow
t1_a    db  74h ; Cntrl Right Arrow
t1_b    db  75h ; Cntrl End
t1_c    db  77h ; Cntrl Home
t1_d    db  76h ; Cntrl PgDn
t1_e    db  84h ; Cntrl PgUp
t1_f    db  00h ; ?
                    ; Table 2 indexes correspond to table 1 indexes
                    ; and points to code address where the function is handled.
table2:
t2_f    dw offset error_return        ;    0ah, 05h   ; ?
t2_e    dw offset cntrl_page_up       ;    74h, 07h   ; Cntrl PgUp
t2_d    dw offset cntrl_page_down     ;   0a9h, 06h   ; Cntrl PgDn
t2_c    dw offset cntrl_home          ;    0bh, 05h   ; Cntrl Home
t2_b    dw offset cntrl_end           ;    27h, 05h   ; Cntrl End
t2_a    dw offset cntrl_right_arrow   ;    41h, 05h   ; Cntrl Right Arrow
t2_9    dw offset cntrl_left_arrow    ;    83h, 05h   ; Cntrl Left Arrow
t2_8    dw offset del_key             ;   0edh, 05h   ; Del key
t2_7    dw offset down_arrow          ;    44h, 06h   ; Down Arrow
t2_6    dw offset end_key             ;   0e4h, 04h   ; End key
t2_5    dw offset right_arrow         ;    67h, 05h   ; Right arrow
t2_4    dw offset left_arrow          ;    99h, 05h   ; Left arrow
t2_3    dw offset up_arrow            ;    43h, 06h   ; Up arrow
t2_2    dw offset home_key            ;   0e1h, 05h   ; Home
t2_1    dw offset backtab             ;    8dh, 05h   ; Backtab

;***************************************************************************
; Display and output services
;***************************************************************************
screen_and_display:                 ; Screen out control characters of form ^x
        CMP     AL, BLANK           ; Compare AL to blank character
        JNB     display_one_char    ; If we have a printable character go to display routine
        CMP     AL, TAB             ; Is this a forward tab?
        JE      display_one_char    ; If so, go display.
        PUSH    AX                  ; No, this is a "normal" control character
        MOV     AL,HAT              ; Place a "^" character in AL
        CALL    display_one_char    ; Print the "^" out.
        POP     AX                  ; Now convert the Control character to its
        OR      AL, UPPER_CASE_MASK ; upper case equivalent and print it.  Result is "^E"
                                    ;    construct for representing control characters.

display_one_char:
        CMP     AL, BLANK           ; Does AL contain a blank character
        JB      display_cntrl_chr   ; Jump if we have a control character

ready_display:
        CMP     AL, CNTL_BACKSPACE           ; Don't increment column counter if this
        JE      output_to_display            ;    is a control Backspace character
        INC     BYTE PTR CS:[current_col]    ; Increment column position because we received
                                             ;    something printable
output_to_display:
        PUSH    DX                           ; Save the DX register and set up the
        XCHG    AX,DX                        ;    AH register for a DOS function 2 (Display
        MOV     AH,  OUTPUT_CHR              ;    output) call.
        INT     21H
        XCHG    AX,DX                        ; Restore the AX register
        POP     DX                           ;    and restore the DX register
        RET

display_cntrl_chr:                           ; Process a control character for output
        CMP     AL, CR                       ; Is this a carriage return character?
        JE      cr_out                       ; If so go take care of it
        CMP     AL, BACKSPACE                ; Is this a backspace?
        JE      bs_out                       ; If so we need to take care of it
        CMP     AL, TAB                      ; Maybe its a tab character
        JNE     relay_to_output              ; Continue if its not a tab
        MOV     AL,BYTE PTR CS:[current_col] ; Set AL to current column on screen
        OR      AL,0F8H                      ; Get the number of spaces to the next
        NEG     AL                           ;    8 byte boundary
        PUSH    CX                           ; Save the CX register
        MOV     CL,AL                        ; Place the count of blanks to be output in CL
        mov     ch, 00h                      ; Zero out high byte
        JCXZ    skip_tabbing                 ; Dont do anything if count is zero

tab_loop:
        MOV     AL, BLANK                    ; Ok, now print out all necessary
        CALL    display_one_char             ;    blanks to reach an 8 character
        LOOP    tab_loop                     ;    boundary.

skip_tabbing:
        POP     CX                           ; Restore the CX register.
        RET

cr_out:
        MOV     CS:BYTE PTR [current_col],00H   ; Reset current column pointer to zero

relay_to_output:
        JMP     SHORT output_to_display

bs_out:
        DEC     BYTE PTR CS:[current_col]  ; Decrement the current column pointer
        PUSH    AX                         ; Save the character in register AX
        PUSH    DX                         ; Save the DX register
        MOV     DX,ES:[0050H]              ; Get the Cursor position from Bios data area
        MOV     AH,ES:[004AH]              ; Get the # of CRT cols on screen from Bios data area
        OR      DL,DL                      ; Are we at column zero?
        JNE     bs_end                     ; If not forget the rest.
        OR      DH,DH                      ; Are off the screen at the top?
        JNE     set_cur_loc                ; If not then dont reset rows
        MOV     DH, ROWS_ON_CRT            ; (Re)set row value to 25

set_cur_loc:
        DEC     DH                         ; Decrement the row count
        MOV     DL,AH                      ; Move in # of columns.  (0, 0) is home.
        PUSH    BX                         ; Save BX
        MOV     BH,00H                     ; Prepare for BIOS interrupt 10 funtion 2
        MOV     AH, SET_CURSOR_POSN        ;    call (Set cursor position)
        INT     10H                        ; Do it.
        POP     BX                         ; Restore BX

bs_end:
        POP     DX                         ; Restore DX register
        POP     AX                         ; and the AX register
        JMP     SHORT relay_to_output      ; and now we are done.

decrement_col_row:                         ; Wrap back if line spans two screen lines
        OR      DL,DL                      ; Are we at column zero
        JNE     dcr_end                    ; If so then dont worry about row update
        DEC     DH                         ; Yep, decrement the row pointer
        MOV     DL,BYTE PTR ES:[crt_cols]  ; Get the # of CRT cols per screen from Bios data area

dcr_end:
        DEC     DL                         ; Decrement the column pointer
        RET

display_blank:
        MOV     AL, BLANK

display_and_test:                             ; Display and test for updated cursor location
        PUSH    CX                            ; Save CX register
        MOV     CX,ES:[cursor_posn]           ; Load CX with cursor position from Bios
        CALL    screen_and_display            ; Send the character in AL to output display
        CMP     CH, LAST_ROW_ON_CRT           ; Are we on the last row?
        JNE     dat_end                       ; If not then no further tests are needed
        CMP     CL,BYTE PTR ES:[cursor_posn]  ; Are we now on a new column?  (alternative question
                                              ;    is: have we scrolled?)
        JBE     dat_end                       ; If current location > cl then yes we have scrolled
                                              ;    up a line and need to decrement the line pointer
        DEC     DH                            ; Decrement the line pointer

dat_end:
        POP     CX                   ; Restore CX
        RET
;***************************************************************************

set_cursor:
        PUSH    BX
        PUSH    CX
        PUSH    DX
        PUSH    BP                                  ; Save registers
        PUSH    SI
        PUSH    DI

inline_mod2:
        MOV     CX, MONO_CUR_DEF                       ; Assume Standard char def
                                                       ;   (Note that this word is modified
                                                       ;    in line if it is later determined
                                                       ;    that a graphics board is in use)
        TEST    BYTE PTR ES:[kbd_flag], INSERT_ON_MASK ; Is insert on?
        JE      after_box                              ; If not then branch
        MOV     CH,CL                                  ; Yep, turn the cursor into
        SHR     CH,1                                   ;   a half sized box

after_box:
        MOV     AH, SET_CURSOR_TYPE                    ; Set up and call Bios for
        INT     10H                                    ;   support.
        POP     DI
        POP     SI
        POP     BP                                     ; Restore Registers
        POP     DX
        POP     CX
        POP     BX
        MOV     AX,WORD PTR ES:[cursor_posn]            ; Load AX with current cursor position

inline_mod3:
        CMP     AX,0888H                                 ; Compare current cursor position to end of line position
        JB      sc_ret                                   ; If less than then dont update end of line position
        MOV     CS:WORD PTR [inline_mod3+1],AX  ; Modify end of line address with value of current cursor position

sc_ret:
        RET

credit  db 'DOS EDITOR BY J. Gersbach',CR,LF,00


begin_dosed:                            ; Save registers
        PUSH    BX
        PUSH    CX
        PUSH    DX
        MOV     BH,00H                  ; Set up to read current cursor position
        MOV     AH, READ_CURSOR_POSN    ; Cursor position returned as DH, DL is row, col
        INT     10H                     ; Read the current cursor position into DH, DL
        MOV     CS:[start_off],DL       ; Move current column into storage
        MOV     CS:[current_col],DL     ; Move current column into storage
        CMP     CL, MONO_CUR_STOP       ; Check: Is current end line for cursor = 12
        JB      bd2                     ; Branch if less than 12
        MOV     AH, READ_VIDEO_STATE    ; Set up to return current video state
        INT     10H                     ; Go get it
        CMP     AL, GRAPHICS_CUR_STOP   ; Is this a 80x25 BW card
        MOV     CX, MONO_CUR_DEF        ; Set start/stop lines for cursor to 11/12
        JE      bd1                     ; Yes it is 80x25 BW card, branch
        MOV     CX, GRAPHICS_CUR_DEF    ; No its not 80x25 card, start/stop lines are 6/7

bd1:
        MOV     AH, SET_CURSOR_TYPE     ; Set function call to set cursor type
        INT     10H                     ; Do it

bd2:
        MOV     CS:WORD PTR [inline_mod2+1],CX   ; Save the cursor type setting in line
        POP     DX
        POP     CX
        POP     BX
        MOV     BX,DX                           ; DX points to offset of input buffer
        MOV     AL,[BX]                         ; Get the number of characters in the buffer
        CMP     AL,02H                          ; Is it bigger than 2 characters?
        JB      sc_ret                          ; Nope, we have a problem here!
        DEC     AL                              ; Now decrement AL to get number of real characters
        MOV     AH, 00H                         ;    buffer han hold.   Zero out AH
        MOV     CS:WORD PTR [inline_mod5+2],AX  ; AX now contains the max number of chars that the buffer
                                                ;    can hold.
        ADD     BX,02H                          ; BX points to address at which to put first real character
                                                ;    in input buffer
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                                                ;;  AUTOMATIC BUFFER TOGGLE (Why, I don't know)
auto_buffer_toggle:                             ;;
        MOV     BP,DS                           ;;  Place the DS register into BP
        PUSH    DS                              ;;  Save the value of the DS register
        MOV     DI,CS                           ;;  Place the CS register into DI
        MOV     DS,DI                           ;;     and also into DS
        CMP     BP,DI                           ;;  Compare DS : CS values
        JB      abt1                            ;;  If DS < CS then jump
                                                ;;
inline_mod4:                                    ;;
        CMP     DI,0888H                        ;;  Compare CS : AUX    (this in-line address will be called AUXiliary)
        JE      abt2                            ;;  If its equal (if we came this way last time!) then go swap
        JMP     SHORT after_swap_loop           ;;  If so then avoid swaps
                                                ;;
abt1:                                           ;;
        MOV     BP,DI                           ;;  Set BP to highest register value (now determined to be CS)
        CMP     DI,DS:WORD PTR [inline_mod4+2]  ;;  Compare CS : AUX
        JE      after_swap_loop                 ;;  If its not equal (if we came this way last time!) then go swap
                                                ;;
abt2:                                           ;;
        PUSH    CS                              ;;  Now we must swap the appropriate memory locations to allow the
        POP     ES                              ;;     editor to use the other buffer (There are two buffers that one
                                                ;;     can transfer between depending on DS : CS relationship.
        MOV     SI,offset last_entry            ;;  Load SI with starting address
        LEA     DI,[SI+08H]                     ;;  Load DI with second starting address
        MOV     CX,0004H                        ;;  4 words are to be moved ... in order ... address of last string accessed,
                                                ;;     address of highest available byte, base address of text holding buffer,
                                                ;;     high address of holding buffer.
                                                ;;  Values are initiallized to:
                                                ;;     1st buffer - 60h, 60h, 60h, 160h
                                                ;;     2nd buffer - 160h, 160h, 160h, 260h
                                                ;;
swap_loop:                                      ;;
        MOV     AX,[DI]                         ;;  Save the value in the secondary buffer
        MOVSW                                   ;;  Move the primary buffer value into the secondary buffer position
        MOV     [SI-02H],AX                     ;;  Replace emptied location with saved value
        LOOP    swap_loop                       ;;  Go back and swap next set of values
                                                ;;
after_swap_loop:                                ;;
        MOV     DS:WORD PTR [inline_mod4+2],BP  ;;  Load AUX such that AUX = Max(CS, DS)
        POP     DS                              ;;  Restore DS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
        MOV     BP,000CH
        JMP     SHORT rib1

reinit_buffer:
        MOV     BP,0004H

rib1:
        XOR     SI,SI                                    ; Zero out Source index
        MOV     CS:WORD PTR [inline_mod3+1],SI           ; Modify inline address just above
        XOR     DI,DI                                    ; Zero out Destination index
        MOV     ES,DI                                    ; Zero out the ES register
        AND     BYTE PTR ES:[kbd_flag], INSERT_OFF_MASK  ; Turn insert off

start_read_char:
        AND     BP,0FFFEH                  ; Turn off low bit in BP (Line may be shorter)
        CALL    set_cursor                 ; Set the cursor shape as per mode
        XCHG    AX,DX                      ; Save AX in DX
        MOV     AH, INPUT_CHR_NOECHO       ; Get a character from the keyboard
        INT     21H                        ; Call DOS for service
        CMP     AL, ACK                    ; Is it an acknowledge character?
        JE      start_read_char            ; If so ... just forget it and go back
        MOV     CX, offset start_read_char ; Save address of start_read_char label
        PUSH    CX                         ; This is a return address for a nonexistent call!
        OR      AL,AL                      ; Set up for test
        JNE     normal_keyboard_chr        ; Jump if non null character input

extended_keyboard_chr:
        MOV     AH, INPUT_CHR_NOECHO       ; Null character, get ready to read next character
        INT     21H                        ; Get it
        PUSH    ES                         ; Save ES
        PUSH    CS                         ; Set ES to value in CS
        POP     ES
        PUSH    DI                         ; Save DI
        MOV     CX,000FH                   ; Set counter to number of items in table 1
        MOV     DI, offset [table1]        ; Set starting address of table 1
        repnz SCASB                        ; Scan for occurrence of second character in table 1
        POP     DI                         ; Restore DI
        POP     ES                         ;    and ES
        XCHG    CX,BX                      ; Let BX contain pointer to item found in table 1
        ADD     BX,BX                      ; Double it
        PUSH    CS:WORD PTR [BX+table2]    ; Index into table 2 for starting address of service code
                                           ;    The value is pushed onto the stack to allow for the
                                           ;    return (Without a corresponding call!)
        MOV     BX,CX                      ; Restore original BX value
        RET                                ; Execute the fake return


;***************************************************************************
; Individual service routines
;***************************************************************************
;*********************************************************************************** Escape Key
escape_handling:                        ; Escape character here
        CALL    home_key                ; Go to start of line
        CALL    cntrl_end               ; Delete to end

restart_input:
        POP     DI                      ; Pop the return address off of the stack
        JMP     SHORT reinit_buffer     ; Jump to reinitialize buffer and read

normal_keyboard_chr:
        CMP     AL, CNTL_BACKSPACE    ; Control Backspace?
        JE      nkc1                  ; if so, go to backspace handling
        CMP     AL, BACKSPACE         ; Backspace?
        JNE     nkc2                  ; If not continue

nkc1:
        JMP     backspace_handling    ; Backspace here, take care of it

nkc2:
        CMP     AL, CR                ; Is it a carriage return?
        JNE     nkc3                   ; If not continue
        JMP     cr_key                ; Yes, go take care of it

nkc3:
        CMP     AL, ESC               ; Is it an escape character
        JE      escape_handling       ; If so, go take care of it

        CMP     AL, TAB               ; Bad code here                                              ** remove this **
        JE      nkc4                  ; Bad code here                                              ** remove this **

inline_mod5:
nkc4:   CMP     DI,0888H              ; Compare DI to max buffer size (modified in line in Begin_Dosed)
        JB      printable_char        ; If less than max then continue with printable character
        MOV     AL, BELL              ; Prepare to ring the bell
        JMP     display_one_char      ; Do it


;*********************************************************************************** Non editing character
printable_char:
        AND     BP,0FFF7H             ; Turn off the no changes made flag
        OR      BP,0002H              ; Turn on the changes made to this line flag
        PUSH    AX                    ; Save AX
        CALL    display_and_test      ; go display the character
        MOV     DX,ES:[cursor_posn]   ; Place the current cursor position in DX
        TEST    BYTE PTR ES:[kbd_flag], INSERT_ON_MASK   ; Is insert mode mask on?
        JE      add_chr_to_inbuf      ; If not then branch around shift up string
        PUSH    DI                    ; Save the DI register

shift_up:
        CMP     DI,SI                 ; Are we pointing past the end?
        JBE     end_shift_up          ; Have we decended to the original point?
        MOV     AL,[BX+DI-01H]        ; Move this character in input buffer up
        MOV     [BX+DI],AL            ;    one byte in memory
        DEC     DI                    ; Next character down
        JMP     SHORT shift_up        ; Return for more

end_shift_up:
        POP     DI                    ; Restore original end of input buffer pointer
        INC     DI                    ; Increment it by one
        INC     SI                    ; Also increment the current character pointer
        CALL    redisplay_line
        DEC     SI                    ; Now decrement source so that it will look
                                      ;    like normal overwrite to next code section

add_chr_to_inbuf:
        POP     AX                    ; Restore AX
        MOV     AH,AL                 ; Move the current character into AH
        XCHG    AL,[BX+SI]            ; Put it into the input buffer
        INC     SI                    ; Point to next character position
        CMP     DI,SI                 ; Have we gone past the end
        JNB     acti1                 ; If not then forget update of DI
        MOV     DI,SI                 ; DI is now reset to SI (which was >)

acti1:
        AND     AL,AH                 ; AND old character against new character
        CMP     AL, BLANK             ; If both are printable then we are finished
                                      ;    because we have coundn't have shortened
        JNB     acti_ret              ;    the line with the overwrite.  (eg. A over ^E
                                      ;    would shorten line by one character)
        TEST    BYTE PTR ES:[kbd_flag], INSERT_ON_MASK  ; If insert mode was on then we
        JNE     acti_ret              ;    are finished also because we have already
                                      ;    printed the string
        CMP     SI,DI                 ; Also we can forget if we are at the end of the line
        JE      acti_ret              ; None of the above hold, and we may have trailing
        JMP     note_shorter_change   ;    characters on the line that need to be blanked
                                      ;    over. (caused by overwriting a ^x diagraph or a
                                      ;    Tab character with a single character.)
acti_ret:
        RET


;*********************************************************************************** End key
end_key:
        TEST    BP,0008H               ; Have we made any changes to this buffer?
        JE      move_to_end            ; If so then go ahead an position to end of line.
        AND     BP,0FFF7H              ; No changes, lets now indicate that changes have been made,
        OR      DI,DI                  ;    and restore the input buffer.  Start by checking DI for zero.
        JNE     move_to_end            ; Go restore if something is there.
        MOV     AL,[BX-01H]            ; Get the length of the string in the holding buffer.
        CMP     [BX-02H],AL            ; Is it larger than the max buffer size?
        JB      recycle_input          ; If so then we have problems and a restart is necessary.
        MOV     AH,00H                 ; Zero out AH
        XCHG    AX,DI                  ; Move the new length into DI
        CMP     BYTE PTR [BX+DI], CR   ; Is there a carriage return here
        JE      move_to_end            ; If so then go ahead and restore it

recycle_input:
        JMP     restart_input          ; No, we must have garbage in the input buffer, go back and restart

move_to_end:
        CALL    right_arrow     ; move over one character to the right
        JB      move_to_end     ; keep going if not at end

error_return:
        RET


;*********************************************************************************** Control home key
cntrl_home:
        PUSH    SI              ; Save the pointer into the input buffer
        CALL    home_key        ; Move to start of line
        POP     SI              ; Restore pointer
        MOV     CX,DI           ; Set CX to character count in string and remove the
        SUB     CX,SI           ;    characters from start of line to current position from count.
        XOR     DI,DI           ; Clear out the DI register
        PUSH    DI              ; Save it.                                                               ** get rid of this **
        PUSH    CX              ;   and the new count of characters.
        JCXZ    after_drop_down ; If the new count of characters is zero then nothing else to do.

drop_text_down:
        MOV     AL,[BX+SI]      ; Get the current character
        INC     SI              ; Advance source pointer to next character
        MOV     [BX+DI],AL      ; Store it down into the next destination available
        INC     DI              ; Increment the destination pointer
        LOOP    drop_text_down  ;    and continue for the count

after_drop_down:
        POP     DI                    ; Restore DI
        POP     SI                    ;    and SI                                                             ** change this to xor SI,SI **
        JMP     note_shorter_change   ; Now go redisplay line on screen


;*********************************************************************************** Control end key
cntrl_end:
        OR      BP,0002H                        ; Turn on the change to line flag
        MOV     CX,CS:WORD PTR [inline_mod3+1]  ; Get the screen position of the last character in the screen

blank_to_end:
        CMP     CX,ES:[cursor_posn]      ; Is the current screen position at the end of line?
        JBE     after_blanking           ; If so then jump
        CALL    display_blank            ; Display a blank
        JMP     SHORT blank_to_end       ; and continue until end of line position on screen is reached

after_blanking:
        MOV     DI,SI                    ; The new line length is current offset in the line
        JMP     place_cursor             ; and now place the cursor on the screen


;*********************************************************************************** Control right arrow
cntrl_right_arrow:                       ; Move right to start of next word
        CALL    right_arrow              ; Move right one character
        JNB     cra_ret                  ; If at the end then fall out of loop
        CALL    check_non_by_alpha       ; Check for non-alpha/alpha combination (return issued from subroutine
                                         ;    if the condition is satisfied)
        JMP     SHORT cntrl_right_arrow  ; continue the cycle

cra_ret:
        RET

check_non_by_alpha:
        MOV     AL,[BX+SI]       ; Get character
        CALL    check_alpha      ; See if this is an alphabetic character
        JB      cnba_ret         ; If not then we are finished
        MOV     AL,[BX+SI-01H]   ; Get previous character
        CALL    check_alpha      ; Is this an alpha?
        JNB     cnba_ret         ; If so then we are still not happy and must continue searching.
        POP     AX               ; Pop off the fake return address if this location points
                                 ;    to an alpha character and the previous one doesnt.
cnba_ret:
        RET

check_alpha:
        OR      AL, LOWER_CASE_MASK  ; Or in lower case bit
        CMP     AL, SMALLA           ; Is this the letter "a"?
        JB      cnba_ret             ; It is less than the letter "a" ... return
        CMP     AL, LEFT_CURLY_BRACE ; Is this the character "{"?  (one greater than "z")
        CMC                          ; Complement Carry flag so its on if < "{"
        RET

;*********************************************************************************** Right arrow
right_arrow:
        CMP     SI,DI                      ; Are we past the last character
        JNE     redisplay_char             ; If not then continue
        RET

redisplay_char:
        MOV     AL,[BX+SI]          ; Move the current character into AL
        INC     SI                  ; Bump the pointer #U8z]ge9^Z
into input buffer
        CALL    display_and_test    ; Redisplay that character
        STC                         ; Set the carry flag
        RET

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
L0474:  CALL    right_arrow                    ;\                             ;;
        JNB     L0482                          ; \                            ;;
        MOV     AL,07H                         ;  \ This code is not called.  ;;
        AND     AL, BYTE PTR ES:[cursor_posn]  ;  /                           ;;
        JNE     L0474                          ; /                            ;;
L0482:  RET                                    ;/                             ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


;*********************************************************************************** Control left arrow
cntrl_left_arrow:
        CALL    left_arrow               ; Move left one character
        JB      bt_ret                   ; Jump if we are at the end of the buffer
        CALL    check_non_by_alpha       ; See if we are at the start of an alph character string.
        JMP     SHORT cntrl_left_arrow   ; If not then loop (if we were then the return was issued from
                                         ;    check_non_by_alpha)

;*********************************************************************************** Backtab key
backtab:
        CALL    left_arrow    ; move left one character
        JB      bt_ret        ; If at the start of the line then quit
        MOV     AL,07H        ; set up the mask
        AND     AL,DL         ; check to see if we are on an 8 byte column.
        JNE     backtab       ; If not then continue left.

bt_ret:
        RET


;*********************************************************************************** Left Arrow
left_arrow:
        OR      SI,SI                      ; Are we at the start of the line
        STC                                ; Set the carry flag
        JE      cnba_ret                   ; If so then do nothing
        DEC     SI                         ; Move the input buffer pointer back one
        CALL    decrement_col_row          ; Adjust the col row positon
        CMP     BYTE PTR [BX+SI], TAB      ; Have we just run over a tab?
        JE      back_over_tab              ; If so then go expand it
        CMP     BYTE PTR [BX+SI], BLANK    ; Compare for printable character
        JNB     la_end                     ; If we have one then jump to final section
        CALL    decrement_col_row          ; Decrement col row one more time (for ^ character)
        JMP     SHORT la_end               ; Finish up
                                           ; Expand the tab character
back_over_tab:
        PUSH    SI                         ; Save the SI pointer into input buffer
        MOV     CX,SI                      ; Set the count to its value
        MOV     AL,CL                      ;    and also AL
        MOV     AH,07H                     ;
        JCXZ    no_prev_tabs               ; At start of line (no previous tab to align us)
                                           ; See if we can find another tab in front of us to
                                           ;    align us on screen (character after that tab
                                           ;    would be properly aligned on 8 byte boundary.)
align:
        DEC     SI                         ; Decrement the pointer into input buffer
        CMP     BYTE PTR [BX+SI], BLANK    ; Check for printable character
        JNB     align_end                  ; If found cycle in loop
        CMP     BYTE PTR [BX+SI], TAB      ; Have we succeded in finding another tab?
        JE      sub_prev_char_cnt          ; If so then we know we are aligned so jump
        DEC     AH                         ; No, this must be a control character diagraph (^x form)
                                           ;    so we need to subract an additional character from the
align_end:                                 ;    count of characters found so far.
        LOOP    align                      ; Go back for more

no_prev_tabs:                              ; Ok, we only get here if there were no previous
                                           ;    characters in input buffer or if there were no previous
                                           ;    tabs in the buffer
        SUB     AH,CS:[start_off]          ; Subtract out the screen bias position for location 0 of the
                                           ;    input buffer pointer.
sub_prev_char_cnt:
        SUB     AH,AL                      ; These two statements remove the count of all previous characters
        ADD     CL,AH                      ;    in the buffer (either to tab boundary or start of line).
                                           ;    Additional diagraph hats "^" have been previously subtracted
                                           ;    from AH.
        AND     CL,07H                     ; take modulo 8
        JE      end_jump_tab               ; Did this tab expand into only one blank (remember we've already
                                           ;    moved over one!), if so jump
jump_tab:
        CALL    decrement_col_row          ; Calculate new column and row on screen
        LOOP    jump_tab

end_jump_tab:
        POP     SI                         ; Restore input buffer pointer

la_end:
        CLC                                ; Clear the carry flag
        JMP     SHORT place_cursor         ; Go place the cursor on the screen
        NOP


;*********************************************************************************** Home key
home_key:                                  ; home key service begins here
        CALL    left_arrow                 ; move over one
        JB      pc_ret                     ; jump if back at start
        JMP     SHORT home_key             ; Not there yet, keep going


;*********************************************************************************** Backspace key
backspace_handling:                        ; backspace handling begins here
        CALL    left_arrow                 ; first just move over one character
        JB      pc_ret                     ; If we are already at the start of the line
                                           ;    then we neednt continue

;*********************************************************************************** Delete Key
del_key:                                   ; Delete key handling begins here
        OR      DI,DI                      ; Is the string length zero?
        JE      pc_ret                     ; If so go to end
        CMP     SI,DI                      ; Are we past the end of the string?
        JE      pc_ret                     ; If so go to end
        PUSH    SI                         ; Save the SI pointer to input buffer

shift_down:
        CMP     SI,DI                      ; Are we past the end:
        JE      after_shift_down           ; If so, finish up
        MOV     AL,[BX+SI+01H]             ; Get next character up
        MOV     [BX+SI],AL                 ; then shift it down into this slot
        INC     SI                         ; Increment the input buffer pointer
        JMP     SHORT shift_down           ;    and cycle

after_shift_down:
        POP     SI                         ; Restore the input text buffer pointer
        DEC     DI                         ; Decrement the length of the input buffer string

note_shorter_change:
        OR      BP,0003H                   ; Indicate that we have changed and potentially shortened the string.

redisplay_line:
        AND     BP,0FFF7H
        PUSH    SI                       ; Save the pointer into the input buffer

display_next_char:
        CMP     SI,DI                    ; Are we past the end of the string?
        JNB     after_display_char       ; If so dont display
        MOV     AL,[BX+SI]               ; Get the character from the input buffer
        CALL    display_and_test         ; send it to the display
        INC     SI                       ; update buffer pointer
        JMP     SHORT display_next_char  ; continue to end

after_display_char:
        CALL    set_cursor                      ; Set type of cursor, AX returns with current cursor location (end of line)
        TEST    BP,0001H                        ; Is the old line longer?
        JE      after_blank_pad                 ; If not then forget blanking the tail
        XCHG    AX,CS:WORD PTR [inline_mod3+1]  ; Put current cursor positon in end of line indicator and
                                                ;    save that value for blanking operation
        XCHG    AX,CX                           ; Put former end of line position in CX

add_blank_pad:
        CALL    display_blank            ; Display a blank
        CMP     CX,ES:[cursor_posn]      ; Is current cursor position now at end of line
        JNBE    add_blank_pad            ; If not, then continue blanking loop.

after_blank_pad:
        POP     SI

place_cursor:
        MOV     AH, SET_CURSOR_POSN      ; Load AH for Bios call
        PUSH    BX                       ; Save BX and CX registers
        PUSH    CX
        MOV     CS:[current_col],DL     ; Record current column position
        MOV     BH,00H
        INT     10H                     ; Call bios for service
        POP     CX                      ; Restore registers
        POP     BX

pc_ret:
        RET


;*********************************************************************************** Up Arrow
up_arrow:                               ; Up arrow service starts here
        STD                             ; Set direction flag to decrement

;*********************************************************************************** Down Arrow
down_arrow:                             ; Down arrow service starts here
        AND     BP,0FFF7H
        CALL    home_key                ; Go to beginning of line
        CALL    cntrl_end               ; Delete to end of line

da1:
        PUSH    ES                      ; Save ES register
        PUSH    DS                      ; Set ES to DS
        POP     ES
        PUSH    CS                      ; Set DS to CS
        POP     DS
        MOV     SI,DS:[last_entry]      ; Get pointer to first byte of current string in
                                        ;    input buffer (from text buffer)
        LODSB                           ; Obtain the character
        LEA     DI,[BX-01H]             ; Load DI with the offset of the length character
                                        ;    of the input buffer
        MOV     CX, TEXT_BUFFER_SIZE    ; Set counter to look at each location in the text buffer

search_for_len_byte:
        CALL    get_char                ; Get a character from the text holding buffer
        TEST    AL,  LENGTH_BYTE_MASK   ; Is it a length byte?
        LOOPZ   search_for_len_byte     ; Nope, go back and try again
        CLD                             ; Yep, clear the direction flag
        JNE     found_a_len_byte        ; Jump if we found a length byte
        PUSH    ES                      ; Restore DS
        POP     DS
        POP     ES                      ; Restore ES
        JMP     restart_input

found_a_len_byte:
        AND     BP,0FFF1H                         ; Indicate new line from holding buffer, and no changes made to it.
        CALL    get_char                          ; Get a dummy character to readjust the SI pointer
        TEST    BYTE PTR [SI],  LENGTH_BYTE_MASK  ; Is next location a length byte
        JNE     recover_string                    ; If so (then down arrow issued) jump to recover string
        DEC     SI                                ; No, an up arrow was issued and we need to back SI down two bytes to
                                                  ;   set up for next get_char to be the length byte.
        CALL    swap_and_get_tp                   ; Back a-one
        DEC     SI
        CALL    swap_and_get_tp                   ; and a-two

recover_string:
        MOV     DS:[last_entry],SI       ; Load the address of the last accessed buffer string
        CALL    get_char                 ; Get the length character from holding buffer
        AND     AL, LENGTH_OFF_MASK      ; Mask off the length byte identifier
        MOV     AH, BYTE PTR ES:[DI-01H] ; Place Max buffer size in AH
        CMP     AL,AH                    ; Is text string smaller than max buffer size?
        JB      continue_recovery        ; If so then continue recovery
        MOV     AL,AH                    ; Uh-oh, take the max buffer size as the count of chars to restore

continue_recovery:
        STOSB                           ; Save the length count
        CBW                             ; Get rid of high portion of AX
        XCHG    AX,CX                   ; Place the count in CX
        PUSH    CX                      ;    and save it for later

load_chr_and_display:
        CALL    get_char                ; Get a character from the holding buffer
        STOSB                           ; Store this character in the input buffer
        CALL    display_and_test        ; Display this character
        LOOP    load_chr_and_display    ; Continue until all characters are done
        POP     DI                      ; Place the count of the number of characters in the
                                        ;    string into DI
        MOV     SI,DI                   ; Require the current pointer to be just past the end
        PUSH    ES                      ; Restore DS
        POP     DS
        POP     ES                      ; Restore ES

lcad_ret:
        RET

;*********************************************************************************** Control Page Down
cntrl_page_down:
        TEST    BP,0006H             ; Are we on the original line or have we made mods
        JNE     lcad_ret             ; If so then do nothing
        PUSH    DS                   ; Save some registers
        PUSH    ES
        PUSH    BX
        CALL    home_key             ; Move to start of line
        CALL    cntrl_end            ; Delete to the end of the line
        PUSH    CS                   ; Set ES register to CS                                                ** change to mov **
        POP     ES
        PUSH    CS                   ; Set DS register to CS
        POP     DS
        MOV     DI,DS:[last_entry]   ; Get address of last string accessed in holding buffer
        PUSH    DI                   ; Save it.
        MOV     SI,DI                ; Point the source index to it.

skip:
        CALL    get_char             ; Get a character from the text buffer
        CMP     AL, CR               ; Is it a carriage return?
        JNE     skip                 ; If n~r~_ot keep going

move_down:
        CMP     SI,DS:[next_entry]   ; Are we at the next available location in buffer
        JE      pad_crs              ; If so then break out of loop
        CALL    get_char             ; Get this character
        CALL    save_char            ;    and move it down in the holding buffer.
        JMP     SHORT move_down      ; Continue the loop.

pad_crs:
        MOV     AL, CR               ; Load AL with a carriage return
        MOV     [DI],AL              ; and into the buffer
        MOV     BX,DI                ; Now reset the base pointer one beyond last string in holding buffer.
        XCHG    BX,DS:[next_entry]   ; Put the old value in BX and the new value in place
        POP     SI                   ; Restore the pointer to last string accessed

continue_pad_cr:
        CMP     BX,DI                   ; Are we at the old next_available slot yet?
        JE      after_pad_cr            ; If yes the break out
        CALL    save_char               ; No, save the carriage return
        JMP     SHORT continue_pad_cr   ; Keep going

after_pad_cr:
        DEC     SI                      ; Point to just before this entry (so Down arrow will pick it up)
        MOV     DS:[last_entry],SI      ; Save it as last accessed text entry
        POP     BX                      ; Restore registers.
        POP     ES
        POP     DS
        JMP     da1                     ; Go perform a down arrow operation

;*********************************************************************************** Carriage Return
cr_key:
        AND     BYTE PTR ES:[kbd_flag], INSERT_OFF_MASK  ; Turn off insert mode
        CALL    set_cursor               ; Change the cursor on the screen
        POP     AX                       ; Pop the fake return address off the stack (so we really return)
        CALL    move_to_end              ; Move the cursor to the end of the line
        MOV     AL, CR                   ; Move a CR into AL
        CALL    display_one_char         ; Display it
        MOV     [BX+DI],AL               ; Add the CR to the input buffer
        MOV     AX,DI                    ; Move the length into AX
        MOV     [BX-01H],AL              ; Now move it into the length byte of the input buffer
        MOV     SI,BX                    ; Point the Source index to the input buffer
        CMP     AL,02H                   ; Are there at least two characters?                         ** remove this? **
        JBE     crk_ret                  ; If not then just forget the save
        PUSH    CS                       ; Set ES to value in CS
        POP     ES
        INC     WORD PTR CS:[last_entry] ; Bump the pointer to the strings location in the text buffer
        TEST    BP,0002H                 ; Have changes been made to this line?
        JE      crk_ret                  ; If not then we are through
        MOV     DI,CS:[next_entry]       ; Point the destination to the next available slot
        OR      AL,  LENGTH_BYTE_MASK    ; Add in the length byte bit mask

save_string:
        CALL    save_char                ; Add it to the holding buffer
        CMP     AL, CR                   ; Is this a carriage return?
        JE      after_save_string        ; If so, break out of loop
        LODSB                            ; Get the next character from the input buffer
        JMP     SHORT save_string

after_save_string:
        MOV     CS:[next_entry],DI       ; Save the new pointer to the text holding buffer

omit_partial_string:
        CMP     CS:[DI],AL                 ; Is it a carriage return?
        JE      after_omit_partial         ; If so we are finished
        CALL    save_char                  ; No, that means there is a partial string here
        JMP     SHORT omit_partial_string  ;    so fill with CRs until next CR is found

after_omit_partial:
        MOV     CS:[last_entry],DI

crk_ret:
        RET

get_char:                        ; Obtain a character from the text holding buffer
        CALL    swap_and_get_tp  ; First we must reverse SI and DI pointers
        LODS    CS:[SI]          ; Load the character from the text holding buffer into AL

swap_and_get_tp:                 ; Reverse SI and DI pointers because
        XCHG    SI,DI            ;    get_text_pointer assumes that DI indexes
        CALL    get_text_pointer ;    into the text holding buffer and not SI
        XCHG    SI,DI            ; Verify legal pointer into holding buffer
        RET

save_char:                        ; Add a character to the text holding buffer
        CALL    get_text_pointer  ; Verify correctness of pointer
        STOSB                     ; Move the character in AL to the text holding buffer

get_text_pointer:                   ; Obtain a legal pointer into the text holding buffer
        CMP     DI,CS:[buffer_bot]  ; Is the current pointer too small?
        JNB     gtp1                ; If not, then continue
        MOV     DI,CS:[buffer_top]  ; Yes, set to upper limit
        DEC     DI                  ;    and decrement one

gtp1:
        CMP     DI,CS:[buffer_top]  ; Is the current pointer too big?
        JB      gtp_ret             ; If not jump to end
        MOV     DI,CS:[buffer_bot]  ; Yes, set to lower limit

gtp_ret:
        RET

;*********************************************************************************** Control Page Up
cntrl_page_up:                         ; Control Page Up service begins here
        CALL    home_key               ; Go to start of line
        CALL    cntrl_end              ; And delete forward
        PUSH    DS                     ; Save DS
        MOV     AX,CS                  ; Set DS and ES to value in CS
        MOV     DS,AX
        MOV     ES,AX
        MOV     DI,DS:[buffer_bot]     ; Get base address of text buffer
        MOV     DS:[last_entry],DI     ; Set current pointer into text buffer to base
        MOV     DS:[next_entry],DI     ; Set next new pointer into text buffer to base
        MOV     CX, TEXT_BUFFER_SIZE   ; Set count to size of text holding buffer
        MOV     AL, CR                 ; Set AL with CR and fill holding buffer
        repz STOSB                     ;    with carriage returns
        POP     DS                     ; Restore DS
        JMP     restart_input

; Data area
start_off    db      0h
current_col  db      0h
last_entry   dw      TEXT_BUFFER_START
next_entry   dw      TEXT_BUFFER_START
buffer_bot   dw      TEXT_BUFFER_START
buffer_top   dw      TEXT_BUFFER_END
aux_last     dw      AUX_BUFFER_START
aux_next     dw      AUX_BUFFER_START
aux_bot      dw      AUX_BUFFER_START
aux_top      dw      AUX_BUFFER_END

initialize:

DOSED   ENDP
CSEG    ENDS
        END  DOSED
