; ANSI1-7ASM  Revised 11/28/88 Garry G. Kraemer
;
;   A problem existed with version 1-6 when the sysop exited to DOS from
;   CHAT and returned, Linefeeds would not be displayed on the CRT.
;   The text would overwrite on the same line.  After several hours of
;   intense debugging, I have placed a few lines of code into the .ASM
;   file that will add a LineFeed (LF or CHR$(10)) to STRNG$ if it
;   does not end with one.  I assume that if I find a CR and am NOT at
;   the end of the string, a LF follows!!
;
;   Changed lines reflect GGK in the right column
;
;   Garry G. Kraemer    520 El Portal   Merced, CA
;   WINTONS LOCAL RBBS 9758 N SHAFFER RD WINTON, CA 95388
;   2400/1200/300 24hrs 400 days a year (209) 358-6154
;
; ANSI1-6ASM  Revised 10/28/87 Jon Martin fix boundary bug
; ANSI1-5ASM  Revised 8/24/85 Dave Terry for QuickBasic Compiler
; ANSI1-4ASM  Revised 8/23/85 Dave Staehlin

ANSI_PRNT SEGMENT PUBLIC 'CODE'         ;By  David W. Terry
          ASSUME CS:ANSI_PRNT           ;    3036 So. Putnam Ct.
          PUBLIC ANSI                   ;    West Valley City, UT 84120

;                      Screen scroll mods by David C. Staehlin
;                                            5430 Candle Glow NE
;                                            Albuquerque, NM 87111
;
;                                       Data (505) 821-7379 24 Hrs, 2400 Baud
STRG_LEN          DW 0                  ;CHANGED TO LENGTH OF STRING PASSED
VID_PAGE          DB 0                  ;Active video page
;
;
ANSI      PROC    FAR
          PUSH    BP
          MOV     BP,SP
;
          MOV     SI,10[BP]         ;GET STRING DESCRIPTOR
          MOV     BL,[SI+ 2]        ;REARRANGE LOW/HIGH BYTES
          MOV     BH,[SI+ 3]        ;NOW BX HOLDS THE ADDRESS OF THE STRING
          MOV     AX,[SI]           ;GET STRING LENGTH
          ADD     AX,BX             ;ADD INITIAL OFFSET (BX) TO LENGTH
          MOV     STRG_LEN,AX       ;STORE OFFSET PLUS LENGTH
;
          PUSH    BX                ;SAVE BX
          MOV     AH,15             ;Get current video state
          INT     10H               ;DO INTERRUPT
          MOV     VID_PAGE,BH       ;Save it
          POP     BX                ;RESTORE BX
;
          MOV     AH,02             ;SET UP FOR FUNCTION CALL 02H
LOOP:
          MOV     DL,[BX]           ;SET DL TO CHARACTER TO PRINT
          PUSH    DX                ;Save the character in AX 'till we check..
          CALL    WHERE_ARE_WE      ; where the cursor is.......
          CMP     DH,17H            ;Row 24?
          JL      NOPE              ; Jump if less......
          CMP     DX,174FH          ;Row 24 column 79 ?
          JZ     NEXT1              ;YES, JUMP TO NEXT 1
          CMP     DH,18H            ;Row 25?
          JZ      NOPE              ;Don't scroll line 25
;         DEC     BX                ; Else backup one character
;         JMP     SCROLL2           ; And go scroll the screen
;
; program never executes thru NEXT2!!  Trust ME!                            GGK
;
NEXT2:    POP     DX                ;And restore the stack to where it was
          CMP     DL,0AH            ;Do we have a line feed?
          JZ      SCROLL            ; Yup - scroll this sucker!
          CMP     DL,0DH            ;  How about a carriage return?
          JNZ     NOPE1             ;  Nope - just go display it.......
          INC     BX                ;  Yup - see if next char is a line feed
          MOV     DX,[BX]
          CMP     DL,0AH            ;  Well, is it?
          JZ      SCROLL            ;  It sure is - let's go scroll
          DEC     BX                ;  Oops - just a carriage return
          JMP     SCROLL            ;  But let's go scroll it anyway
;
NEXT1:    POP     DX                ; save DX
          INT     21H               ; print char using interrupt
          CALL SCROLLIT
          JMP     EXIT1
;
NOPE:     POP     DX
NOPE1:    INT     21H               ;Else just display it
SKIPIT:   INC     BX                ; point to next char
          CMP     DL,0DH            ; WAS LAST CHAR A CR?                   GGK
          JNZ     NOTCR             ; NO, jump to not CR                    GGK
          CMP     BX, STRG_LEN      ; AT END OF STRING?                     GGK
          JB      LOOP              ; NO, CONTINUE - NEXT MUST BE A LF!!    GGK
          MOV     DL,0AH            ; ELSE AT END OF STRING SO WE ADD A LF! GGK
          INT     21H               ; DO INTERRUPT AND DISPLAY IT!          GGK
          JMP     EXIT1             ; AND EXIT                              GGK
;                                                                           GGK
;                                                                           GGK
NOTCR:    CMP     BX,STRG_LEN       ; Test 'AT END OF STRING' ?             GGK
          JB      LOOP              ; NO, LOOP UNTIL ALL CHARS PROCESSED
;
EXIT1:    MOV     AH,03             ;SET UP FOR ROM-BIOS CALL (03H)
          MOV     BH,VID_PAGE       ;TO READ THE CURRENT CURSOR POSITION
          INT     10H               ;  DH = ROW   DL = COLUMN
          INC     DH                ;ADD 1 TO ROW (BECAUSE TOP OF SCREEN = 0)
          INC     DL                ;ADD 1 TO COL (BECAUSE POS 1 = 0)
;
          MOV     SI,[BP]+ 8
          MOV     [SI],DH           ;PASS BACK ROW COORDINATE
          MOV     SI,[BP]+ 6
          MOV     [SI],DL           ;PASS BACK COLUMN COORDINATE
;
          POP     BP
          RET     6
ANSI      ENDP

Where_Are_We:                       ;Get the current cursor position
          PUSH    AX                ;Save the registers
          PUSH    BX
          PUSH    CX
          MOV     AH,03             ;SET UP FOR ROM-BIOS CALL (03H)
          MOV     BH,VID_PAGE       ;TO READ THE CURRENT CURSOR POSITION
          INT     10H               ;  DH = ROW   DL = COLUMN
          POP     CX                ;Restore the registers
          POP     BX
          POP     AX
          RET                        ;And go back from wence we came
;
SCROLL2:  POP     DX                ;Put the stack like it was
SCROLL:   CALL    SCROLLIT          ;Scroll the screen
          JMP     SKIPIT
;
SCROLLIT: PUSH    AX                ;Save the registers that will be affected
          PUSH    BX
          PUSH    CX
          PUSH    DX
          PUSH    BP
          MOV     AH,2              ;Now set cursor position to 24,0
          MOV     DX,1700H          ;so we can get the proper character
          MOV     BH,VID_PAGE       ;attribute
          INT     10H
          MOV     AH,8              ;Get the current character attribute
          MOV     BH,VID_PAGE
          INT     10H
          MOV     BH,AH             ;Transfer the attribute to BH for next call
          MOV     AH,6              ;Otherwise scroll 24 lines
          MOV     AL,1              ; Only blank line 24
          MOV     CX,0000H          ; Begin scroll at position 0,0
          MOV     DX,174FH          ; End scroll at Line 24, Col 79
          INT     10H               ; And do it.......
          MOV     AH,2              ;Now set cursor position to 24,0
          MOV     DX,1700H
          MOV     BH,VID_PAGE
          INT     10H
          POP     BP
          POP     DX                ;Restore the stack like it was
          POP     CX
          POP     BX
          POP     AX
          RET
;
ANSI_PRNT ENDS
          END

