Login

Subversion Repositories NedoOS

Rev

Rev 1314 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

;EXPORT:
;initstdio - init stdinhandle, stdouthandle, stdhgt
;receivechar (macro GETCHAR_) - read char from stdin (out: A=char, CY=error)
;receivechars - read chars from stdin (de=buf, hl=size, out: bc=bytes actually read (if EOF), CY=error(EOF))
;receivekey - read one byte of key from stdin (out: A=keylang, C=keynolang(???TODO), CY=error)
;getkey (macro GETKEY_) - read key from stdin (out: A=keylang, C=keynolang(???TODO), CY=error)
;yieldgetkeyloop - wait key from stdin (out: A=keylang, C=keynolang(???TODO), CY=error)
;setcolor (macro SETCOLOR_) - set color attribute (in: D=paper0..7, E=ink0..15)
;setcolor_invisible - NON-STANDARD
;setcolor_visible - NON-STANDARD
;scrolldown ;de=topyx, hl=hgt,wid ;x, wid even
;scrollup ;de=topyx, hl=hgt,wid ;x, wid even
;setxy (macro SETXY_) - set cursor position (in: de=YX, top left is 0;0)
;setx (macro SETX_) - set cursor X position (in: e=X, left is 0)
;sendchar (macro PRCHAR_) - send char to stdout (in: A=char)
;sendchars - send chars to stdout (in: de=buf, hl=size, out: A=error)
;setstdouthandle - in: A=handle
;setstdinhandle - in: A=handle
;clearrestofline - clear line after cursor
;clearrestofline_crlf - clear line after cursor, go to next line
;clearterm - print <stdiohgt> lines of spaces except one space, set cursor to 0,0

STDINBUF_SZ=255

initstdio
        ;OS_GETSTDINOUT ;e=stdin, d=stdout, h=stderr, l=hgt of stdout
        ld c,CMD_GETSTDINOUT
        call BDOS
        ld a,l
        ld (stdiohgt),a
        ld a,e
        ld (stdinhandle),a
        ld a,d
setstdouthandle
        ld (stdouthandle),a
        ret
setstdinhandle
        ld (stdinhandle),a
        ret

setstdinout
        ;OS_GETMAINPAGES ;out: dehl=номера страниц в 0000,4000,8000,c000, c=flags, b=id
        ld c,CMD_GETMAINPAGES
        call BDOS
        ld a,(stdinhandle)
        ld e,a
        ld a,(stdouthandle)
        ld d,a
;b=id, e=stdin, d=stdout, h=stderr (TODO)
        ;OS_SETSTDINOUT
        ld c,CMD_SETSTDINOUT
        call BDOS
        ret

getkey
;out: NC=no error, nz=event (a=key, l=mousebuttons, de=mouxexy)
getkey0
        xor a
        ld (wasmouseevent),a
        call receivekey
         ret c ;error
        ld hl,(term_prfsm_curstate)
        dec l
        jr nz,getkey0 ;пока не примем кнопку до конца
        inc l ;nz
;был mouse event? считаем за нажатие, а приложение будет смотреть координаты и кнопку мыши
stdio_mousebuttons=$+1
        ld l,0
stdio_mousex=$+1
stdio_mousey=$+2
        ld de,0
wasmouseevent=$
        ret ;NC=no error, nz=event ;/nop
        or a ;z/nz
        ret

yieldgetkeyloop
;wait key from stdin (out: A=keylang, C=keynolang(???TODO), CY=error)
;в одном фрейме может прийти много кнопок (управляющий esc-код)!
        ;jr yieldgetkey_afteryield
;yieldgetkey_nokey
;может быть, мы в середине esc-кода? тогда надо yieldgetkeyloop
        ;ld a,(term_prfsm_curstate)
        ;dec a
        ;jr nz,yieldgetkeyloop
        ld c,CMD_YIELD
        call BDOS       ;YIELD
        call getkey
        ret c ;error
        ;ret nz ;event
        ;or a ;cp NOKEY ;keylang==0?
        ;jr nz,$+3
        ;cp c ;keynolang==0?
        jr z,yieldgetkeyloop ;no event
         scf
         ccf ;no error
        ret
;yieldgetkey_nokey
;может быть, мы в середине esc-кода? тогда надо yieldgetkeyloop
;        ld a,(term_prfsm_curstate)
;        dec a
;        jr nz,yieldgetkeyloop

;последовательности слать одним куском!

scrolldown
;de=topyx, hl=hgt,wid
;x, wid even
        ld b,h ;hgt
        ld c,l ;wid
        ld hl,stdoutbuf
       push hl
        ld (hl),0x1b
        inc hl
        ld (hl),'['
        inc hl
        ld a,c ;wid
        call sendchar_num
        ld (hl),';'
        inc hl
        ld a,b ;hgt
        call sendchar_num
        ld (hl),';'
        inc hl
        ld a,e ;topx
        call sendchar_num
        ld (hl),';'
        inc hl
        ld a,d ;topy
        call sendchar_num
        ld (hl),'d' ;NON-STANDARD!!!
        jr setcolorqq
       
scrollup
;de=topyx, hl=hgt,wid
;x, wid even
        ld b,h ;hgt
        ld c,l ;wid
        ld hl,stdoutbuf
       push hl
        ld (hl),0x1b
        inc hl
        ld (hl),'['
        inc hl
        ld a,c ;wid
        call sendchar_num
        ld (hl),';'
        inc hl
        ld a,b ;hgt
        call sendchar_num
        ld (hl),';'
        inc hl
        ld a,e ;topx
        call sendchar_num
        ld (hl),';'
        inc hl
        ld a,d ;topy
        call sendchar_num
        ld (hl),'u' ;NON-STANDARD!!!
        jr setcolorqq

setcolor
;set color attribute (in: d=paper, e=ink)
;CSI Pm m Character Attributes (SGR)
;Ps = 30  Set foreground color to Black.
;Ps = 31  Set foreground color to Red.
;Ps = 32  Set foreground color to Green.
;Ps = 33  Set foreground color to Yellow.
;Ps = 34  Set foreground color to Blue.
;Ps = 35  Set foreground color to Magenta.
;Ps = 36  Set foreground color to Cyan. (Grey?)
;Ps = 37  Set foreground color to White.
;Ps = 39  Set foreground color to default, ECMA-48 3rd.
;Ps = 40  Set background color to Black.
;Ps = 41  Set background color to Red.
;Ps = 42  Set background color to Green.
;Ps = 43  Set background color to Yellow.
;Ps = 44  Set background color to Blue.
;Ps = 45  Set background color to Magenta.
;Ps = 46  Set background color to Cyan.
;Ps = 47  Set background color to White.
;Ps = 49  Set background color to default, ECMA-48 3rd.
;Ps = 8   Invisible, i.e., hidden, ECMA-48 2nd, VT300. (не работает в Putty!!!)
;Ps = 28  Visible, i.e., not hidden, ECMA-48 3rd, VT300. (не работает в Putty!!!)
;Assume that xterm's resources are set so that the ISO color codes are the first 8 of a set of 16. Then the aixterm colors are the bright versions of the ISO colors:
;Ps = 90  Set foreground color to Black.
;Ps = 91  Set foreground color to Red.
;Ps = 92  Set foreground color to Green.
;Ps = 93  Set foreground color to Yellow.
;Ps = 94  Set foreground color to Blue.
;Ps = 95  Set foreground color to Magenta.
;Ps = 96  Set foreground color to Cyan.
;Ps = 97  Set foreground color to White.
;TODO 1  -  BRIGHT ON: Включение яркости INK. (Bold, VT100.)
;TODO 22 - Normal (neither bold nor faint), ECMA-48 3rd. [21  -  BRIGHT OFF: Выключение яркости INK. (Doubly-underlined, ECMA-48 3rd.)]
        ld hl,stdoutbuf
       push hl
        ld (hl),0x1b
        inc hl
        ld (hl),'['
        inc hl
        ld a,e ;a=ink
        cp 8
        jr c,$+4
        add a,90-30-8
        add a,30
        call sendchar_num
        ld (hl),';'
        inc hl
        ld a,d ;a=paper
        and 7
        add a,40
setcolorq
        call sendchar_num
        ld (hl),'m'
setcolorqq
        inc hl
       pop de
       or a
       sbc hl,de ;de=buf, hl=size
        jp sendchars

setcolor_invisible
        ld hl,stdoutbuf
       push hl
        ld (hl),0x1b
        inc hl
        ld (hl),'['
        inc hl
        ld a,8
        jr setcolorq
       
setcolor_visible
        ld hl,stdoutbuf
       push hl
        ld (hl),0x1b
        inc hl
        ld (hl),'['
        inc hl
        ld a,28
        jr setcolorq

clearrestofline
        ld hl,stdoutbuf
       push hl
        ld (hl),0x1b
        inc hl
        ld (hl),'['
        inc hl
        ld (hl),'K'
        jr setcolorqq

clearterm
        ld a,0x0d ;carriage return
        call sendchar
stdiohgt=$+1
        ld b,25
        dec b
clearterm0
        push bc
        ;ld de,clearterm_data
        ;ld hl,80
        ;call sendchars
        call clearrestofline_crlf
        pop bc
        djnz clearterm0
        ;ld de,clearterm_data
        ;ld hl,79
        ;call sendchars
        call clearrestofline
        ld de,0
        jp setxy

clearrestofline_crlf
        ld de,tclearrestofline_crlf
        ld hl,tclearrestofline_crlf_sz
        jp sendchars
tclearrestofline_crlf
        DEFB 0x1b,'[','K',0x0d,0x0a
tclearrestofline_crlf_sz=$-tclearrestofline_crlf

setxy
;set cursor position (in: de=YX, top left is 0;0)
        ld hl,stdoutbuf
       push hl
        ;push de
        ;ld a,0x1b
        ;call sendchar_byte_a
        ld (hl),0x1b
        inc hl
        ;ld a,'['
        ;call sendchar_byte_a
        ld (hl),'['
        inc hl
        ;pop de
        ;push de
        ld a,d ;y
        inc a
        call sendchar_num
        ;ld a,';'
        ;call sendchar_byte_a
         ld (hl),';'
         inc hl
        ;pop de
        ld a,e ;x
        inc a
        call sendchar_num
        ;ld a,'H'
        ld (hl),'H'
        jp setcolorqq

setx
;set cursor X position (in: e=X, left is 0)
        ld hl,stdoutbuf
       push hl
        ld (hl),0x1b
        inc hl
        ld (hl),'['
        inc hl
        ld a,e ;x
        inc a
        call sendchar_num
        ld (hl),'G'
        jp setcolorqq

sendchar_num
;a=num
        push bc
        ld c,'0'-1
        inc c
        sub 10
        jr nc,$-3
        ;push af
        ;ld a,c
        ;call sendchar_byte_a
        ;pop af
         ld (hl),c
         inc hl
        add a,'0'+10
        ;jr sendchar_byte_a
         ld (hl),a
         inc hl
        pop bc
        ret

sendchar
        ;cp 0x80
        ;jr nc,sendchar_rustoutf8
;sendchar_byte_a
        ld (stdoutbuf),a
        ld hl,1
        ld de,stdoutbuf
sendchars
;send chars to stdout (in: de=buf, hl=size, out: A=error)
       ; if 0
        ; xor a
        ; ld (sendchars_yieldkeepcount),a
       ; endif
sendchars0
        push de
        push hl
stdouthandle=$+1
        ld b,0
        ld c,CMD_WRITEHANDLE
        call BDOS;OS_WRITEHANDLE ;1436t ;[2718t (1225 before BDOS_writehandle + 195 before BDOS_writehandle_pipe + 477 ..findpipe_byhandle + 301 pipe + 192 end BDOS_writehandle + 326 end BDOS)]
        ld b,h
        ld c,l ;bytes actually written
        pop hl
        pop de
         or a
          ret nz ;error ;TODO обработать? а так пока просто избегаем зацикливания
         sbc hl,bc ;datasize-byteswritten
         ret z
         ex de,hl
         add hl,bc ;dataaddr+byteswritten
         ex de,hl
;hl=remaining data size
;de=remaining data addr
        push de
        push hl
       ; if 0
; ;чтобы избежать бесконечного YIELDKEEP с постоянным попаданием прерывания в керналь
; ;ограничим число YIELDKEEP, а потом будет YIELD
         ; ld a,b
         ; or c ;bc=bytes actually written
         ; jr z,sendchars_nofail ;NC
; sendchars_yieldkeepcount=$+1
        ; ld a,0
        ; add a,128
        ; ld (sendchars_yieldkeepcount),a
; sendchars_nofail ;NC
        ; ;ld c,CMD_YIELDKEEP
        ; ;jr nc,$+4
        ; ;ld c,CMD_YIELD
        ; ;call BDOS
       ; else
        ; YIELDKEEP ;2158t        
        ld c,CMD_YIELDKEEP
        call BDOS
       ; endif
        pop hl
        pop de
        jr sendchars0

;receivechars - read chars from stdin
receivechars
;de=buf, hl=size
;out: de=end addr in buf (if EOF), CY=error(EOF))
receivechars0
        push de
        push hl
        ld a,(stdinhandle)
        ld b,a
        ld c,CMD_READHANDLE
        call BDOS ;OS_READHANDLE ;hl=size actually received
        ld b,h
        ld c,l
        pop hl
        pop de
        or a
        scf
        ret nz ;error
        ex de,hl
        add hl,bc ;addr+=readed
        ex de,hl
        or a
        sbc hl,bc ;size-=readed
        jr nz,receivechars0
        ret

receivechar
;read char from stdin (out: A=char(maybe 0), CY=error)
stdindatacount=$+1
        ld a,0
        or a
        jr z,receivechar_doreceive
        dec a
        ld (stdindatacount),a
stdindatapointer=$+1
        ld hl,0
        ld a,(hl)
        inc hl
        ld (stdindatapointer),hl
        or a ;NC=no error
        ret
receivechar_doreceive
        ld hl,STDINBUF_SZ
        ld de,stdinbuf
        ld (stdindatapointer),de
stdinhandle=$+1
        ld b,0
        ld c,CMD_READHANDLE
        call BDOS ;OS_READHANDLE ;hl=size actually received
        or a
        scf
        ret nz ;error
        ld a,h
        or l
        ;ld c,a
        ret z ;NC=no error
        ;ld a,l
        ld (stdindatacount),a
        jr receivechar

receivekey
;read key from stdin (out: A=keylang, C=keynolang(???TODO), CY=error)
        call receivechar
        ret c ;error
         or a
         ld c,a
         ret z ;NC=no error
;a=char
TERM_ST_SINGLE=1 ;1: wait for single symbol
TERM_ST_AFTERESC=2 ;2: after 0x1b
TERM_ST_AFTERESCBRACKET=3 ;3: after 0x1b [ [number] (might be more digits)
TERM_ST_AFTERMOUSE=4
TERM_ST_AFTERMOUSEb=5
TERM_ST_AFTERMOUSEbx=6
term_prfsm_curstate=$+1
        ld b,TERM_ST_SINGLE
        djnz term_prfsm_nosingle
         ;cp 0x0a
         ;ld c,0x0d
         ;jp z,term_prfsm_keycok
        cp 0x1b
        ld c,a
        jp nz,term_prfsm_keycok
        ld hl,term_prfsm_curstate
        inc (hl) ;TERM_ST_AFTERESC
        jp term_prfsm_nokey
term_prfsm_nosingle
        djnz term_prfsm_noafteresc
        cp 'O'
        jr z,escO
        ;cp '['
        ld c,0x1b
        cp c
        jp z,term_prfsm_keycok ;esc esc -> esc_key
escO ;костыль! esc O P/Q/R/S = F1..F4
        ld hl,term_prfsm_curstate
        inc (hl) ;TERM_ST_AFTERESCBRACKET
term_prfsm_0curnumber_nokey
        xor a
        ld (term_prfsm_curnumber),a
        ;xor a ;no key, no error
        ld c,a
        ret
term_prfsm_noafteresc
        djnz term_prfsm_noafterescbracket
        sub '0'
        cp 10
        jr nc,term_prfsm_afterescbracket_nonumber
        ld e,a
        ld hl,term_prfsm_curnumber
        ld a,(hl)
        add a,a
        add a,a
        add a,(hl)
        add a,a ;*10
        add a,e
        ld (hl),a
        jr term_prfsm_nokey
term_prfsm_afterescbracket_nonumber
        add a,'0'
        cp ';'
        jr nz,term_prfsm_afterescbracket_nosemicolon
        ld a,(term_prfsm_curnumber)
        ld (term_prfsm_curnumber1),a
        jr term_prfsm_0curnumber_nokey
term_prfsm_afterescbracket_nosemicolon
        ld hl,term_prfsm_curstate
        ld (hl),TERM_ST_SINGLE
        ;cp 'H'
        cp '~'
        jp z,term_prfsm_afterescbracket_tilde
        cp 'A'
        ld c,key_up
        jr z,term_prfsm_keycok
        cp 'B'
        ld c,key_down
        jr z,term_prfsm_keycok
        cp 'C'
        ld c,key_right
        jr z,term_prfsm_keycok
        cp 'D'
        ld c,key_left
        jr z,term_prfsm_keycok
         cp 'P'
         ld c,key_F1
         jr z,term_prfsm_keycok
         cp 'Q'
         ld c,key_F2
         jr z,term_prfsm_keycok
         cp 'R'
         ld c,key_F3
         jr z,term_prfsm_keycok
         cp 'S'
         ld c,key_F4
         jr z,term_prfsm_keycok
        cp 'M'
        jr z,term_prfsm_mouse
term_prfsm_nokey
        xor a ;no key, no error
        ld c,a
        ret
;escO
;        jr $
term_prfsm_noafterescbracket
        djnz term_prfsm_noaftermouse
        ld hl,term_prfsm_curstate
        inc (hl) ;TERM_ST_AFTERMOUSEb
         and 0x1f ;TODO как отличить движение мыши от unclick?
         ld l,0xff
         dec a
         jr nz,$+3
         dec l
         dec a
         jr nz,$+4
         res 1,l
         dec a
         jr nz,$+4
         res 2,l
         ld a,l
         ld (stdio_mousebuttons),a
        xor a ;no key, no error
        ld c,a
        ret
term_prfsm_noaftermouse
        djnz term_prfsm_aftermousebx;term_prfsm_noaftermouseb
        ld hl,term_prfsm_curstate
        inc (hl) ;TERM_ST_AFTERMOUSEbx
         sub 32
         ld (stdio_mousex),a
        xor a ;no key, no error
        ld c,a
        ret
term_prfsm_aftermousebx
        ld hl,term_prfsm_curstate
        ld (hl),TERM_ST_SINGLE
         sub 32
         ld (stdio_mousey),a
        ld a,0xc9
        ld (wasmouseevent),a
        xor a ;no key, no error
        ld c,a
        ret

term_prfsm_keycok
        ld hl,term_prfsm_curstate
        ld (hl),TERM_ST_SINGLE
        xor a
        or c ;NC=no error
        ret
term_prfsm_mouse
        ld hl,term_prfsm_curstate
        ld (hl),TERM_ST_AFTERMOUSE
        xor a ;no key, no error
        ld c,a
        ret

term_prfsm_afterescbracket_tilde
        ld a,(term_prfsm_curnumber)
;        if 1==1
;        display $
        cp tcontrolkeys_sz
        jr nc,term_prfsm_nokey
        ld hl,tcontrolkeys
        add a,l
        ld l,a
        jr nc,$+3
        inc h
        ld c,(hl)
        jr term_prfsm_keycok
;        else
;        cp 3
;        ld c,key_del
;        jr z,term_prfsm_keycok
;        cp 1
;        ld c,key_home
;        jr z,term_prfsm_keycok
;        cp 4
;        ld c,key_end
;        jr z,term_prfsm_keycok
;        cp 2
;        ld c,key_ins
;        jr z,term_prfsm_keycok
;        cp 5
;        ld c,key_pgup
;        jr z,term_prfsm_keycok
;        cp 6
;        ld c,key_pgdown
;        jr z,term_prfsm_keycok
;        endif
        jr term_prfsm_nokey

tcontrolkeys
        DEFB 0
        DEFB key_home ;1
        DEFB key_ins ;2
        DEFB key_del ;3
        DEFB key_end ;4
        DEFB key_pgup ;5
        DEFB key_pgdown ;6
        DEFB 0 ;7
        DEFB 0 ;8
        DEFB 0 ;9
        DEFB 0 ;10
        DEFB key_F1 ;11
        DEFB key_F2 ;12
        DEFB key_F3 ;13
        DEFB key_F4 ;14
        DEFB key_F5 ;15
        DEFB 0 ;16
        DEFB key_F6 ;17
        DEFB key_F7 ;18
        DEFB key_F8 ;19
        DEFB key_F9 ;20
        DEFB key_F10 ;21
        ;DEFB 0 ;22
        ;DEFB key_F11 ;23
        ;DEFB key_F12 ;24
tcontrolkeys_sz=$-tcontrolkeys

term_prfsm_curnumber
         DEFB 0
term_prfsm_curnumber1
         DEFB 0

stdoutbuf
        DEFB "-[00;00;00;00u"

stdinbuf
        DEFS STDINBUF_SZ