CTRLBRK_INT EQU 23H
FASTCON_INT EQU 29H

Conpnext      dd 0ffff0000h
Condevattr    dw 1000000000000100b 
Constrategy   dw offset _con_strategy
Coninterrupt  dw offset _con_interrupt
Con_device    db 'CON     ' ; Blank-padded device (or 10-byte block device sub-unit number)
; Jump table 
contable      db 9
              dw cs:con_init    ; 0 - initialize driver
              dw cs:con_err     ; 1 - media change check 
              dw cs:con_err     ; 2 - build BPB
              dw cs:con_err     ; 3 - IOCTL string output
              dw cs:con_input   ; 4 - input
              dw cs:con_input   ; 5 - nondestructive input
              dw cs:con_istat   ; 6 - input status
              dw cs:con_flush   ; 7 - input flush
              dw cs:con_output  ; 8 - output
              dw cs:con_output  ; 9 - output w/ verify

local_char db 0
local_flag db 0

CON:

con_err  proc far
         mov  ax, 3  ; invalid command
         ret
con_err  endp

con_istat proc far
         mov  al, byte ptr cs:local_flag
         ret
con_istat endp

con_input proc far
     ; fetch character from STDIN, CON, return in AL
     ; Reads (waits for) a character from the Standard Input Device.
     ; Echos that character to the Standard Output Device. If
     ; Ctrl-Break is detected, INT 23H is executed.
     ; Ext, ascii keys requrie two calls to this function
     kbhit
     or   al, al
     jz   _no_read_console
     push bx
     xor  ax, ax
     int  16h
     pop  bx
     mov  dl, al
     mov  byte ptr cs:local_char, al
     mov  byte ptr cs:local_flag, true
_no_read_console:
     ret
con_input endp

con_output proc far
     ; DL = character to send to standard output
     ; returns none
     ; Sends DL to STDOUT, Handles backspace (ASCII 8) by moving
     ; the cursor left and leaving the cursor there.
     ; If ctrl-break is detected. INT 23H is run.
     ;push bx
     ;mov  al, dl
     ;call teletype
     ;pop  bx
     call cs:fastansi
         ret
con_output endp

con_flush proc far
         mov  byte ptr cs:local_char, 0
         mov  byte ptr cs:local_flag, 0
;         mov  word ptr cs:local_char, 'C'-40h + (256* 0FFFFh)
;         mov  byte ptr cs:local_char, 'C'-40h   ; force a ^C into local buffer
;         mov  byte ptr cs:local_flag, 0ffffh    ; buffer not empty
         ret
con_flush endp

; ===========================================================================
int29 proc far              ; Interrupt 29 - FASTCONSOLE Write - Undocumented
; AL = CHAR
; ===========================================================================
      call cs:fastansi
      iret
fastcon proc far
        pushregs
        push cs
        pop  ds
        call teletype
;        mov  ah, 0eh
;        mov  bx, cs:textattr
;        int  10h  
        popregs
        ret
fastcon endp
fastansi proc far
         push ax
         call scrnattr
         pop  ax
         mov  cs:textattr, bh
         ;
         cmp  al, 1bh
         je   ANSIDRV
         mov  bl, cs:ansiidx
         or   bl, bl
         jnz  buildansi
         cmp  al, 08h
         jne  fc_echo  
fc_bs:   ; Special case
         mov  al, 8
         call fastcon
         mov  al, 32
         call fastcon
         mov  al, 8
         call fastcon
         ; call    A20Enable               ; make sure A20 is on
         ; jmpfar  OutputBS, OutputBSFixup ; call up to the HMA
         jmp  short doneansi
fc_echo:
         call fastcon         ; updates cursor position
         call cs:getxy  ; ah well, lets get it anyays
         mov  cs:doscol, dh
         mov  cs:dosrow, dl
         jmp  short doneansi
ANSIDRV:
         ; Take special action on ESC (ANSI ESCAPE)
         mov  bl, 0
         mov  cs:ansiidx, bl
buildansi:
         xor  bx, bx
         ; ansistr[i++] = ch
         mov  bl, cs:ansiidx
         mov  bp, bx
         mov  byte ptr cs:ansiseq[bp], al
         inc  cs:ansiidx
         ; build until ";"
         cmp  al, ';'
         jne  doneansi
              mov  bl, cs:ansiidx
              mov  bp, bx
              mov  byte ptr cs:ansiseq[bp], 0  
              dec  cs:ansiidx
              ; act on it - parse

         xor  bl, bl
         mov  cs:ansiidx, bl
doneansi:
         ret
ansiidx  db 0
AnsiSeq  db 15 dup(0),0
doscol   db 0
dosrow   db 0
      ret
fastansi endp
int29 endp

con_init proc far
         push es
         push ds

         push cs
         pop  ds


IFDEF (JAPANESE)
         mov  ax, 5000h    ; set 081 Japanese mode
         mov  bx, 81h
         int  10h
         mov  ax, 5000h    
         mov  bx, 81h
         int  16h
ENDIF

         mov  ax, 29h
         mov  cx, offset FASTCON_INT
         call setvector

         mov  ax, 14*0ffh+13
         int  10h
         mov  ax, 14*0ffh+10
         int  10h
         ;
_coninit_ok:
         xor  ax, ax
         jmp  short _conix
_coninit_err:
         mov  ax, -1
_conix:

         clc
         pop  ds
         pop  es
         ret


_con_strategy:

	ret
_con_interrupt:

        ret
con_init endp

Char_Input proc far
     call con_input
     ret
Char_input endp

Char_output proc far
     call con_output
     ret
Char_output endp

dir_conIO proc far
    ; Direct Console I/O
    ; Adv. I/O DL=FF input else char to AL
    ; If DL is 0ffh, this performs a "no wait" console input,
    ; returningthe Zero Flag (ZF) set <ZR> if there is no
    ; character ready. If a character is ready, returns ZF
    ; cleared (NZ) with the character that was read in AL.
    ; IF DL is anything but 0ffh, DL is sent to
    ; Standard Output. Doesn't check for Ctrl-break, call
    ; twice for extended ASCII.

    ; DL = 0 to 0feh for character to send of 0ffh to read from standard input

    cmp  dl, 0ffh
    je   Keyboard_IN
         call char_output
    jmp  dconiox
Keyboard_IN:
         ; CON No echo Input w/ wait
         ; returns character in AL from standard input
         ; Reads (waits for) a character from the standard input device,
         ; returning that character in AL. the character is not
         ; displayed. Does not check for ctrl-break, call twice for EXT.
         ; ASCII. Use fn 0bh to check status before calling (if you don't
         ; want to wait for a key).
         xor  ax, ax
         int  16h
         ; CON Input w/ wait checks CRTL-C 
         ; fetches from standard input returns in AL, if ctrl-break then
         ; INT 23H is executed. Call twice for EXT. ASCII
         cmp  al, 3
         jne  dconiox
         call cs:ctrlbreak  ; if CTRL-C call INT23
         ;_echo 08h
         ;_echo 20h
         ;_echo 08h
    ; if stdinbusy() dosidle()
dconiox:
    ret
dir_conIO endp

buf_input proc far
    ; Buffered Keyboard Input
    ;                               | 0 | 1 | 2 | ...
    ; DS:DX length prefixed buffer - MAX__________...
    ; returns DS:DX terminated by a CR and indentifies actual input
    ; length                        |MAX | LEN | 1 2 CR..
    ; Maximum DOS length is 254 bytes, but I think I can increase
    ; it to 65534 bytes
    ; Read chars to MAX-1
    ; if max-1 is reached then each char will beep until CR is
    ; entered.
    ; DOS template editing keystrokes are in effect:
    ; ESC = displays "\" and restarts the edit
    ; F3  = displays to the end of the template
    ; F5  = displays "@" and stores the line as the template
    ; INS = toggles insert mode, <- backs up and deletes, etc...
    ; execute INT 23H if ctrl-break and the buffer remains unchanged
    ; dos fn 3fh bx=0 to get a cooked string from stdin
    xor  cx, cx
    mov  di, dx
    mov  cl, byte ptr ds:[di]
    inc  di
    call getdata
    ; read_line(get_sft_idx(STDIN), get_sft_idx(STDOUT), FP_DS_DX);
    ret
buf_input endp
