home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / assemblr / library / sampler0 / dos_ed.asm < prev    next >
Assembly Source File  |  1987-10-30  |  61KB  |  1,207 lines

  1.         PAGE    60,132
  2. ;***************************************************************************
  3. ; General comments
  4. ;***************************************************************************
  5. ; The following comprises the disassembled and documented version of DOS-ED
  6. ; as it exists on Compuserve's XA6 data base.  If one reassembles this
  7. ; program one will obtain the exact version of DOS-ED.COM that exists on
  8. ; that database.  No attempt has been made to make improvements to this code
  9. ; other than to indicate in the margin were some could (and probably should)
  10. ; be made.  If you notice that the program sizes are different between this
  11. ; reassembled and relinked version and the version that has been generated
  12. ; from the HEX file on CIS, that is because there is some trailing garbage
  13. ; on the CIS file.  You can strip it off in the debugger and the files will
  14. ; compare exactly.
  15. ;
  16. ; Even after disassembling and documenting this code I have a few questions
  17. ; about what was being done in places.  If my comments seem spurious at
  18. ; times, then just take them with a grain of salt.  They should help you
  19. ; understand this code for the most part.
  20. ;
  21. ; When linking this program you should expect to receive a No Stack warning
  22. ; message along with an Unsatisfied external error on DOS_RETURN.  These
  23. ; are normal and should be ignored.
  24. ;
  25. ; DOS-ED is a fine piece of programming performed by Jack Gersbach.
  26. ; This disassembly and documentation was done by myself.
  27. ;                                     - Scott W. Killen
  28. ;
  29. ;***************************************************************************
  30. ; Definitions and commentary on conventions in coding
  31. ;***************************************************************************
  32. ; Register usage:  (Most common (but not exclusive) uses are listed)
  33. ; AX, DX, CX - Used for many reasons
  34. ; DH - Usually current row on crt
  35. ; DL - Usually current col on crt
  36. ; SI - Usually points to offset of current character in 
  37. ;                    input buffer (first character is offset 0)
  38. ; DI - Usually has the value of one of the following:
  39. ;      * The number of characters currently in the input buffer   *or*
  40. ;      * Points to a destination in the text holding buffer
  41. ; BX - Usually contains the address at which the first character in the input 
  42. ;                                buffer is located.
  43. ;         (The two characters before this are the max buffer size and length
  44. ;                               of string characters.)
  45. ; BP - Usually a register of flags organized as bits |01234567| where:
  46. ;      Bits 0-3 have no function
  47. ;      Bit 4 - Off means the input buffer has been altered since interrupt 
  48. ;        processing began.  On means *only* lateral cursor positioning
  49. ;            commands have been issued since interrupt processing began.
  50. ;      Bit 5 - Off means previous line from holding buffer, On means original
  51. ;           line
  52. ;      Bit 6 - Off means no changes to current line in input buffer, On means
  53. ;           changes have been made
  54. ;      Bit 7 - Applies to the redisplay of lines on the screen after an 
  55. ;           intra-line edit operation
  56. ;          Off means line wasn't shortened therefore no trailing blanks needed
  57. ;          On means line is now shorter and blanks are needed over trailing 
  58. ;           characters
  59. ;
  60. ; Memory Usage:
  61. ; ES:[0450H] - Contains current cursor position in Bios data area
  62. ; ES:[044AH] - Contains # of columns of current crt screen in Bios data area
  63. ; ES:[0417H] - Keyboard flag, containing insert, shift, num lock, scroll lock
  64. ;         etc in Bios data area
  65. ;                   insert flag bit is 80h
  66. ;
  67. ; CS:[inline_mod1+1] - Jump return address to normal DOS funcion processing
  68. ; CS:[inline_mod2+1] - Current cursor definition (start/stop lines)
  69. ; CS:[inline_mod3+1] - Screen location of end of line (row/col)
  70. ; CS:[inline_mod4+2] - Higher of DS or CS on entry into interrupt.
  71. ; CS:[inline_mod5+2] - Maximum size of input buffer
  72. ;
  73. ; start_off  - Offset of start of input buffer on screen (example if prompt 
  74. ;         is A> then screen column position
  75. ;                   of input buffer start would be 2
  76. ; current_col - Current column position on screen (1st column is 0)
  77. ; last_entry - Address (offset) of last string accessed in text buffer
  78. ; next_entry - Address (offset) of next available block in text buffer
  79. ; buffer_bot - Base address of text buffer
  80. ; buffer_top - Top address of text buffer
  81. ; aux_last  \
  82. ; aux_next   \ Same as previous four except for auxiliary buffer
  83. ; aux_bot    /
  84. ; aux_top   /
  85. ;
  86.  
  87. ; Character equates
  88. ACK              equ  06h  ; Acknowledge character (Cntrl F)
  89. BELL             equ  07h  ; Bell character        (Cntrl G)
  90. BACKSPACE        equ  08h  ; Backspace character
  91. TAB              equ  09h  ; Tab character
  92. ESCCHAR          equ  1Bh  ; Escape character
  93. BLANK            equ  20h  ; Space character
  94. CR               equ  0dh  ; carriage return
  95. LF               equ  0ah  ; Line feed
  96. HAT              equ  5eh  ; "^" character
  97. SMALLA           equ  61h  ; "a" character
  98. LEFT_CURLY_BRACE equ  7Bh  ; "{" character
  99. CNTL_BACKSPACE   equ  7fh  ; Control and backspace pressed simultaneously
  100.  
  101. ; Masks
  102. INSERT_ON_MASK   equ  80h  ; Insert key bit on, corresponding to keyboard
  103.                ; status word
  104. INSERT_OFF_MASK  equ  7fh  ; Insert key bit off, corresponding to keyboard
  105.                ; status word
  106. LENGTH_BYTE_MASK equ  80h  ; Mask to identify the text string length bit in
  107.                ; text buffer
  108. LENGTH_OFF_MASK  equ  7fh  ; Mask to turn of the length byte identifier
  109. UPPER_CASE_MASK  equ  40h  ; Convert control character to upper case character
  110. LOWER_CASE_MASK  equ  20h  ; Convert upper case character to lower case
  111.                ; character
  112.  
  113. ; Physical characteristics
  114. ROWS_ON_CRT       equ 19h               ; Ordinal number of lines on crt
  115. LAST_ROW_ON_CRT   equ  ROWS_ON_CRT - 1  ; Offset of last line on crt
  116.                     ; (top line is line 0)
  117. MONO_CUR_DEF      equ  0B0Ch            ; Start, stop lines of cursor
  118. MONO_CUR_STOP     equ  0Ch              ; Stop line for standard cursor
  119. GRAPHICS_CUR_DEF  equ  0607h            ; Start, stop lines of cursor for
  120.                     ; graphics device
  121. GRAPHICS_CUR_STOP equ  07h              ; Stop line for standard cursor for
  122.                     ; graphics device
  123. TEXT_BUFFER_START equ 60h               ; Start address for text holding
  124.                     ; buffer
  125. TEXT_BUFFER_END   equ 160h              ; End address for text holding buffer
  126. TEXT_BUFFER_SIZE  equ TEXT_BUFFER_END-TEXT_BUFFER_START ;Extent of text buffer
  127. BOTH_BUFFS_SIZE   equ TEXT_BUFFER_SIZE+TEXT_BUFFER_SIZE ;Combined buffer size
  128. AUX_BUFFER_START  equ 160h             ;Auxiliary holding buffer start address
  129. AUX_BUFFER_END    equ 260h              ;Auxilliary holding buffer end address
  130.                                  ;*NOTE* TEXT_BUFFER_END - TEXT_BUFFER_START =
  131.                                         ; AUX_BUFFER_END - AUX_BUFFER_START
  132.  
  133. ; Bios interrupt 10 functions
  134. SET_CURSOR_TYPE  equ  01h
  135. SET_CURSOR_POSN  equ  02h
  136. READ_CURSOR_POSN equ  03h
  137. READ_VIDEO_STATE equ  0fh
  138.  
  139. ; Dos interrupt 21 functions
  140. INPUT_CHR_NOECHO  equ  08h
  141. OUTPUT_CHR        equ  02h
  142.  
  143. ;***************************************************************************
  144. ; BIOS data segment definition
  145. ;***************************************************************************
  146. BIOSEG  SEGMENT at 0h
  147.         org 417h
  148.         kbd_flag     db  ?
  149.         org 44ah
  150.         crt_cols     dw  ?
  151.         org 450h
  152.         cursor_posn  dw  ?
  153. BIOSEG  ends
  154.  
  155. ;***************************************************************************
  156. ; DOS-ED code segment begins
  157. ;***************************************************************************
  158. CSEG    SEGMENT
  159.         ASSUME CS:CSEG
  160.         ORG 100H
  161. DOSED   PROC NEAR
  162.  
  163.         MOV     SI,offset loadlabel    ;Source of code to move is at loadlable
  164.         MOV     DI,offset initialize   ;Destination is at end of file
  165.                        ;             at initialize
  166.         MOV     CX,offset line_table   ; Above the code to be moved is 
  167.                        ; linetable
  168.         SUB     CX,SI                  ; The difference is the amount of code
  169.                        ;               to be moved
  170.         repz MOVSB                     ; Move it!!
  171.         JMP     initialize             ; Now go do it.
  172.  
  173. loadlabel:
  174.         XOR     AX,AX                  ; Clear AX
  175.         MOV     DS,AX                  ; Prepare to save original interrupt
  176.         MOV     SI,0084H               ; Source for INT 21h as provided for
  177.                        ; in the interrupt table
  178.         MOV     DI, offset [inline_mod1+1]  ; Destination in the code segment
  179.                         ; for moving this pointer
  180.         MOVSW                               ; Move the two word address
  181.         MOVSW
  182.         MOV     AX, offset entry_point ; Move this programs starting address
  183.                        ; into the dos interrupt slot
  184.         MOV     [SI-04H],AX            ; Move offset in line
  185.         MOV     [SI-02H],CS            ; Move segment value in line
  186.         MOV     DI, TEXT_BUFFER_START  ; Working buffer begins at offset 60h
  187.                        ; which is Formatted parameter
  188.         MOV     CX, BOTH_BUFFS_SIZE    ; area 1 in the Program Segment Prefix.
  189.         MOV     AL, CR                 ; Fill 512 bytes with CR characters.  
  190.                        ; Note that this technique uses
  191.         repz STOSB                     ;   161 bytes of PSP for storage!
  192.         MOV     DX, offset initialize  ; Dos may load above this address
  193.         INT     27H                    ; Terminate but stay resident
  194.  
  195. line_table      db  300 dup (?)
  196.  
  197. entry_point:
  198.         CMP     AH,0AH               ; Is this function 10?
  199.         JE      wrapper              ; Nope, continue with normal Dos 21 Int
  200.         EXTRN   DOS_RETURN:FAR
  201.  
  202. inline_mod1:
  203.         JMP     DOS_RETURN           ; This code is modified in line!
  204.                                      ;    Go to normal Dos function handling.
  205.  
  206. wrapper:
  207.         PUSH    AX
  208.         PUSH    BX
  209.         PUSH    CX
  210.         PUSH    DX
  211.         PUSH    SI
  212.         PUSH    DI
  213.         PUSH    BP
  214.         PUSH    DS
  215.         PUSH    ES
  216.         STI
  217.         CALL    begin_dosed
  218.         POP     ES
  219.         POP     DS
  220.         POP     BP
  221.         POP     DI
  222.         POP     SI
  223.         POP     DX
  224.         POP     CX
  225.         POP     BX
  226.         POP     AX
  227.         MOV     AL,00H
  228.         IRET
  229.  
  230. ;***************************************************************************
  231. ; Extended keystroke recognition and branching tables
  232. ;***************************************************************************
  233.                 ; Table 1 of extended keyboard function codes
  234. table1:
  235. t1_1    db  0fh ; Back Tab
  236. t1_2    db  47h ; Home key
  237. t1_3    db  48h ; Up arrow
  238. t1_4    db  4bh ; Left arrow
  239. t1_5    db  4dh ; Right arrow
  240. t1_6    db  4fh ; End key
  241. t1_7    db  50h ; Down Arrow
  242. t1_8    db  53h ; Del key
  243. t1_9    db  73h ; Cntrl Left Arrow
  244. t1_a    db  74h ; Cntrl Right Arrow
  245. t1_b    db  75h ; Cntrl End
  246. t1_c    db  77h ; Cntrl Home
  247. t1_d    db  76h ; Cntrl PgDn
  248. t1_e    db  84h ; Cntrl PgUp
  249. t1_f    db  00h ; ?
  250.                     ;Table 2 indexes correspond to table 1 indexes
  251.                     ;and points to code address where the function is handled.
  252. table2:
  253. t2_f    dw offset error_return        ;    0ah, 05h   ; ?
  254. t2_e    dw offset cntrl_page_up       ;    74h, 07h   ; Cntrl PgUp
  255. t2_d    dw offset cntrl_page_down     ;   0a9h, 06h   ; Cntrl PgDn
  256. t2_c    dw offset cntrl_home          ;    0bh, 05h   ; Cntrl Home
  257. t2_b    dw offset cntrl_end           ;    27h, 05h   ; Cntrl End
  258. t2_a    dw offset cntrl_right_arrow   ;    41h, 05h   ; Cntrl Right Arrow
  259. t2_9    dw offset cntrl_left_arrow    ;    83h, 05h   ; Cntrl Left Arrow
  260. t2_8    dw offset del_key             ;   0edh, 05h   ; Del key
  261. t2_7    dw offset down_arrow          ;    44h, 06h   ; Down Arrow
  262. t2_6    dw offset end_key             ;   0e4h, 04h   ; End key
  263. t2_5    dw offset right_arrow         ;    67h, 05h   ; Right arrow
  264. t2_4    dw offset left_arrow          ;    99h, 05h   ; Left arrow
  265. t2_3    dw offset up_arrow            ;    43h, 06h   ; Up arrow
  266. t2_2    dw offset home_key            ;   0e1h, 05h   ; Home
  267. t2_1    dw offset backtab             ;    8dh, 05h   ; Backtab
  268.  
  269. ;***************************************************************************
  270. ; Display and output services
  271. ;***************************************************************************
  272. screen_and_display:                 ; Screen out control characters of form ^x
  273.         CMP     AL, BLANK           ; Compare AL to blank character
  274.         JNB     display_one_char    ; If we have a printable character go to
  275.                     ;                     display routine
  276.         CMP     AL, TAB             ; Is this a forward tab?
  277.         JE      display_one_char    ; If so, go display.
  278.         PUSH    AX                  ; No, this is a "normal" control character
  279.         MOV     AL,HAT              ; Place a "^" character in AL
  280.         CALL    display_one_char    ; Print the "^" out.
  281.         POP     AX                  ; Now convert the Control character to its
  282.         OR      AL, UPPER_CASE_MASK ; upper case equivalent and print it.
  283.                     ; Result is "^E" construct for 
  284.                     ; representing control characters.
  285.  
  286. display_one_char:
  287.         CMP     AL, BLANK           ; Does AL contain a blank character
  288.         JB      display_cntrl_chr   ; Jump if we have a control character
  289.  
  290. ready_display:
  291.         CMP     AL, CNTL_BACKSPACE    ; Don't increment column counter if this
  292.         JE      output_to_display     ;    is a control Backspace character
  293.         INC     BYTE PTR CS:[current_col]    ; Increment column position 
  294.                      ; because we received something printable
  295. output_to_display:
  296.         PUSH    DX                   ; Save the DX register and set up the
  297.         XCHG    AX,DX                ;    AH register for a DOS function 2
  298.         MOV     AH,  OUTPUT_CHR              ;     (Display output) call.
  299.         INT     21H
  300.         XCHG    AX,DX                        ; Restore the AX register
  301.         POP     DX                           ;    and restore the DX register
  302.         RET
  303.  
  304. display_cntrl_chr:                    ; Process a control character for output
  305.         CMP     AL, CR                ; Is this a carriage return character?
  306.         JE      cr_out                       ; If so go take care of it
  307.         CMP     AL, BACKSPACE                ; Is this a backspace?
  308.         JE      bs_out                ; If so we need to take care of it
  309.         CMP     AL, TAB                      ; Maybe its a tab character
  310.         JNE     relay_to_output              ; Continue if its not a tab
  311.         MOV     AL,BYTE PTR CS:[current_col] ; Set AL to current column on scr
  312.         OR      AL,0F8H                      ; Get the number of spaces to the
  313.         NEG     AL                           ;     next 8 byte boundary
  314.         PUSH    CX                           ; Save the CX register
  315.         MOV     CL,AL                        ; Place the count of blanks to
  316.                          ;               be output in CL
  317.         mov     ch, 00h                      ; Zero out high byte
  318.         JCXZ    skip_tabbing                 ; Dont do anything if count is 0
  319.  
  320. tab_loop:
  321.         MOV     AL, BLANK                    ; Ok, now print out all necessary
  322.         CALL    display_one_char             ;  blanks to reach an 8 character
  323.         LOOP    tab_loop                     ;    boundary.
  324.  
  325. skip_tabbing:
  326.         POP     CX                           ; Restore the CX register.
  327.         RET
  328.  
  329. cr_out:
  330.         MOV     CS:BYTE PTR [current_col],00H   ; Reset current column pointer
  331.                         ; to zero
  332.  
  333. relay_to_output:
  334.         JMP     SHORT output_to_display
  335.  
  336. bs_out:
  337.         DEC     BYTE PTR CS:[current_col]  ; Decrement the current column ptr
  338.         PUSH    AX                         ; Save the character in register AX
  339.         PUSH    DX                         ; Save the DX register
  340.         MOV     DX,ES:[0050H]              ; Get the Cursor position from Bios
  341.                        ;             data area
  342.         MOV     AH,ES:[004AH]              ; Get the # of CRT cols on screen
  343.                        ; from Bios data area
  344.         OR      DL,DL                      ; Are we at column zero?
  345.         JNE     bs_end                     ; If not forget the rest.
  346.         OR      DH,DH                      ; Are off the screen at the top?
  347.         JNE     set_cur_loc                ; If not then dont reset rows
  348.         MOV     DH, ROWS_ON_CRT            ; (Re)set row value to 25
  349.  
  350. set_cur_loc:
  351.         DEC     DH                         ; Decrement the row count
  352.         MOV     DL,AH                      ; Move in # of columns. 0,0 is home
  353.         PUSH    BX                         ; Save BX
  354.         MOV     BH,00H                     ; Prepare for BIOS interrupt 
  355.         MOV     AH, SET_CURSOR_POSN        ; 10 funct 2 call (Set cursor pos)
  356.         INT     10H                        ; Do it.
  357.         POP     BX                         ; Restore BX
  358.  
  359. bs_end:
  360.         POP     DX                         ; Restore DX register
  361.         POP     AX                         ; and the AX register
  362.         JMP     SHORT relay_to_output      ; and now we are done.
  363.  
  364. decrement_col_row:                  ; Wrap back if line spans two screen lines
  365.         OR      DL,DL                      ; Are we at column zero
  366.         JNE     dcr_end             ; If so then dont worry about row update
  367.         DEC     DH                         ; Yep, decrement the row pointer
  368.         MOV     DL,BYTE PTR ES:[crt_cols]  ; Get the # of CRT cols per screen
  369.                        ; from Bios data area
  370.  
  371. dcr_end:
  372.         DEC     DL                         ; Decrement the column pointer
  373.         RET
  374.  
  375. display_blank:
  376.         MOV     AL, BLANK
  377.  
  378. display_and_test:               ; Display and test for updated cursor location
  379.         PUSH    CX                            ; Save CX register
  380.         MOV     CX,ES:[cursor_posn]   ; Load CX with cursor position from Bios
  381.         CALL    screen_and_display ;Send the character in AL to output display
  382.         CMP     CH, LAST_ROW_ON_CRT           ; Are we on the last row?
  383.         JNE     dat_end              ; If not then no further tests are needed
  384.         CMP     CL,BYTE PTR ES:[cursor_posn]  ; Are we now on a new column?
  385.                     ; (alternative question is: have we scrolled?)
  386.         JBE     dat_end   ; If current location > cl then yes we have scrolled
  387.                           ;   up a line and need to decrement the line pointer
  388.         DEC     DH                            ; Decrement the line pointer
  389.  
  390. dat_end:
  391.         POP     CX                   ; Restore CX
  392.         RET
  393.  
  394. ;***************************************************************************
  395.  
  396. set_cursor:
  397.         PUSH    BX
  398.         PUSH    CX
  399.         PUSH    DX
  400.         PUSH    BP                                  ; Save registers
  401.         PUSH    SI
  402.         PUSH    DI
  403.  
  404. inline_mod2:
  405.         MOV     CX, MONO_CUR_DEF                       ; Assume Standard char def
  406.                                                        ;   (Note that this word is modified
  407.                                                        ;    in line if it is later determined
  408.                                                        ;    that a graphics board is in use)
  409.         TEST    BYTE PTR ES:[kbd_flag], INSERT_ON_MASK ; Is insert on?
  410.         JE      after_box                              ; If not then branch
  411.         MOV     CH,CL                                  ; Yep, turn the cursor into
  412.         SHR     CH,1                                   ;   a half sized box
  413.  
  414. after_box:
  415.         MOV     AH, SET_CURSOR_TYPE                 ; Set up and call Bios for
  416.         INT     10H                                    ;   support.
  417.         POP     DI
  418.         POP     SI
  419.         POP     BP                                     ; Restore Registers
  420.         POP     DX
  421.         POP     CX
  422.         POP     BX
  423.         MOV     AX,WORD PTR ES:[cursor_posn] ; Load AX with current cursor pos
  424.  
  425. inline_mod3:
  426.         CMP     AX,0888H  ; Compare current cursor position to end of line pos
  427.         JB      sc_ret    ; If less than then dont update end of line position
  428.         MOV     CS:WORD PTR [inline_mod3+1],AX  ; Modify end of line address
  429.                            ; with value of current cursor position
  430.  
  431. sc_ret:
  432.         RET
  433.  
  434. credit  db 'DOS EDITOR BY J. Gersbach',CR,LF,00
  435.  
  436.  
  437. begin_dosed:                            ; Save registers
  438.         PUSH    BX
  439.         PUSH    CX
  440.         PUSH    DX
  441.         MOV     BH,00H                ; Set up to read current cursor position
  442.         MOV     AH, READ_CURSOR_POSN  ; Cursor position returned as DH, DL
  443.                       ; is row, col
  444.         INT     10H            ;  Read the current cursor position into DH, DL
  445.         MOV     CS:[start_off],DL       ; Move current column into storage
  446.         MOV     CS:[current_col],DL     ; Move current column into storage
  447.         CMP     CL, MONO_CUR_STOP ; Check: Is current end line for cursor = 12
  448.         JB      bd2                     ; Branch if less than 12
  449.         MOV     AH, READ_VIDEO_STATE    ; Set up to return current video state
  450.         INT     10H                     ; Go get it
  451.         CMP     AL, GRAPHICS_CUR_STOP   ; Is this a 80x25 BW card
  452.         MOV     CX, MONO_CUR_DEF    ; Set start/stop lines for cursor to 11/12
  453.         JE      bd1                     ; Yes it is 80x25 BW card, branch
  454.         MOV     CX, GRAPHICS_CUR_DEF    ; No its not 80x25 card, 
  455.                     ; start/stop lines are 6/7
  456.  
  457. bd1:
  458.         MOV     AH, SET_CURSOR_TYPE     ; Set function call to set cursor type
  459.         INT     10H                     ; Do it
  460.  
  461. bd2:
  462.         MOV     CS:WORD PTR [inline_mod2+1],CX   ; Save the cursor type
  463.                          ;   setting in line
  464.         POP     DX
  465.         POP     CX
  466.         POP     BX
  467.         MOV     BX,DX             ; DX points to offset of input buffer
  468.         MOV     AL,[BX]           ; Get the number of characters in the buffer
  469.         CMP     AL,02H            ; Is it bigger than 2 characters?
  470.         JB      sc_ret            ; Nope, we have a problem here!
  471.         DEC     AL         ; Now decrement AL to get number of real characters
  472.         MOV     AH, 00H           ;    buffer han hold.   Zero out AH
  473.         MOV     CS:WORD PTR [inline_mod5+2],AX  ; AX now contains the max
  474.                   ; number of chars that the buffer can hold.
  475.         ADD     BX,02H  ; BX points to address at which to put first real char
  476.                                                 ;    in input buffer
  477.  
  478. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  479. ;;  AUTOMATIC BUFFER TOGGLE (Why, I don't know)
  480. auto_buffer_toggle:                             ;;
  481.         MOV     BP,DS             ;;  Place the DS register into BP
  482.         PUSH    DS                ;;  Save the value of the DS register
  483.         MOV     DI,CS             ;;  Place the CS register into DI
  484.         MOV     DS,DI             ;;     and also into DS
  485.         CMP     BP,DI             ;;  Compare DS : CS values
  486.         JB      abt1              ;;  If DS < CS then jump
  487.                                   ;;
  488. inline_mod4:                      ;;
  489.         CMP     DI,0888H          ;;  Compare CS : AUX    (this in-line
  490.                   ;;    address will be called AUXiliary)
  491.         JE      abt2              ;;  If its equal (if we came this way last
  492.                   ;;    time!) then go swap
  493.         JMP     SHORT after_swap_loop           ;;  If so then avoid swaps
  494.                                                 ;;
  495. abt1:                                           ;;
  496.         MOV     BP,DI             ;;  Set BP to highest register value
  497.                   ;;         (now determined to be CS)
  498.         CMP     DI,DS:WORD PTR [inline_mod4+2]  ;;  Compare CS : AUX
  499.         JE      after_swap_loop   ;;  If its not equal (if we came this way
  500.                   ;;        last time!) then go swap
  501.                                   ;;
  502. abt2:                             ;;
  503.         PUSH    CS                ;;  Now we must swap the appropriate
  504.                   ;;   memory locations to allow the editor to
  505.         POP     ES                ;;   use the other buffer (There are two 
  506.                   ;;   buffers that one can transfer between
  507.                   ;;   depending on DS : CS relationship.
  508.         MOV     SI,offset last_entry  ;;  Load SI with starting address
  509.         LEA     DI,[SI+08H]           ;;  Load DI with second starting address
  510.         MOV     CX,0004H          ;;  4 words are to be moved ... in order
  511.                   ;;  ... address of last string accessed,
  512.                                   ;;     address of highest available byte,
  513.                   ;;     base address of text holding buffer,
  514.                                   ;;     high address of holding buffer.
  515.                                   ;;  Values are initiallized to:
  516.                                   ;;     1st buffer - 60h, 60h, 60h, 160h
  517.                                   ;;     2nd buffer - 160h, 160h, 160h, 260h
  518.                                   ;;
  519. swap_loop:                        ;;
  520.         MOV     AX,[DI]           ;;  Save the value in the secondary buffer
  521.         MOVSW                     ;;  Move the primary buffer value into the
  522.                   ;;      secondary buffer position
  523.         MOV     [SI-02H],AX       ;;  Replace emptied location with saved val
  524.         LOOP    swap_loop         ;;  Go back and swap next set of values
  525.                                   ;;
  526. after_swap_loop:                  ;;
  527.         MOV     DS:WORD PTR [inline_mod4+2],BP  ;; Load AUX such that 
  528.                         ;;      AUX = Max(CS, DS)
  529.         POP     DS                              ;;  Restore DS
  530. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  531.  
  532.         MOV     BP,000CH
  533.         JMP     SHORT rib1
  534.  
  535. reinit_buffer:
  536.         MOV     BP,0004H
  537.  
  538. rib1:
  539.         XOR     SI,SI                          ; Zero out Source index
  540.         MOV     CS:WORD PTR [inline_mod3+1],SI ;Modify inline addr just above
  541.         XOR     DI,DI                          ; Zero out Destination index
  542.         MOV     ES,DI                          ; Zero out the ES register
  543.         AND     BYTE PTR ES:[kbd_flag], INSERT_OFF_MASK  ; Turn insert off
  544.  
  545. start_read_char:
  546.         AND     BP,0FFFEH       ; Turn off low bit in BP (Line may be shorter)
  547.         CALL    set_cursor      ; Set the cursor shape as per mode
  548.         XCHG    AX,DX           ; Save AX in DX
  549.         MOV     AH, INPUT_CHR_NOECHO       ; Get a character from the keyboard
  550.         INT     21H                        ; Call DOS for service
  551.         CMP     AL, ACK                    ; Is it an acknowledge character?
  552.         JE      start_read_char ; If so ... just forget it and go back
  553.         MOV     CX, offset start_read_char ; Save address of start_read_char label
  554.         PUSH    CX          ; This is a return address for a nonexistent call!
  555.         OR      AL,AL                      ; Set up for test
  556.         JNE     normal_keyboard_chr        ; Jump if non null character input
  557.  
  558. extended_keyboard_chr:
  559.         MOV     AH, INPUT_CHR_NOECHO       ; Null character, get ready to read
  560.                        ;          next character
  561.         INT     21H                        ; Get it
  562.         PUSH    ES                         ; Save ES
  563.         PUSH    CS                         ; Set ES to value in CS
  564.         POP     ES
  565.         PUSH    DI                         ; Save DI
  566.         MOV     CX,000FH                   ; Set counter to number of items in
  567.                        ;          table 1
  568.         MOV     DI, offset [table1]        ; Set starting address of table 1
  569.         repnz SCASB                        ; Scan for occurrence of second
  570.                        ;        character in table 1
  571.         POP     DI                         ; Restore DI
  572.         POP     ES                         ;    and ES
  573.         XCHG    CX,BX                      ; Let BX contain pointer to item
  574.                        ;              found in table 1
  575.         ADD     BX,BX                      ; Double it
  576.         PUSH    CS:WORD PTR [BX+table2]    ; Index into table 2 for starting
  577.                        ;           address of service code
  578.                                            ; The value is pushed onto the
  579.                        ;   stack to allow for the return
  580.                                            ;   (Without a corresponding call!)
  581.         MOV     BX,CX                      ; Restore original BX value
  582.         RET                                ; Execute the fake return
  583.  
  584.  
  585. ;***************************************************************************
  586. ; Individual service routines
  587. ;***************************************************************************
  588.  
  589. ;****************************************************************** Escape Key
  590. escape_handling:                        ; Escape character here
  591.         CALL    home_key                ; Go to start of line
  592.         CALL    cntrl_end               ; Delete to end
  593.  
  594. restart_input:
  595.         POP     DI                   ; Pop the return address off of the stack
  596.         JMP     SHORT reinit_buffer     ; Jump to reinitialize buffer and read
  597.  
  598. normal_keyboard_chr:
  599.         CMP     AL, CNTL_BACKSPACE    ; Control Backspace?
  600.         JE      nkc1                  ; if so, go to backspace handling
  601.         CMP     AL, BACKSPACE         ; Backspace?
  602.         JNE     nkc2                  ; If not continue
  603.  
  604. nkc1:
  605.         JMP     backspace_handling    ; Backspace here, take care of it
  606.  
  607. nkc2:
  608.         CMP     AL, CR                ; Is it a carriage return?
  609.         JNE     nkc3                   ; If not continue
  610.         JMP     cr_key                ; Yes, go take care of it
  611.  
  612. nkc3:
  613.         CMP     AL, ESCCHAR               ; Is it an escape character
  614.         JE      escape_handling       ; If so, go take care of it
  615.  
  616.  
  617. inline_mod5:
  618. nkc4:   CMP     DI,0888H          ; Compare DI to max buffer size 
  619.                       ;       modified in line in Begin_Dosed)
  620.         JB      printable_char        ; If less than max then continue with
  621.                       ;      printable character
  622.         MOV     AL, BELL              ; Prepare to ring the bell
  623.         JMP     display_one_char      ; Do it
  624.  
  625.  
  626. ;******************************************************* Non editing character
  627. printable_char:
  628.         AND     BP,0FFF7H             ; Turn off the no changes made flag
  629.         OR      BP,0002H              ; Turn on the changes made to 
  630.                       ;             this line flag
  631.         PUSH    AX                    ; Save AX
  632.         CALL    display_and_test      ; go display the character
  633.         MOV     DX,ES:[cursor_posn]   ;Place the current cursor position in DX
  634.         TEST    BYTE PTR ES:[kbd_flag],INSERT_ON_MASK ;Is insert mode mask on?
  635.         JE      add_chr_to_inbuf   ; If not then branch around shift up string
  636.         PUSH    DI                    ; Save the DI register
  637.  
  638. shift_up:
  639.         CMP     DI,SI                 ; Are we pointing past the end?
  640.         JBE     end_shift_up          ; Have we decended to the original point?
  641.         MOV     AL,[BX+DI-01H]        ; Move this character in input buffer up
  642.         MOV     [BX+DI],AL            ;    one byte in memory
  643.         DEC     DI                    ; Next character down
  644.         JMP     SHORT shift_up        ; Return for more
  645.  
  646. end_shift_up:
  647.         POP     DI              ; Restore original end of input buffer pointer
  648.         INC     DI              ; Increment it by one
  649.         INC     SI              ; Also increment the current character pointer
  650.         CALL    redisplay_line
  651.         DEC     SI              ; Now decrement source so that it will look
  652.                                 ;   like normal overwrite to next code section
  653.  
  654. add_chr_to_inbuf:
  655.         POP     AX                    ; Restore AX
  656.         MOV     AH,AL                 ; Move the current character into AH
  657.         XCHG    AL,[BX+SI]            ; Put it into the input buffer
  658.         INC     SI                    ; Point to next character position
  659.         CMP     DI,SI                 ; Have we gone past the end
  660.         JNB     acti1                 ; If not then forget update of DI
  661.         MOV     DI,SI                 ; DI is now reset to SI (which was >)
  662.  
  663. acti1:
  664.         AND     AL,AH          ; AND old character against new character
  665.         CMP     AL, BLANK      ; If both are printable then we are finished
  666.                                ;  because we have coundn't have shortened
  667.         JNB     acti_ret       ;  the line with the overwrite.  (eg. A over ^E
  668.                                ;  would shorten line by one character)
  669.         TEST    BYTE PTR ES:[kbd_flag], INSERT_ON_MASK  ; If insert mode was
  670.         JNE     acti_ret              ;   on then we are finished also because
  671.                                       ;   we have already printed the string
  672.         CMP     SI,DI                 ; Also we can forget if we are at the
  673.                       ;                   end of the line
  674.         JE      acti_ret             ; None of the above hold, and we may have
  675.         JMP     note_shorter_change  ;  trailing characters on the line that 
  676.                                      ;  need to be blanked over. (caused by 
  677.                      ;  overwriting a ^x diagraph or a Tab
  678.                      ;  character with a single character.)
  679. acti_ret:
  680.         RET
  681.  
  682. ;********************************************************************* End key
  683. end_key:
  684.         TEST    BP,0008H     ; Have we made any changes to this buffer?
  685.         JE      move_to_end  ; If so then go ahead an position to end of line.
  686.         AND     BP,0FFF7H    ; No changes, lets now indicate that changes have
  687.         OR      DI,DI        ;     been made, and restore the input buffer.  
  688.                  ;       Start by checking DI for zero.
  689.         JNE     move_to_end  ; Go restore if something is there.
  690.         MOV     AL,[BX-01H]  ; Get the length of the str in the holding buffer
  691.         CMP     [BX-02H],AL  ; Is it larger than the max buffer size?
  692.         JB      recycle_input ; If so then we have problems and a restart 
  693.                   ;     is necessary.
  694.         MOV     AH,00H                 ; Zero out AH
  695.         XCHG    AX,DI                  ; Move the new length into DI
  696.         CMP     BYTE PTR [BX+DI], CR   ; Is there a carriage return here
  697.         JE      move_to_end            ; If so then go ahead and restore it
  698.  
  699. recycle_input:
  700.         JMP     restart_input              ; No, we must have garbage in the
  701.                     ; input buffer, go back and restart
  702.  
  703. move_to_end:
  704.         CALL    right_arrow     ; move over one character to the right
  705.         JB      move_to_end     ; keep going if not at end
  706.  
  707. error_return:
  708.         RET
  709.  
  710. ;************************************************************ Control home key
  711. cntrl_home:
  712.         PUSH    SI             ; Save the pointer into the input buffer
  713.         CALL    home_key       ; Move to start of line
  714.         POP     SI             ; Restore pointer
  715.         MOV     CX,DI          ; Set CX to char count in string and remove the
  716.         SUB     CX,SI           ;    characters from start of line to current
  717.                    ;    position from count.
  718.         XOR     DI,DI           ; Clear out the DI register
  719.         PUSH    CX              ;   and the new count of characters.
  720.         JCXZ    after_drop_down ; If the new count of characters is zero then
  721.                 ;     nothing else to do.
  722.  
  723. drop_text_down:
  724.         MOV     AL,[BX+SI]      ; Get the current character
  725.         INC     SI              ; Advance source pointer to next character
  726.         MOV     [BX+DI],AL      ; Store it down into the next destination 
  727.                 ;                available
  728.         INC     DI              ; Increment the destination pointer
  729.         LOOP    drop_text_down  ;    and continue for the count
  730.  
  731. after_drop_down:
  732.         XOR     SI,SI                 ; Restore DI & SI
  733.         JMP     note_shorter_change   ; Now go redisplay line on screen
  734.  
  735. ;************************************************************* Control end key
  736. cntrl_end:
  737.         OR      BP,0002H                     ; Turn on the change to line flag
  738.         MOV     CX,CS:WORD PTR [inline_mod3+1]  ; Get the screen position of
  739.                          ; the last char in the screen
  740.  
  741. blank_to_end:
  742.         CMP     CX,ES:[cursor_posn]      ; Is the current screen position at 
  743.                      ;        the end of line?
  744.         JBE     after_blanking           ; If so then jump
  745.         CALL    display_blank            ; Display a blank
  746.         JMP     SHORT blank_to_end       ; and continue until end of line
  747.                      ; position on screen is reached
  748.  
  749. after_blanking:
  750.         MOV     DI,SI       ;The new line length is current offset in the line
  751.         JMP     place_cursor          ; and now place the cursor on the screen
  752.  
  753.  
  754. ;********************************************************* Control right arrow
  755. cntrl_right_arrow:                     ; Move right to start of next word
  756.         CALL    right_arrow            ; Move right one character
  757.         JNB     cra_ret                ; If at the end then fall out of loop
  758.         CALL    check_non_by_alpha     ; Check for non-alpha/alpha combination
  759.                        ; (return issued from subroutine
  760.                                          ;    if the condition is satisfied)
  761.         JMP     SHORT cntrl_right_arrow  ; continue the cycle
  762.  
  763. cra_ret:
  764.         RET
  765.  
  766. check_non_by_alpha:
  767.         MOV     AL,[BX+SI]       ; Get character
  768.         CALL    check_alpha      ; See if this is an alphabetic character
  769.         JB      cnba_ret         ; If not then we are finished
  770.         MOV     AL,[BX+SI-01H]   ; Get previous character
  771.         CALL    check_alpha      ; Is this an alpha?
  772.         JNB     cnba_ret         ; If so then we are still not happy and must
  773.                      ;  continue searching.
  774.         POP     AX               ; Pop off the fake return address if this
  775.                  ; location points to an alpha character and
  776.                  ; the one doesnt.
  777. cnba_ret:
  778.         RET
  779.  
  780. check_alpha:
  781.         OR      AL, LOWER_CASE_MASK  ; Or in lower case bit
  782.         CMP     AL, SMALLA           ; Is this the letter "a"?
  783.         JB      cnba_ret           ; It is less than the letter "a" ... return
  784.         CMP     AL, LEFT_CURLY_BRACE ; Is this the character "{"?
  785.                      ;             (one greater than "z")
  786.         CMC                         ; Complement Carry flag so its on if < "{"
  787.         RET
  788.  
  789. ;***************************************************************** Right arrow
  790. right_arrow:
  791.         CMP     SI,DI                      ; Are we past the last character
  792.         JNE     redisplay_char             ; If not then continue
  793.         RET
  794.  
  795. redisplay_char:
  796.         MOV     AL,[BX+SI]          ; Move the current character into AL
  797.         INC     SI                  ; Bump the pointer into input buffer
  798.         CALL    display_and_test    ; Redisplay that character
  799.         STC                         ; Set the carry flag
  800.         RET
  801.  
  802. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  803. L0474:  CALL    right_arrow                  ;\                             ;;
  804.         JNB     L0482                        ; \                            ;;
  805.         MOV     AL,07H                       ;  \ This code is not called.  ;;
  806.         AND     AL, BYTE PTR ES:[cursor_posn];  /                           ;;
  807.         JNE     L0474                        ; /                            ;;
  808. L0482:  RET                                  ;/                             ;;
  809. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  810.  
  811.  
  812. ;********************************************************** Control left arrow
  813. cntrl_left_arrow:
  814.         CALL    left_arrow           ; Move left one character
  815.         JB      bt_ret               ; Jump if we are at the end of the buffer
  816.         CALL    check_non_by_alpha   ; See if we are at the start of an alph
  817.                      ;         character string.
  818.         JMP     SHORT cntrl_left_arrow ; If not then loop (if we were then the
  819.                        ; return was issued from
  820.                                        ;    check_non_by_alpha)
  821.  
  822. ;***************************************************************** Backtab key
  823. backtab:
  824.         CALL    left_arrow    ; move left one character
  825.         JB      bt_ret        ; If at the start of the line then quit
  826.         MOV     AL,07H        ; set up the mask
  827.         AND     AL,DL         ; check to see if we are on an 8 byte column.
  828.         JNE     backtab       ; If not then continue left.
  829.  
  830. bt_ret:
  831.         RET
  832.  
  833.  
  834. ;***************************************************************** Left Arrow
  835. left_arrow:
  836.         OR      SI,SI                      ; Are we at the start of the line
  837.         STC                                ; Set the carry flag
  838.         JE      cnba_ret                   ; If so then do nothing
  839.         DEC     SI                         ; Move the input buffer pointer back one
  840.         CALL    decrement_col_row          ; Adjust the col row positon
  841.         CMP     BYTE PTR [BX+SI], TAB      ; Have we just run over a tab?
  842.         JE      back_over_tab              ; If so then go expand it
  843.         CMP     BYTE PTR [BX+SI], BLANK    ; Compare for printable character
  844.         JNB     la_end             ; If we have one then jump to final section
  845.         CALL    decrement_col_row          ; Decrement col row one more time
  846.                        ;  (for ^ character)
  847.         JMP     SHORT la_end               ; Finish up
  848.                                            ; Expand the tab character
  849. back_over_tab:
  850.         PUSH    SI                         ; Save the SI ptr into input buffer
  851.         MOV     CX,SI                      ; Set the count to its value
  852.         MOV     AL,CL                      ;    and also AL
  853.         MOV     AH,07H                     ;
  854.         JCXZ    no_prev_tabs; At start of line (no previous tab to align us)
  855.                             ; See if we can find another tab in front of us to
  856.                             ;   align us on screen (character after that tab
  857.                             ;   would be properly aligned on 8 byte boundary.)
  858. aalign:
  859.         DEC     SI                   ; Decrement the pointer into input buffer
  860.         CMP     BYTE PTR [BX+SI], BLANK    ; Check for printable character
  861.         JNB     align_end                  ; If found cycle in loop
  862.         CMP     BYTE PTR [BX+SI], TAB         ; Have we found another tab?
  863.         JE      sub_prev_char_cnt   ;If so then we know we are aligned so jump
  864.         DEC     AH                  ;No, this must be a control character 
  865.                     ; diagraph (^x form) so we need to subract
  866.                     ; an additional character from the
  867. align_end:                              ;    count of characters found so far.
  868.         LOOP    aalign                   ; Go back for more
  869.  
  870. no_prev_tabs:                    ; Ok, we only get here if there were no previous
  871.                                  ;    chars in input buffer or if there were no
  872.                   ;    previous tabs in the buffer
  873.         SUB     AH,CS:[start_off]; Subtract out the screen bias position
  874.                  ; for location 0 of the input buffer pointer.
  875. sub_prev_char_cnt:
  876.         SUB     AH,AL       ; These two statements remove the count of
  877.                 ;    all previous characters
  878.         ADD     CL,AH                      ;    in the buffer (either to tab boundary or start of line).
  879.                                            ;    Additional diagraph hats "^" have been previously subtracted
  880.                                            ;    from AH.
  881.         AND     CL,07H                     ; take modulo 8
  882.         JE      end_jump_tab               ; Did this tab expand into only one blank (remember we've already
  883.                                            ;    moved over one!), if so jump
  884. jump_tab:
  885.         CALL    decrement_col_row          ; Calculate new column and row on screen
  886.         LOOP    jump_tab
  887.  
  888. end_jump_tab:
  889.         POP     SI                         ; Restore input buffer pointer
  890.  
  891. la_end:
  892.         CLC                                ; Clear the carry flag
  893.         JMP     SHORT place_cursor         ; Go place the cursor on the screen
  894.         NOP
  895.  
  896.  
  897. ;*********************************************************************************** Home key
  898. home_key:                                  ; home key service begins here
  899.         CALL    left_arrow                 ; move over one
  900.         JB      pc_ret                     ; jump if back at start
  901.         JMP     SHORT home_key             ; Not there yet, keep going
  902.  
  903.  
  904. ;*********************************************************************************** Backspace key
  905. backspace_handling:                        ; backspace handling begins here
  906.         CALL    left_arrow                 ; first just move over one character
  907.         JB      pc_ret                     ; If we are already at the start of the line
  908.                                            ;    then we neednt continue
  909.  
  910. ;*********************************************************************************** Delete Key
  911. del_key:                                   ; Delete key handling begins here
  912.         OR      DI,DI                      ; Is the string length zero?
  913.         JE      pc_ret                     ; If so go to end
  914.         CMP     SI,DI                      ; Are we past the end of the string?
  915.         JE      pc_ret                     ; If so go to end
  916.         PUSH    SI                         ; Save the SI pointer to input buffer
  917.  
  918. shift_down:
  919.         CMP     SI,DI                      ; Are we past the end:
  920.         JE      after_shift_down           ; If so, finish up
  921.         MOV     AL,[BX+SI+01H]             ; Get next character up
  922.         MOV     [BX+SI],AL                 ; then shift it down into this slot
  923.         INC     SI                         ; Increment the input buffer pointer
  924.         JMP     SHORT shift_down           ;    and cycle
  925.  
  926. after_shift_down:
  927.         POP     SI                         ; Restore the input text buffer pointer
  928.         DEC     DI                         ; Decrement the length of the input buffer string
  929.  
  930. note_shorter_change:
  931.         OR      BP,0003H                   ; Indicate that we have changed and potentially shortened the string.
  932.  
  933. redisplay_line:
  934.         AND     BP,0FFF7H
  935.         PUSH    SI                       ; Save the pointer into the input buffer
  936.  
  937. display_next_char:
  938.         CMP     SI,DI                    ; Are we past the end of the string?
  939.         JNB     after_display_char       ; If so dont display
  940.         MOV     AL,[BX+SI]               ; Get the character from the input buffer
  941.         CALL    display_and_test         ; send it to the display
  942.         INC     SI                       ; update buffer pointer
  943.         JMP     SHORT display_next_char  ; continue to end
  944.  
  945. after_display_char:
  946.         CALL    set_cursor                      ; Set type of cursor, AX returns with current cursor location (end of line)
  947.         TEST    BP,0001H                        ; Is the old line longer?
  948.         JE      after_blank_pad                 ; If not then forget blanking the tail
  949.         XCHG    AX,CS:WORD PTR [inline_mod3+1]  ; Put current cursor positon in end of line indicator and
  950.                                                 ;    save that value for blanking operation
  951.         XCHG    AX,CX                           ; Put former end of line position in CX
  952.  
  953. add_blank_pad:
  954.         CALL    display_blank            ; Display a blank
  955.         CMP     CX,ES:[cursor_posn]      ; Is current cursor position now at end of line
  956.         JNBE    add_blank_pad            ; If not, then continue blanking loop.
  957.  
  958. after_blank_pad:
  959.         POP     SI
  960.  
  961. place_cursor:
  962.         MOV     AH, SET_CURSOR_POSN      ; Load AH for Bios call
  963.         PUSH    BX                       ; Save BX and CX registers
  964.         PUSH    CX
  965.         MOV     CS:[current_col],DL     ; Record current column position
  966.         MOV     BH,00H
  967.         INT     10H                     ; Call bios for service
  968.         POP     CX                      ; Restore registers
  969.         POP     BX
  970.  
  971. pc_ret:
  972.         RET
  973.  
  974.  
  975. ;*********************************************************************************** Up Arrow
  976. up_arrow:                               ; Up arrow service starts here
  977.         STD                             ; Set direction flag to decrement
  978.  
  979. ;*********************************************************************************** Down Arrow
  980. down_arrow:                             ; Down arrow service starts here
  981.         AND     BP,0FFF7H
  982.         CALL    home_key                ; Go to beginning of line
  983.         CALL    cntrl_end               ; Delete to end of line
  984.  
  985. da1:
  986.         PUSH    ES                      ; Save ES register
  987.         PUSH    DS                      ; Set ES to DS
  988.         POP     ES
  989.         PUSH    CS                      ; Set DS to CS
  990.         POP     DS
  991.         MOV     SI,DS:[last_entry]      ; Get pointer to first byte of current string in
  992.                                         ;    input buffer (from text buffer)
  993.         LODSB                           ; Obtain the character
  994.         LEA     DI,[BX-01H]             ; Load DI with the offset of the length character
  995.                                         ;    of the input buffer
  996.         MOV     CX, TEXT_BUFFER_SIZE    ; Set counter to look at each location in the text buffer
  997.  
  998. search_for_len_byte:
  999.         CALL    get_char                ; Get a character from the text holding buffer
  1000.         TEST    AL,  LENGTH_BYTE_MASK   ; Is it a length byte?
  1001.         LOOPZ   search_for_len_byte     ; Nope, go back and try again
  1002.         CLD                             ; Yep, clear the direction flag
  1003.         JNE     found_a_len_byte        ; Jump if we found a length byte
  1004.         PUSH    ES                      ; Restore DS
  1005.         POP     DS
  1006.         POP     ES                      ; Restore ES
  1007.         JMP     restart_input
  1008.  
  1009. found_a_len_byte:
  1010.         AND     BP,0FFF1H                         ; Indicate new line from holding buffer, and no changes made to it.
  1011.         CALL    get_char                          ; Get a dummy character to readjust the SI pointer
  1012.         TEST    BYTE PTR [SI],  LENGTH_BYTE_MASK  ; Is next location a length byte
  1013.         JNE     recover_string                    ; If so (then down arrow issued) jump to recover string
  1014.         DEC     SI                                ; No, an up arrow was issued and we need to back SI down two bytes to
  1015.                                                   ;   set up for next get_char to be the length byte.
  1016.         CALL    swap_and_get_tp                   ; Back a-one
  1017.         DEC     SI
  1018.         CALL    swap_and_get_tp                   ; and a-two
  1019.  
  1020. recover_string:
  1021.         MOV     DS:[last_entry],SI       ; Load the address of the last accessed buffer string
  1022.         CALL    get_char                 ; Get the length character from holding buffer
  1023.         AND     AL, LENGTH_OFF_MASK      ; Mask off the length byte identifier
  1024.         MOV     AH, BYTE PTR ES:[DI-01H] ; Place Max buffer size in AH
  1025.         CMP     AL,AH                    ; Is text string smaller than max buffer size?
  1026.         JB      continue_recovery        ; If so then continue recovery
  1027.         MOV     AL,AH                    ; Uh-oh, take the max buffer size as the count of chars to restore
  1028.  
  1029. continue_recovery:
  1030.         STOSB                           ; Save the length count
  1031.         CBW                             ; Get rid of high portion of AX
  1032.         XCHG    AX,CX                   ; Place the count in CX
  1033.         PUSH    CX                      ;    and save it for later
  1034.  
  1035. load_chr_and_display:
  1036.         CALL    get_char                ; Get a character from the holding buffer
  1037.         STOSB                           ; Store this character in the input buffer
  1038.         CALL    display_and_test        ; Display this character
  1039.         LOOP    load_chr_and_display    ; Continue until all characters are done
  1040.         POP     DI                      ; Place the count of the number of characters in the
  1041.                                         ;    string into DI
  1042.         MOV     SI,DI                   ; Require the current pointer to be just past the end
  1043.         PUSH    ES                      ; Restore DS
  1044.         POP     DS
  1045.         POP     ES                      ; Restore ES
  1046.  
  1047. lcad_ret:
  1048.         RET
  1049.  
  1050. ;*********************************************************************************** Control Page Down
  1051. cntrl_page_down:
  1052.         TEST    BP,0006H             ; Are we on the original line or have we made mods
  1053.         JNE     lcad_ret             ; If so then do nothing
  1054.         PUSH    DS                   ; Save some registers
  1055.         PUSH    ES
  1056.         PUSH    BX
  1057.         CALL    home_key             ; Move to start of line
  1058.         CALL    cntrl_end            ; Delete to the end of the line
  1059.         PUSH    CS                   ; Set ES register to CS                                                ** change to mov **
  1060.         POP     ES
  1061.         PUSH    CS                   ; Set DS register to CS
  1062.         POP     DS
  1063.         MOV     DI,DS:[last_entry]   ; Get address of last string accessed in holding buffer
  1064.         PUSH    DI                   ; Save it.
  1065.         MOV     SI,DI                ; Point the source index to it.
  1066.  
  1067. skip:
  1068.         CALL    get_char             ; Get a character from the text buffer
  1069.         CMP     AL, CR               ; Is it a carriage return?
  1070.         JNE     skip                 ; If not keep going
  1071.  
  1072. move_down:
  1073.         CMP     SI,DS:[next_entry]   ; Are we at the next available location in buffer
  1074.         JE      pad_crs              ; If so then break out of loop
  1075.         CALL    get_char             ; Get this character
  1076.         CALL    save_char            ;    and move it down in the holding buffer.
  1077.         JMP     SHORT move_down      ; Continue the loop.
  1078.  
  1079. pad_crs:
  1080.         MOV     AL, CR               ; Load AL with a carriage return
  1081.         MOV     [DI],AL              ; and into the buffer
  1082.         MOV     BX,DI                ; Now reset the base pointer one beyond last string in holding buffer.
  1083.         XCHG    BX,DS:[next_entry]   ; Put the old value in BX and the new value in place
  1084.         POP     SI                   ; Restore the pointer to last string accessed
  1085.  
  1086. continue_pad_cr:
  1087.         CMP     BX,DI                   ; Are we at the old next_available slot yet?
  1088.         JE      after_pad_cr            ; If yes the break out
  1089.         CALL    save_char               ; No, save the carriage return
  1090.         JMP     SHORT continue_pad_cr   ; Keep going
  1091.  
  1092. after_pad_cr:
  1093.         DEC     SI                      ; Point to just before this entry (so Down arrow will pick it up)
  1094.         MOV     DS:[last_entry],SI      ; Save it as last accessed text entry
  1095.         POP     BX                      ; Restore registers.
  1096.         POP     ES
  1097.         POP     DS
  1098.         JMP     da1                     ; Go perform a down arrow operation
  1099.  
  1100. ;*********************************************************************************** Carriage Return
  1101. cr_key:
  1102.         AND     BYTE PTR ES:[kbd_flag], INSERT_OFF_MASK  ; Turn off insert mode
  1103.         CALL    set_cursor               ; Change the cursor on the screen
  1104.         POP     AX                       ; Pop the fake return address off the stack (so we really return)
  1105.         CALL    move_to_end              ; Move the cursor to the end of the line
  1106.         MOV     AL, CR                   ; Move a CR into AL
  1107.         CALL    display_one_char         ; Display it
  1108.         MOV     [BX+DI],AL               ; Add the CR to the input buffer
  1109.         MOV     AX,DI                    ; Move the length into AX
  1110.         MOV     [BX-01H],AL              ; Now move it into the length byte of the input buffer
  1111.         MOV     SI,BX                    ; Point the Source index to the input buffer
  1112.         CMP     AL,02H                   ; Are there at least two characters?                         ** remove this? **
  1113.         JBE     crk_ret                  ; If not then just forget the save
  1114.         PUSH    CS                       ; Set ES to value in CS
  1115.         POP     ES
  1116.         INC     WORD PTR CS:[last_entry] ; Bump the pointer to the strings location in the text buffer
  1117.         TEST    BP,0002H                 ; Have changes been made to this line?
  1118.         JE      crk_ret                  ; If not then we are through
  1119.         MOV     DI,CS:[next_entry]       ; Point the destination to the next available slot
  1120.         OR      AL,  LENGTH_BYTE_MASK    ; Add in the length byte bit mask
  1121.  
  1122. save_string:
  1123.         CALL    save_char                ; Add it to the holding buffer
  1124.         CMP     AL, CR                   ; Is this a carriage return?
  1125.         JE      after_save_string        ; If so, break out of loop
  1126.         LODSB                            ; Get the next character from the input buffer
  1127.         JMP     SHORT save_string
  1128.  
  1129. after_save_string:
  1130.         MOV     CS:[next_entry],DI       ; Save the new pointer to the text holding buffer
  1131.  
  1132. omit_partial_string:
  1133.         CMP     CS:[DI],AL                 ; Is it a carriage return?
  1134.         JE      after_omit_partial         ; If so we are finished
  1135.         CALL    save_char                  ; No, that means there is a partial string here
  1136.         JMP     SHORT omit_partial_string  ;    so fill with CRs until next CR is found
  1137.  
  1138. after_omit_partial:
  1139.         MOV     CS:[last_entry],DI
  1140.  
  1141. crk_ret:
  1142.         RET
  1143.  
  1144. get_char:                        ; Obtain a character from the text holding buffer
  1145.         CALL    swap_and_get_tp  ; First we must reverse SI and DI pointers
  1146.         LODS    byte ptr CS:[SI] ; Load the character from the text holding
  1147.                  ;  buffer into AL
  1148.  
  1149. swap_and_get_tp:                 ; Reverse SI and DI pointers because
  1150.         XCHG    SI,DI            ;    get_text_pointer assumes that DI indexes
  1151.         CALL    get_text_pointer ;    into the text holding buffer and not SI
  1152.         XCHG    SI,DI            ; Verify legal pointer into holding buffer
  1153.         RET
  1154.  
  1155. save_char:                        ; Add a character to the text holding buffer
  1156.         CALL    get_text_pointer  ; Verify correctness of pointer
  1157.         STOSB                     ; Move the character in AL to the text holding buffer
  1158.  
  1159. get_text_pointer:                   ; Obtain a legal pointer into the text holding buffer
  1160.         CMP     DI,CS:[buffer_bot]  ; Is the current pointer too small?
  1161.         JNB     gtp1                ; If not, then continue
  1162.         MOV     DI,CS:[buffer_top]  ; Yes, set to upper limit
  1163.         DEC     DI                  ;    and decrement one
  1164.  
  1165. gtp1:
  1166.         CMP     DI,CS:[buffer_top]  ; Is the current pointer too big?
  1167.         JB      gtp_ret             ; If not jump to end
  1168.         MOV     DI,CS:[buffer_bot]  ; Yes, set to lower limit
  1169.  
  1170. gtp_ret:
  1171.         RET
  1172.  
  1173. ;*********************************************************************************** Control Page Up
  1174. cntrl_page_up:                         ; Control Page Up service begins here
  1175.         CALL    home_key               ; Go to start of line
  1176.         CALL    cntrl_end              ; And delete forward
  1177.         PUSH    DS                     ; Save DS
  1178.         MOV     AX,CS                  ; Set DS and ES to value in CS
  1179.         MOV     DS,AX
  1180.         MOV     ES,AX
  1181.         MOV     DI,DS:[buffer_bot]     ; Get base address of text buffer
  1182.         MOV     DS:[last_entry],DI     ; Set current pointer into text buffer to base
  1183.         MOV     DS:[next_entry],DI     ; Set next new pointer into text buffer to base
  1184.         MOV     CX, TEXT_BUFFER_SIZE   ; Set count to size of text holding buffer
  1185.         MOV     AL, CR                 ; Set AL with CR and fill holding buffer
  1186.         repz STOSB                     ;    with carriage returns
  1187.         POP     DS                     ; Restore DS
  1188.         JMP     restart_input
  1189.  
  1190. ; Data area
  1191. start_off    db      0h
  1192. current_col  db      0h
  1193. last_entry   dw      TEXT_BUFFER_START
  1194. next_entry   dw      TEXT_BUFFER_START
  1195. buffer_bot   dw      TEXT_BUFFER_START
  1196. buffer_top   dw      TEXT_BUFFER_END
  1197. aux_last     dw      AUX_BUFFER_START
  1198. aux_next     dw      AUX_BUFFER_START
  1199. aux_bot      dw      AUX_BUFFER_START
  1200. aux_top      dw      AUX_BUFFER_END
  1201.  
  1202. initialize:
  1203.  
  1204. DOSED   ENDP
  1205. CSEG    ENDS
  1206.         END  DOSED
  1207.