mirror of
https://github.com/ksherlock/marlene.git
synced 2025-01-15 03:33:05 +00:00
rewrite vt100 and telnet.
This commit is contained in:
parent
9285503c5f
commit
9cc53483ad
32
GNUmakefile
Normal file
32
GNUmakefile
Normal file
@ -0,0 +1,32 @@
|
||||
PROG = fctelnet
|
||||
OBJS = o/fctelnet.a o/vt100.a o/telnet.a o/ansi.a o/chars.a o/marinetti.a o/display.a
|
||||
|
||||
OPTIMIZE ?= 79
|
||||
|
||||
CFLAGS = -w-1 -O $(OPTIMIZE)
|
||||
CC = occ --gno
|
||||
|
||||
$(PROG): $(OBJS)
|
||||
$(RM) o/ansi.root
|
||||
$(RM) o/chars.root
|
||||
$(CC) $(OBJS) -o $@
|
||||
|
||||
|
||||
fctelnet.o: fctelnet.c marinetti.h
|
||||
vt100.o: vt100.c CLAGS+=-r
|
||||
ansi.o: ansi.asm
|
||||
chars.o: chars.asm
|
||||
marinetti.o: marinetti.c CLAGS+=-r
|
||||
telnet.o: telnet.c CLAGS+=-r
|
||||
|
||||
o/%.a : %.c
|
||||
$(CC) -c $(CFLAGS) -o $@ $^
|
||||
|
||||
o/%.a : %.asm
|
||||
$(CC) -c $(CFLAGS) -o $@ $^
|
||||
|
||||
|
||||
clean:
|
||||
$(RM) -f *.o *.root *.a *.r
|
||||
clobber: clean
|
||||
$(RM) -f $(PROG)
|
661
ansi.asm
661
ansi.asm
@ -3,6 +3,46 @@
|
||||
dummy start
|
||||
end
|
||||
|
||||
tables privdata
|
||||
|
||||
;
|
||||
; each line is 160 pixels.
|
||||
; top/bottom margin is 4 lines (4*160 pixels)
|
||||
|
||||
rows anop
|
||||
dc i2'0*8*160+4*160+$2000'
|
||||
dc i2'1*8*160+4*160+$2000'
|
||||
dc i2'2*8*160+4*160+$2000'
|
||||
dc i2'3*8*160+4*160+$2000'
|
||||
dc i2'4*8*160+4*160+$2000'
|
||||
dc i2'5*8*160+4*160+$2000'
|
||||
dc i2'6*8*160+4*160+$2000'
|
||||
dc i2'7*8*160+4*160+$2000'
|
||||
dc i2'8*8*160+4*160+$2000'
|
||||
dc i2'9*8*160+4*160+$2000'
|
||||
dc i2'10*8*160+4*160+$2000'
|
||||
dc i2'11*8*160+4*160+$2000'
|
||||
dc i2'12*8*160+4*160+$2000'
|
||||
dc i2'13*8*160+4*160+$2000'
|
||||
dc i2'14*8*160+4*160+$2000'
|
||||
dc i2'15*8*160+4*160+$2000'
|
||||
dc i2'16*8*160+4*160+$2000'
|
||||
dc i2'17*8*160+4*160+$2000'
|
||||
dc i2'18*8*160+4*160+$2000'
|
||||
dc i2'19*8*160+4*160+$2000'
|
||||
dc i2'20*8*160+4*160+$2000'
|
||||
dc i2'21*8*160+4*160+$2000'
|
||||
dc i2'22*8*160+4*160+$2000'
|
||||
dc i2'23*8*160+4*160+$2000'
|
||||
dc i2'24*8*160+4*160+$2000'
|
||||
|
||||
;
|
||||
; columns are simply x * 2
|
||||
;
|
||||
|
||||
|
||||
|
||||
end
|
||||
;
|
||||
;ReverseScrollRegion(line1, line2)
|
||||
;
|
||||
@ -12,6 +52,8 @@ line1 equ 7
|
||||
_rtlb equ 3
|
||||
_d equ 1
|
||||
|
||||
using tables
|
||||
|
||||
; brk $ea
|
||||
|
||||
phb
|
||||
@ -20,36 +62,28 @@ _d equ 1
|
||||
tcd
|
||||
|
||||
lda <line1
|
||||
cmp #0
|
||||
bcc exit
|
||||
bmi exit
|
||||
|
||||
lda <line2
|
||||
cmp #24
|
||||
cmp #25
|
||||
bcs exit
|
||||
|
||||
lda <line1
|
||||
cmp <line2
|
||||
bcs exit
|
||||
|
||||
; a = (line2 - line1) * 8 * 160 - 1
|
||||
asl line1
|
||||
asl line2
|
||||
|
||||
lda <line2
|
||||
sec
|
||||
sbc <line1
|
||||
; a = a * 256 * 5
|
||||
xba ; a = a * 256
|
||||
; 5x = 4x + x
|
||||
; count = (line2 - line1) * 8 * 160 - 1
|
||||
|
||||
pha ; save
|
||||
asl a ; x2
|
||||
asl a ; x4
|
||||
clc
|
||||
adc 1,s
|
||||
sta 1,s
|
||||
pla
|
||||
dec a ; a = a - 1
|
||||
ldx <line2
|
||||
lda >rows,x
|
||||
clc ; dec a
|
||||
ldx <line1
|
||||
sbc >rows,x
|
||||
pha
|
||||
|
||||
pha ; save
|
||||
|
||||
;
|
||||
; mvn:
|
||||
@ -66,21 +100,14 @@ _d equ 1
|
||||
; x = src address = dest - 160*8
|
||||
|
||||
|
||||
lda <line2
|
||||
inc a
|
||||
xba ; x256
|
||||
pha ; save
|
||||
asl a ; x 2
|
||||
asl a ; x 4
|
||||
clc
|
||||
adc #$2000+4*160
|
||||
adc 1,s
|
||||
dec a ; - 1
|
||||
sta 1,s ;store it...
|
||||
ldx <line2
|
||||
lda >rows,x
|
||||
dec a
|
||||
tay
|
||||
sec
|
||||
sbc #1280
|
||||
tax ; src address
|
||||
ply ; dest address
|
||||
sbc #160*8
|
||||
tax
|
||||
|
||||
pla ; length
|
||||
|
||||
mvp $e10000,$e10000
|
||||
@ -88,8 +115,8 @@ _d equ 1
|
||||
;
|
||||
; now empty first line
|
||||
;
|
||||
pei (line1)
|
||||
jsl ClearLine
|
||||
ldx <line1
|
||||
jsr _ClearLine
|
||||
|
||||
exit anop
|
||||
|
||||
@ -113,6 +140,8 @@ exit anop
|
||||
;
|
||||
ScrollRegion START
|
||||
|
||||
using tables
|
||||
|
||||
line2 equ 9
|
||||
line1 equ 7
|
||||
_rtlb equ 3
|
||||
@ -126,36 +155,28 @@ _d equ 1
|
||||
tcd
|
||||
|
||||
lda <line1
|
||||
cmp #0
|
||||
bcc exit
|
||||
bmi exit
|
||||
|
||||
lda <line2
|
||||
cmp #24
|
||||
cmp #25
|
||||
bcs exit
|
||||
|
||||
lda <line1
|
||||
cmp <line2
|
||||
bcs exit
|
||||
|
||||
asl line1
|
||||
asl line2
|
||||
|
||||
; a = (line2 - line1) * 8 * 160 - 1
|
||||
|
||||
lda <line2
|
||||
sec
|
||||
sbc <line1
|
||||
; a = a * 256 * 5
|
||||
xba ; a = a * 256
|
||||
; 5x = 4x + x
|
||||
ldx <line2
|
||||
lda >rows,x
|
||||
clc ; dec a
|
||||
ldx <line1
|
||||
sbc >rows,x
|
||||
pha
|
||||
|
||||
pha ; save
|
||||
asl a ; x2
|
||||
asl a ; x4
|
||||
clc
|
||||
adc 1,s
|
||||
sta 1,s
|
||||
pla
|
||||
dec a ; a = a - 1
|
||||
|
||||
pha ; save
|
||||
|
||||
; src address = $2000 + line1
|
||||
|
||||
@ -166,18 +187,13 @@ _d equ 1
|
||||
; dest = $2000 + 640 + line1 * 8 * 160
|
||||
; src = dest + 1280
|
||||
|
||||
lda <line1
|
||||
xba ; x256
|
||||
pha ; save
|
||||
asl a ; x 2
|
||||
asl a ; x 4
|
||||
ldx <line1
|
||||
lda >rows,x
|
||||
tay
|
||||
clc
|
||||
adc #$2000+4*160
|
||||
adc 1,s
|
||||
sta 1,s ;store it...
|
||||
adc #1280
|
||||
tax ; src address
|
||||
ply ; dest address
|
||||
adc #8*160
|
||||
tax
|
||||
|
||||
pla ; length
|
||||
|
||||
mvn $e10000,$e10000
|
||||
@ -185,8 +201,10 @@ _d equ 1
|
||||
;
|
||||
; now empty last line
|
||||
;
|
||||
pei (line2)
|
||||
jsl ClearLine
|
||||
ldx line2
|
||||
dex
|
||||
dex
|
||||
jsr _ClearLine
|
||||
|
||||
exit anop
|
||||
|
||||
@ -210,6 +228,8 @@ exit anop
|
||||
;
|
||||
ScrollDown START
|
||||
|
||||
using tables
|
||||
|
||||
phb
|
||||
;
|
||||
; mvn:
|
||||
@ -232,8 +252,8 @@ ScrollDown START
|
||||
;
|
||||
; now empty outline #24
|
||||
;
|
||||
pea 23
|
||||
jsl ClearLine
|
||||
ldx #23
|
||||
jsr _ClearLine
|
||||
|
||||
|
||||
plb
|
||||
@ -241,54 +261,50 @@ ScrollDown START
|
||||
|
||||
END
|
||||
|
||||
|
||||
; clear line in X (which has been pre-multiplied)
|
||||
_ClearLine PRIVATE
|
||||
|
||||
using tables
|
||||
|
||||
lda >rows,x
|
||||
tax
|
||||
lda #0
|
||||
sta >$e10000,x ; stick a 0 in there
|
||||
txy ; destination address (src + 2)
|
||||
iny
|
||||
iny
|
||||
|
||||
lda #8*160-3 ; length -1
|
||||
mvn $e10000,$e10000
|
||||
rts
|
||||
END
|
||||
;
|
||||
; ClearLine(int line_no); clears the line
|
||||
;
|
||||
ClearLine START
|
||||
|
||||
line equ 9
|
||||
_rtlb equ 5
|
||||
tmp equ 3
|
||||
line equ 7
|
||||
_rtlb equ 3
|
||||
_d equ 1
|
||||
|
||||
|
||||
; brk $ea
|
||||
phb
|
||||
pha
|
||||
|
||||
phd
|
||||
tsc
|
||||
tcd
|
||||
|
||||
; line * 8 * 160 + 4*160
|
||||
; = line * 1024 + line * 256 + 4*160
|
||||
lda <line
|
||||
cmp #24
|
||||
bcs exit
|
||||
|
||||
and #$00ff
|
||||
xba ; x256
|
||||
sta <tmp
|
||||
asl a ; x 512
|
||||
asl a ; x 1024
|
||||
clc
|
||||
adc <tmp
|
||||
sta <tmp
|
||||
|
||||
clc
|
||||
adc #4*160
|
||||
sta <tmp
|
||||
clc
|
||||
adc #$2000 ; graphics begin @ $e12000
|
||||
|
||||
asl a
|
||||
tax
|
||||
lda #0
|
||||
sta >$e10000,x ; stick a 0 in there
|
||||
txy ; destination address (src + 2)
|
||||
iny
|
||||
iny
|
||||
jsr _ClearLine
|
||||
|
||||
|
||||
lda #8*160-3 ; length -1
|
||||
mvn $e10000,$e10000
|
||||
exit anop
|
||||
|
||||
lda <_rtlb+2
|
||||
sta <_rtlb+4
|
||||
@ -297,74 +313,76 @@ _d equ 1
|
||||
|
||||
pld
|
||||
pla
|
||||
pla
|
||||
plb
|
||||
rtl
|
||||
|
||||
END
|
||||
|
||||
|
||||
;extern void ClearScreenFrom(int Y);
|
||||
;
|
||||
; ClearScreen2(int start, int end);
|
||||
;
|
||||
;
|
||||
ClearScreenFrom START
|
||||
ClearScreen2 START
|
||||
|
||||
Y equ 9
|
||||
_rtlb equ 5
|
||||
tmp equ 3
|
||||
using tables
|
||||
|
||||
line2 equ 9
|
||||
line1 equ 7
|
||||
_rtlb equ 3
|
||||
_d equ 1
|
||||
|
||||
|
||||
|
||||
; brk $ea
|
||||
phb
|
||||
pha
|
||||
|
||||
phd
|
||||
tsc
|
||||
tcd
|
||||
|
||||
; line * 8 * 160 + 4*160
|
||||
; = line * 1024 + line * 256 + 4*160
|
||||
lda <Y
|
||||
lda <line1
|
||||
bmi exit
|
||||
|
||||
and #$00ff
|
||||
xba ; x256
|
||||
sta <tmp
|
||||
asl a ; x 512
|
||||
asl a ; x 1024
|
||||
clc
|
||||
adc <tmp
|
||||
sta <tmp
|
||||
lda line2
|
||||
cmp #25
|
||||
bcs exit
|
||||
|
||||
clc
|
||||
adc #4*160
|
||||
sta <tmp
|
||||
clc
|
||||
adc #$2000 ; graphics begin @ $e12000
|
||||
lda <line1
|
||||
cmp <line2
|
||||
bcs exit
|
||||
|
||||
asl line1
|
||||
asl line2
|
||||
|
||||
ldx <line2
|
||||
lda >rows,x
|
||||
clc
|
||||
ldx <line1
|
||||
sbc >rows,x
|
||||
dec a
|
||||
dec a
|
||||
pha ; save length
|
||||
|
||||
|
||||
ldx <line2
|
||||
lda >rows,x
|
||||
tax
|
||||
tay
|
||||
iny
|
||||
iny
|
||||
|
||||
lda #0
|
||||
sta >$e10000,x ; stick a 0 in there
|
||||
txy ; destination address (src + 2)
|
||||
iny
|
||||
iny
|
||||
|
||||
|
||||
phy
|
||||
lda #$9d00-2 ; end of graphics + $2000
|
||||
sec
|
||||
sbc 1,s
|
||||
ply
|
||||
|
||||
; a now equals length to clear
|
||||
sta >$e1000,x
|
||||
pla ; restore length
|
||||
|
||||
mvn $e10000,$e10000
|
||||
|
||||
|
||||
exit anop
|
||||
lda <_rtlb+2
|
||||
sta <_rtlb+4
|
||||
sta <line2
|
||||
lda <_rtlb
|
||||
sta <_rtlb+2
|
||||
sta <line1
|
||||
|
||||
pld
|
||||
pla
|
||||
@ -375,22 +393,23 @@ _d equ 1
|
||||
END
|
||||
|
||||
;
|
||||
;extern void ClearLineFrom(int Y, int X);
|
||||
; ClearLine2(int line, int start, int end);
|
||||
;
|
||||
|
||||
;
|
||||
; clear the end of the line from a given x & y
|
||||
; clear a section of a given line.
|
||||
;
|
||||
ClearLineFrom START
|
||||
ClearLine2 START
|
||||
|
||||
X equ 11
|
||||
Y equ 9
|
||||
_rtlb equ 5
|
||||
tmp equ 3
|
||||
using tables
|
||||
|
||||
end equ 11
|
||||
start equ 9
|
||||
line equ 7
|
||||
_rtlb equ 3
|
||||
_d equ 1
|
||||
|
||||
phb
|
||||
pha
|
||||
phd
|
||||
tsc
|
||||
tcd
|
||||
@ -400,62 +419,62 @@ _d equ 1
|
||||
plb
|
||||
|
||||
|
||||
;
|
||||
; if X is >= 80, skip it...
|
||||
;
|
||||
lda <X
|
||||
cmp #80
|
||||
bcs exit
|
||||
|
||||
lda <Y
|
||||
and #$00ff
|
||||
xba ; x 256
|
||||
sta <tmp
|
||||
asl a ; x 512
|
||||
asl a ; x 1024
|
||||
clc
|
||||
adc <tmp ; Y * 8 * 160
|
||||
clc
|
||||
adc #160*4
|
||||
sta <tmp
|
||||
|
||||
; each char takes up 2 bytes
|
||||
lda <X
|
||||
asl a ; x 2
|
||||
clc
|
||||
adc <tmp
|
||||
sta <tmp
|
||||
|
||||
tax
|
||||
|
||||
lda #80
|
||||
sec
|
||||
sbc <X
|
||||
loop anop
|
||||
|
||||
dec a
|
||||
lda start
|
||||
bmi exit
|
||||
|
||||
stz $2000,x
|
||||
stz $2000+160,x
|
||||
stz $2000+320,x
|
||||
stz $2000+480,x
|
||||
stz $2000+640,x
|
||||
stz $2000+800,x
|
||||
stz $2000+960,x
|
||||
stz $2000+1120,x
|
||||
lda end
|
||||
cmp #81
|
||||
bcs exit
|
||||
|
||||
lda start
|
||||
cmp end
|
||||
bcs exit
|
||||
|
||||
sec
|
||||
lda end
|
||||
sbc start
|
||||
; bmi exit
|
||||
; beq exit
|
||||
tay ; counter
|
||||
|
||||
asl start ; x 2
|
||||
asl line
|
||||
|
||||
ldx <line
|
||||
lda >rows,x
|
||||
|
||||
clc
|
||||
adc start
|
||||
tax
|
||||
|
||||
|
||||
loop anop
|
||||
|
||||
stz |0,x
|
||||
stz |160,x
|
||||
stz |320,x
|
||||
stz |480,x
|
||||
stz |640,x
|
||||
stz |800,x
|
||||
stz |960,x
|
||||
stz |1120,x
|
||||
inx
|
||||
inx
|
||||
bra loop
|
||||
dey
|
||||
bne loop
|
||||
|
||||
exit anop
|
||||
|
||||
lda <_rtlb+2
|
||||
sta <end
|
||||
lda <_rtlb
|
||||
sta <start
|
||||
|
||||
pld
|
||||
pla
|
||||
pla
|
||||
sta 3,s
|
||||
pla
|
||||
sta 3,s
|
||||
|
||||
plb
|
||||
rtl
|
||||
END
|
||||
@ -533,242 +552,214 @@ ClearScreen START
|
||||
plb
|
||||
plb
|
||||
lda #0
|
||||
ldy #0
|
||||
ldy #32000
|
||||
loop anop
|
||||
sta $2000,y
|
||||
iny
|
||||
iny
|
||||
cpy #32000
|
||||
bcc loop
|
||||
sta |$2000-2,y
|
||||
dey
|
||||
dey
|
||||
bne loop
|
||||
plb
|
||||
rtl
|
||||
|
||||
;
|
||||
; this will, in 1 atomic action, blast the screen with 0
|
||||
;
|
||||
|
||||
phb
|
||||
lda #0
|
||||
sta >$e12000
|
||||
lda #32000-3 ;length
|
||||
ldx #$2000
|
||||
ldy #$2002
|
||||
mvn $e10000,$e10000
|
||||
|
||||
plb
|
||||
rtl
|
||||
END
|
||||
;
|
||||
; draw a character at the current Xpos & Ypos
|
||||
;
|
||||
;
|
||||
|
||||
; PrintChar(x, y, char, andMask, xorMask)
|
||||
PrintChar START
|
||||
|
||||
andMask equ 11
|
||||
char equ 9
|
||||
_rtlb equ 5
|
||||
pos equ 3
|
||||
using tables
|
||||
|
||||
xorMask equ 15
|
||||
andMask equ 13
|
||||
char equ 11
|
||||
yy equ 9
|
||||
xx equ 7
|
||||
_rtlb equ 3
|
||||
_d equ 1
|
||||
|
||||
; brk $ea
|
||||
phb
|
||||
pha
|
||||
|
||||
phd
|
||||
tsc
|
||||
tcd
|
||||
|
||||
; sanity check on Xpos && Ypos
|
||||
lda Xpos
|
||||
cmp #80
|
||||
bcc _ok
|
||||
lda Ypos
|
||||
cmp #24
|
||||
bcc _ok
|
||||
brl exit
|
||||
_ok anop
|
||||
|
||||
ldx xx
|
||||
cpx #80
|
||||
bcc ok2
|
||||
|
||||
exit2 anop
|
||||
brl exit
|
||||
|
||||
ok2 anop
|
||||
ldy yy
|
||||
cpy #24
|
||||
bcs exit2
|
||||
|
||||
lda <char
|
||||
cmp #$7f
|
||||
bcs space
|
||||
sec
|
||||
sbc #$20
|
||||
bmi space
|
||||
asl a ; x2
|
||||
asl a ; x4
|
||||
asl a ; x8
|
||||
asl a ; x16
|
||||
sta char
|
||||
bra ok
|
||||
|
||||
|
||||
space anop
|
||||
stz <char
|
||||
|
||||
ok anop
|
||||
|
||||
pea $e1e1
|
||||
plb
|
||||
plb
|
||||
|
||||
;
|
||||
; each line has a width of 160 pixels
|
||||
;
|
||||
; start drawing the letter at $e12000 + (Ypos x 160 x 8) + Xpos
|
||||
asl xx
|
||||
asl yy
|
||||
|
||||
|
||||
; 160 * 8 = 1240 = 1024 + 256
|
||||
lda >Ypos
|
||||
and #$00ff
|
||||
xba ; x 256
|
||||
sta <pos ; store temporarily
|
||||
|
||||
asl a ; x 512
|
||||
asl a ; x 1024
|
||||
ldx yy
|
||||
lda >rows,x
|
||||
clc
|
||||
adc <pos
|
||||
sta <pos
|
||||
|
||||
;
|
||||
; lower 1/2 row additional
|
||||
;
|
||||
clc
|
||||
adc #160*4
|
||||
sta <pos
|
||||
|
||||
;
|
||||
; for x offset, 160 bytes per row / 80 chars = 2 bytes/letter
|
||||
;
|
||||
lda >Xpos
|
||||
asl a ; x 2
|
||||
clc
|
||||
adc <pos
|
||||
sta <pos
|
||||
adc xx
|
||||
tay
|
||||
|
||||
|
||||
;
|
||||
; $e12000 + pos = location to start drawing the character
|
||||
;
|
||||
|
||||
|
||||
lda <char
|
||||
|
||||
cmp #$20 ; smallest printing char
|
||||
bcc exit ; not printable....
|
||||
cmp #127 ; 126 is biggest
|
||||
bcs exit ; not printable
|
||||
|
||||
;
|
||||
; each char takes up 16 bytes :. the offset is (char - $20) * 16
|
||||
;
|
||||
|
||||
sec
|
||||
sbc #$20
|
||||
asl a ; x2
|
||||
asl a ; x4
|
||||
asl a ; x8
|
||||
asl a ; x16
|
||||
|
||||
tax
|
||||
ldx char
|
||||
lda >CHAR_SPACE,x
|
||||
eor >xor_mask
|
||||
eor <xorMask
|
||||
and <andMask
|
||||
sta |$2000,y ; blast it to the screen
|
||||
sta |0,y ; blast it to the screen
|
||||
|
||||
lda >CHAR_SPACE+2,x
|
||||
eor >xor_mask
|
||||
eor <xorMask
|
||||
and <andMask
|
||||
sta |$2000+160,y
|
||||
sta |160,y
|
||||
|
||||
lda >CHAR_SPACE+4,x
|
||||
eor >xor_mask
|
||||
eor <xorMask
|
||||
and <andMask
|
||||
sta |$2000+320,y
|
||||
sta |320,y
|
||||
|
||||
lda >CHAR_SPACE+6,x
|
||||
eor >xor_mask
|
||||
eor <xorMask
|
||||
and <andMask
|
||||
sta |$2000+480,y
|
||||
sta |480,y
|
||||
|
||||
lda >CHAR_SPACE+8,x
|
||||
eor >xor_mask
|
||||
eor <xorMask
|
||||
and <andMask
|
||||
sta |$2000+640,y
|
||||
sta |640,y
|
||||
|
||||
lda >CHAR_SPACE+10,x
|
||||
eor >xor_mask
|
||||
eor <xorMask
|
||||
and <andMask
|
||||
sta |$2000+800,y
|
||||
sta |800,y
|
||||
|
||||
lda >CHAR_SPACE+12,x
|
||||
eor >xor_mask
|
||||
eor <xorMask
|
||||
and <andMask
|
||||
sta |$2000+960,y
|
||||
sta |960,y
|
||||
|
||||
lda >CHAR_SPACE+14,x
|
||||
eor >xor_mask
|
||||
eor <xorMask
|
||||
and <andMask
|
||||
sta |$2000+1120,y
|
||||
sta |1120,y
|
||||
|
||||
exit anop
|
||||
|
||||
lda <_rtlb+2
|
||||
sta <andMask
|
||||
sta <xorMask
|
||||
lda <_rtlb
|
||||
sta <char
|
||||
sta <andMask
|
||||
pld
|
||||
pla
|
||||
pla
|
||||
pla
|
||||
pla
|
||||
pla
|
||||
plb
|
||||
rtl
|
||||
end
|
||||
|
||||
Cursor START
|
||||
;Cursor START
|
||||
|
||||
StartCursor ENTRY
|
||||
;StartCursor ENTRY
|
||||
|
||||
pha
|
||||
; ~ReadBParam #$2f
|
||||
pla
|
||||
sta blinkRate
|
||||
; pha
|
||||
;; ~ReadBParam #$2f
|
||||
; pla
|
||||
; sta blinkRate
|
||||
|
||||
stz savedX
|
||||
stz savedY
|
||||
; stz savedX
|
||||
; stz savedY
|
||||
|
||||
; ~SetHeartBeat #CursorHB
|
||||
rtl
|
||||
;; ~SetHeartBeat #CursorHB
|
||||
; rtl
|
||||
|
||||
|
||||
StopCursor ENTRY
|
||||
; ~DelHeartBeat #CursorHB
|
||||
rtl
|
||||
;StopCursor ENTRY
|
||||
;; ~DelHeartBeat #CursorHB
|
||||
; rtl
|
||||
|
||||
notSafe ENTRY
|
||||
ds 2
|
||||
blinkRate ds 2
|
||||
savedX ds 2
|
||||
savedY ds 2
|
||||
;notSafe ENTRY
|
||||
; ds 2
|
||||
;blinkRate ds 2
|
||||
;savedX ds 2
|
||||
;savedY ds 2
|
||||
|
||||
CursorHB anop
|
||||
dc i4'0'
|
||||
count dc i2'30'
|
||||
dc h'5AA5'
|
||||
;CursorHB anop
|
||||
; dc i4'0'
|
||||
;count dc i2'30'
|
||||
; dc h'5AA5'
|
||||
|
||||
longa off
|
||||
; longa off
|
||||
|
||||
phb
|
||||
phk
|
||||
plb
|
||||
php
|
||||
; phb
|
||||
; phk
|
||||
; plb
|
||||
; php
|
||||
|
||||
; long ai
|
||||
lda notSafe
|
||||
bne exit
|
||||
;; long ai
|
||||
; lda notSafe
|
||||
; bne exit
|
||||
|
||||
lda Xpos
|
||||
cmp savedX
|
||||
bne moved
|
||||
lda Ypos
|
||||
cmp savedY
|
||||
bne moved
|
||||
bra exit
|
||||
; lda Xpos
|
||||
; cmp savedX
|
||||
; bne moved
|
||||
; lda Ypos
|
||||
; cmp savedY
|
||||
; bne moved
|
||||
; bra exit
|
||||
|
||||
moved jsr drawCursor
|
||||
;moved jsr drawCursor
|
||||
|
||||
|
||||
exit anop
|
||||
;exit anop
|
||||
|
||||
plp
|
||||
plb
|
||||
clc
|
||||
rtl
|
||||
; plp
|
||||
; plb
|
||||
; clc
|
||||
; rtl
|
||||
|
||||
drawCursor anop
|
||||
;drawCursor anop
|
||||
|
||||
rts
|
||||
; rts
|
||||
|
||||
END
|
||||
; END
|
||||
|
384
display.c
384
display.c
@ -1,54 +1,21 @@
|
||||
#pragma noroot
|
||||
#pragma lint -1
|
||||
|
||||
#include <types.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <Event.h>
|
||||
#include "Marinetti.h"
|
||||
|
||||
#define ESC "\x1b"
|
||||
|
||||
extern void ScrollRegion(word,word);
|
||||
extern void ScrollDown(void);
|
||||
extern void PrintChar(int the_char, unsigned int andMask);
|
||||
extern void ClearScreen(void);
|
||||
extern void ClearScreenFrom(int Y);
|
||||
extern void ClearLine(int Y);
|
||||
extern void ClearLineFrom(int Y, int X);
|
||||
|
||||
void handle_ansi(word code, char *buffer, word cnt);
|
||||
|
||||
extern void GrafOn(void) inline(0x0a04, 0xe10000);
|
||||
extern void GrafOff(void) inline(0x0b04, 0xe10000);
|
||||
extern pascal void SetColorTable(Word, ColorTable) inline(0x0E04,dispatcher);
|
||||
extern pascal void SysBeep2(Word) inline(0x3803,dispatcher);
|
||||
extern pascal void SetAllSCBs(Word) inline(0x1404,dispatcher);
|
||||
extern pascal void SetMasterSCB(Word) inline(0x1604,dispatcher);
|
||||
extern pascal void InitColorTable(ColorTable) inline(0x0D04,dispatcher);
|
||||
|
||||
|
||||
|
||||
extern word Xpos;
|
||||
extern word Ypos;
|
||||
extern word __scroll[2];
|
||||
extern word and_mask;
|
||||
extern word xor_mask;
|
||||
|
||||
word esc;
|
||||
char esc_buffer[256];
|
||||
|
||||
struct errlist
|
||||
{
|
||||
struct errlist {
|
||||
Word Error;
|
||||
Word MsgLen;
|
||||
const char *Msg;
|
||||
};
|
||||
|
||||
#define _ERR(n,msg) { n, sizeof(msg), msg }
|
||||
#define ESC "\x1b"
|
||||
#define _ERR(n,msg) { n, sizeof(msg) - 1, msg }
|
||||
|
||||
struct errlist errors[] =
|
||||
{
|
||||
extern void vt100_process(const unsigned char *buffer, unsigned buffer_size);
|
||||
|
||||
static struct errlist errors[] = {
|
||||
_ERR(1,"tcperrDeafDestPort"),
|
||||
_ERR(2,"tcperrHostReset"),
|
||||
_ERR(3,"tcperrConExists"),
|
||||
@ -63,346 +30,27 @@ struct errlist errors[] =
|
||||
_ERR(0x0c,"tcperrConReset"),
|
||||
_ERR(0x0d,"tcperrUserTimeout"),
|
||||
_ERR(0x0e,"tcperrConRefused"),
|
||||
|
||||
{0,0,NULL}
|
||||
};
|
||||
void display_str(const char *buffer, word cnt);
|
||||
|
||||
void display_err(Word err)
|
||||
{
|
||||
struct errlist *l;
|
||||
void display_err(Word err) {
|
||||
|
||||
for (l = &errors[0]; l->Error; l++)
|
||||
if (l->Error == err) break;
|
||||
if (l->Error != err) return;
|
||||
|
||||
display_str("\r\n" "\x1b" "[1m", 6); // bold on
|
||||
display_str(l->Msg, l->MsgLen); // show the string
|
||||
display_str("\x1b" "[0m", 4); // bold off
|
||||
if (err == 0 || err >= 0x0f) return;
|
||||
--err;
|
||||
vt100_process("\r\n" ESC "[1m", 6); // bold on
|
||||
vt100_process(errors[err].Msg, errors[err].MsgLen);
|
||||
vt100_process(ESC "[0m", 4); // bold off
|
||||
}
|
||||
|
||||
void display_cstr(const char *cstr)
|
||||
{
|
||||
void display_cstr(const char *cstr) {
|
||||
if (cstr && *cstr)
|
||||
display_str(cstr, strlen(cstr));
|
||||
vt100_process(cstr, strlen(cstr));
|
||||
}
|
||||
|
||||
void display_pstr(const char *pstr)
|
||||
{
|
||||
void display_pstr(const char *pstr) {
|
||||
if (pstr && *pstr)
|
||||
display_str(pstr + 1, *pstr);
|
||||
vt100_process(pstr + 1, *pstr);
|
||||
}
|
||||
|
||||
|
||||
void display_char(char c)
|
||||
{
|
||||
switch(c)
|
||||
{
|
||||
case 0x07:
|
||||
SysBeep2(0);
|
||||
break;
|
||||
|
||||
//backspace
|
||||
case 0x08:
|
||||
if (Xpos) Xpos--;
|
||||
break;
|
||||
|
||||
//tab
|
||||
case 0x09:
|
||||
// 1, 9, 17, 25, ...
|
||||
// not sure this is right
|
||||
Xpos = Xpos & 0xf8;
|
||||
Xpos += 8;
|
||||
//TODO - wrapping
|
||||
break;
|
||||
|
||||
// line feed
|
||||
case 0x0A:
|
||||
if (++Ypos > 23)
|
||||
{
|
||||
ScrollRegion(__scroll[0], __scroll[1]);
|
||||
Ypos = 23;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case 0x0D: //carriage return
|
||||
Xpos = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (isprint(c));
|
||||
{
|
||||
// check the wrapping flag ...
|
||||
if (Xpos > 80)
|
||||
{
|
||||
Xpos = 0;
|
||||
if (++Ypos > 23)
|
||||
{
|
||||
ScrollRegion(__scroll[0],
|
||||
__scroll[1]);
|
||||
|
||||
Ypos = 23;
|
||||
}
|
||||
}
|
||||
PrintChar(c, and_mask);
|
||||
Xpos++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* this reads text & has it drawn on the shr screen
|
||||
*
|
||||
*/
|
||||
// todo - and_mask + xor_mask
|
||||
void display_str(const char *buffer, word cnt)
|
||||
{
|
||||
word i;
|
||||
|
||||
|
||||
asm
|
||||
{
|
||||
phk
|
||||
plb
|
||||
}
|
||||
|
||||
for ( i = 0; i < cnt; i++)
|
||||
{
|
||||
if (esc)
|
||||
{
|
||||
esc_buffer[esc++] = buffer[i];
|
||||
if (isalpha(buffer[i])
|
||||
|| buffer[i] == '~'
|
||||
|| buffer[i] == '='
|
||||
|| buffer[i] == '>'
|
||||
)
|
||||
{
|
||||
handle_ansi(buffer[i],
|
||||
esc_buffer, esc);
|
||||
esc = 0;
|
||||
}
|
||||
}
|
||||
else switch (buffer[i])
|
||||
{
|
||||
// bell
|
||||
case 0x07:
|
||||
SysBeep2(0);
|
||||
break;
|
||||
|
||||
//backspace
|
||||
case 0x08:
|
||||
if (Xpos) Xpos--;
|
||||
break;
|
||||
|
||||
//tab
|
||||
case 0x09:
|
||||
// 1, 9, 17, 25, ...
|
||||
// not sure this is right
|
||||
Xpos = Xpos & 0xf8;
|
||||
Xpos += 8;
|
||||
//TODO - wrapping
|
||||
break;
|
||||
|
||||
// line feed
|
||||
case 0x0A:
|
||||
if (++Ypos > 23)
|
||||
{
|
||||
ScrollRegion(__scroll[0],
|
||||
__scroll[1]);
|
||||
|
||||
Ypos = 23;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case 0x0D: //carriage return
|
||||
Xpos = 0;
|
||||
break;
|
||||
|
||||
case 0x1b: //start of escape sequence
|
||||
|
||||
esc = 1;
|
||||
esc_buffer[0] = 0x1b;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (isprint(buffer[i]))
|
||||
{
|
||||
// check the wrapping flag ...
|
||||
if (Xpos > 80)
|
||||
{
|
||||
Xpos = 0;
|
||||
if (++Ypos > 23)
|
||||
{
|
||||
ScrollRegion(__scroll[0],
|
||||
__scroll[1]);
|
||||
|
||||
Ypos = 23;
|
||||
}
|
||||
}
|
||||
PrintChar(buffer[i], and_mask);
|
||||
Xpos++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// remap the iigs key to a vt100 code (if necessary) and send it out.
|
||||
|
||||
void send_event(EventRecord *event, Word ipid)
|
||||
{
|
||||
char *cp;
|
||||
int len = 0;
|
||||
word key;
|
||||
word mods;
|
||||
|
||||
key = event->message;
|
||||
mods = event->modifiers;
|
||||
|
||||
|
||||
if (mods & keyPad)
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
case 0x72: // insert
|
||||
cp = ESC "[2~";
|
||||
len = 4;
|
||||
break;
|
||||
|
||||
case 0x75: // delete
|
||||
cp = ESC "[3~";
|
||||
len = 4;
|
||||
break;
|
||||
|
||||
case 0x73: // home
|
||||
cp = ESC "[1~";
|
||||
len = 4;
|
||||
break;
|
||||
|
||||
case 0x77: // end
|
||||
cp = ESC "[4~";
|
||||
len = 4;
|
||||
break;
|
||||
|
||||
case 0x74: // page up
|
||||
cp = ESC "[5~";
|
||||
len = 4;
|
||||
break;
|
||||
|
||||
case 0x79: // page down
|
||||
cp = ESC "[6~";
|
||||
len = 4;
|
||||
break;
|
||||
|
||||
case 0x7a: // f1
|
||||
cp = mods & shiftKey ? ESC "[23~" : ESC "[11~";
|
||||
len = 5;
|
||||
break;
|
||||
|
||||
case 0x78: // f2
|
||||
cp = mods & shiftKey ? ESC "[24~" : ESC "[12~";
|
||||
len = 5;
|
||||
break;
|
||||
|
||||
case 0x63: // f3
|
||||
cp = mods & shiftKey ? ESC "[25~" : ESC "[13~";
|
||||
len = 5;
|
||||
break;
|
||||
|
||||
case 0x76: // f4
|
||||
cp = mods & shiftKey ? ESC "[26~" : ESC "[14~";
|
||||
len = 5;
|
||||
break;
|
||||
|
||||
|
||||
case 0x60: // f5
|
||||
cp = mods & shiftKey ? ESC "[28~" : ESC "[15~";
|
||||
len = 5;
|
||||
break;
|
||||
|
||||
case 0x61: // f6
|
||||
cp = mods & shiftKey ? ESC "[29~" : ESC "[17~";
|
||||
len = 5;
|
||||
break;
|
||||
|
||||
|
||||
case 0x62: // f7
|
||||
cp = mods & shiftKey ? ESC "[31~" : ESC "[18~";
|
||||
len = 5;
|
||||
break;
|
||||
|
||||
case 0x64: // f8
|
||||
cp = mods & shiftKey ? ESC "[32~" : ESC "[19~";
|
||||
len = 5;
|
||||
break;
|
||||
|
||||
case 0x65: // f9
|
||||
cp = mods & shiftKey ? ESC "[33~" : ESC "[20~";
|
||||
len = 5;
|
||||
break;
|
||||
|
||||
case 0x6d: // f10
|
||||
cp = mods & shiftKey ? ESC "[34~" : ESC "[21~";
|
||||
len = 5;
|
||||
break;
|
||||
|
||||
case 0x67: // f11
|
||||
cp = ESC "[23~";
|
||||
len = 5;
|
||||
break;
|
||||
|
||||
case 0x6f: // f12
|
||||
cp = ESC "[24~";
|
||||
len = 5;
|
||||
break;
|
||||
|
||||
default: len = 0; cp = NULL;
|
||||
}
|
||||
}
|
||||
else if (mods & controlKey)
|
||||
{
|
||||
cp = (char *)&event->message;
|
||||
len = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(key)
|
||||
{
|
||||
case 0x0d:
|
||||
cp = "\r\n";
|
||||
len = 2;
|
||||
break;
|
||||
case 0x08: // <--- arrow
|
||||
cp = ESC "[D";
|
||||
len = 3;
|
||||
break;
|
||||
case 0x0A: // down arrow
|
||||
cp = ESC "[B";
|
||||
len = 3;
|
||||
break;
|
||||
case 0x0B: // up arrow
|
||||
cp = ESC "[A";
|
||||
len = 3;
|
||||
break;
|
||||
case 0x15: // ---> arrow
|
||||
cp = ESC "[C";
|
||||
len = 3;
|
||||
break;
|
||||
|
||||
// backspace to delete char
|
||||
case 0x7f:
|
||||
cp = "\x08";
|
||||
len = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
cp = (char *)&event->message;
|
||||
len = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (len) TCPIPWriteTCP(ipid, cp, len, false, false);
|
||||
|
||||
}
|
||||
|
413
fctelnet.c
413
fctelnet.c
@ -1,4 +1,4 @@
|
||||
#include "Marinetti.h"
|
||||
#include <tcpip.h>
|
||||
#include <Locator.h>
|
||||
#include <Memory.h>
|
||||
#include <texttool.h>
|
||||
@ -22,16 +22,11 @@
|
||||
|
||||
#include "telnet.h"
|
||||
|
||||
extern void ScrollRegion(word,word);
|
||||
extern void ScrollDown(void);
|
||||
extern void PrintChar(int the_char, unsigned int andMask);
|
||||
extern void ClearScreen(void);
|
||||
extern void ClearScreenFrom(int Y);
|
||||
extern void ClearLine(int Y);
|
||||
extern void ClearLineFrom(int Y, int X);
|
||||
|
||||
extern void GrafOn(void) inline(0x0a04, 0xe10000);
|
||||
extern void GrafOff(void) inline(0x0b04, 0xe10000);
|
||||
extern pascal void GrafOn(void) inline(0x0a04, dispatcher);
|
||||
extern pascal void GrafOff(void) inline(0x0b04, dispatcher);
|
||||
|
||||
extern pascal void SetColorTable(Word, ColorTable) inline(0x0E04,dispatcher);
|
||||
extern pascal void SysBeep2(Word) inline(0x3803,dispatcher);
|
||||
extern pascal void SetAllSCBs(Word) inline(0x1404,dispatcher);
|
||||
@ -39,26 +34,30 @@ extern pascal void SetMasterSCB(Word) inline(0x1604,dispatcher);
|
||||
extern pascal void InitColorTable(ColorTable) inline(0x0D04,dispatcher);
|
||||
|
||||
|
||||
Word MyID;
|
||||
Word __gno;
|
||||
|
||||
Word modeTelnet = 1;
|
||||
Word flagEcho = 1; // if *I* echo
|
||||
|
||||
|
||||
void init_ansi(void);
|
||||
|
||||
Word ResolveHost(const char *name, cvtRecPtr cvt);
|
||||
Word GetChar(word ipid, unsigned char *c);
|
||||
Word UngetChar(char c);
|
||||
int WaitForStatus(word ipid, word status);
|
||||
|
||||
|
||||
void display_str(const char *txt, word cnt);
|
||||
void display_pstr(const char *);
|
||||
void display_cstr(const char *);
|
||||
void display_err(Word);
|
||||
|
||||
void send_event(EventRecord *, Word);
|
||||
extern void telnet_init(void);
|
||||
extern void telnet_process(void);
|
||||
|
||||
extern void vt100_init(void);
|
||||
extern void vt100_process(const unsigned char *buffer, unsigned buffer_size);
|
||||
extern void vt100_event(EventRecord *event);
|
||||
|
||||
|
||||
|
||||
|
||||
Word MyID;
|
||||
Word __gno;
|
||||
|
||||
|
||||
#define ESC "\x1b"
|
||||
|
||||
|
||||
|
||||
#pragma databank 1
|
||||
@ -67,25 +66,17 @@ void send_event(EventRecord *, Word);
|
||||
* called to print connect/disconnect messages from
|
||||
* Marinetti. msg is a pstring.
|
||||
*/
|
||||
void printCallBack(const char *msg)
|
||||
{
|
||||
word i;
|
||||
i = *msg;
|
||||
if (i)
|
||||
{
|
||||
display_str("\x1b" "[1m", 4); // bold on
|
||||
display_str(msg + 1, i); // show the string
|
||||
display_str("\x1b" "[0m\n\r", 6); // bold off
|
||||
void printCallBack(const char *msg) {
|
||||
if (msg && *msg) {
|
||||
display_cstr(ESC "\n\r[1m"); // bold on
|
||||
display_pstr(msg); // show the string
|
||||
display_cstr(ESC "[0m\n\r"); // bold off
|
||||
}
|
||||
}
|
||||
#pragma databank 0
|
||||
|
||||
extern word esc;
|
||||
extern word Xpos;
|
||||
extern word Ypos;
|
||||
|
||||
void init_screen(void)
|
||||
{
|
||||
static void screen_init(void) {
|
||||
#define WHITE 0x0fff
|
||||
#define YELLOW 0x0ff0
|
||||
#define BLACK 0x0000
|
||||
@ -115,8 +106,8 @@ static ColorTable ct =
|
||||
BLUE,
|
||||
GREEN,
|
||||
};
|
||||
int i;
|
||||
|
||||
unsigned i;
|
||||
|
||||
// linearize memory, disable shadowing.
|
||||
asm
|
||||
@ -138,147 +129,48 @@ int i;
|
||||
SetMasterSCB(0xc080);
|
||||
SetAllSCBs(0xc080);
|
||||
//InitColorTable(ct);
|
||||
for (i = 0; i < 15; i++)
|
||||
for (i = 0; i < 16; i++)
|
||||
SetColorTable(i, ct);
|
||||
|
||||
ClearScreen();
|
||||
GrafOn();
|
||||
}
|
||||
|
||||
static char out_buffer[1024];
|
||||
static char out_buffer_size = 0;
|
||||
|
||||
/*
|
||||
* this is (more or less) a state machine.
|
||||
* old state (and character) are passed in
|
||||
* new state is returned.
|
||||
*
|
||||
* 0 = starting state.
|
||||
*/
|
||||
#define SB_IAC 0xfaff
|
||||
Word do_iac(Word state, char c, Word ipid)
|
||||
{
|
||||
static char buffer[64];
|
||||
static int cnt;
|
||||
static word ipid = -1;
|
||||
|
||||
if (state == 0) return c == IAC ? IAC : 0;
|
||||
// FF must be escaped as FF FF within SB.
|
||||
// SB_IAC means the first FF has been processed.
|
||||
if (state == SB)
|
||||
{
|
||||
if (c == IAC) return SB_IAC;
|
||||
buffer[cnt++] = c;
|
||||
return SB;
|
||||
static void flush(void) {
|
||||
if (out_buffer_size) {
|
||||
TCPIPWriteTCP(ipid, out_buffer, out_buffer_size, true, false);
|
||||
out_buffer_size = 0;
|
||||
}
|
||||
|
||||
if (state == SB_IAC)
|
||||
{
|
||||
// it was an escaped FF
|
||||
if (c == IAC)
|
||||
{
|
||||
buffer[cnt++] = IAC;
|
||||
return SB;
|
||||
}
|
||||
else state = IAC; // process below...
|
||||
}
|
||||
if (state == IAC)
|
||||
switch (c)
|
||||
{
|
||||
case DONT:
|
||||
case DO:
|
||||
case WONT:
|
||||
case WILL:
|
||||
return c;
|
||||
case SB:
|
||||
cnt = 0;
|
||||
return c;
|
||||
case SE:
|
||||
// buffer is the data between
|
||||
// IAC SB <...> IAC SE
|
||||
if (buffer[0] == TELOPT_TTYPE
|
||||
&& buffer[1] == TELQUAL_SEND)
|
||||
{
|
||||
static char msg[] =
|
||||
{
|
||||
IAC, SB, TELOPT_TTYPE, TELQUAL_IS,
|
||||
'V', 'T', '1', '0', '0',
|
||||
IAC, SE
|
||||
};
|
||||
TCPIPWriteTCP(ipid, msg,
|
||||
sizeof(msg), true, false);
|
||||
}
|
||||
else if (buffer[0] == TELOPT_NAWS
|
||||
&& buffer[1] == TELQUAL_SEND)
|
||||
{
|
||||
static char msg[] =
|
||||
{
|
||||
IAC, SB, TELOPT_NAWS,
|
||||
0, 80, 0, 24,
|
||||
IAC, SE
|
||||
};
|
||||
TCPIPWriteTCP(ipid, msg,
|
||||
sizeof(msg), true, false);
|
||||
}
|
||||
else if (buffer[0] == TELOPT_TSPEED
|
||||
&& buffer[1] == TELQUAL_SEND)
|
||||
{
|
||||
static char msg[] =
|
||||
{
|
||||
IAC, SB, TELOPT_TSPEED,
|
||||
'9', '6', '0', '0', ',', '9', '6', '0', '0',
|
||||
IAC, SE
|
||||
};
|
||||
TCPIPWriteTCP(ipid, msg,
|
||||
sizeof(msg), true, false);
|
||||
}
|
||||
cnt = 0;
|
||||
return 0;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
if (state == DO)
|
||||
{
|
||||
buffer[0] = IAC;
|
||||
buffer[1] = WONT;
|
||||
buffer[2] = c;
|
||||
if (c == TELOPT_TTYPE
|
||||
|| c == TELOPT_SGA
|
||||
|| c == TELOPT_NAWS
|
||||
|| c == TELOPT_TSPEED)
|
||||
{
|
||||
buffer[1] = WILL;
|
||||
}
|
||||
TCPIPWriteTCP(ipid, buffer, 3, true, false);
|
||||
|
||||
}
|
||||
if (state == DONT)
|
||||
{
|
||||
buffer[0] = IAC;
|
||||
buffer[1] = WONT;
|
||||
buffer[2] = c;
|
||||
|
||||
TCPIPWriteTCP(ipid, buffer, 3, true, false);
|
||||
}
|
||||
if (state == WILL || state == WONT)
|
||||
{
|
||||
buffer[0] = IAC;
|
||||
buffer[1] = DONT;
|
||||
buffer[2] = c;
|
||||
if (c == TELOPT_ECHO)
|
||||
{
|
||||
buffer[1] = DO;
|
||||
}
|
||||
cnt = 3;
|
||||
|
||||
TCPIPWriteTCP(ipid, buffer, cnt, true, false);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
|
||||
void send(char *data, unsigned size) {
|
||||
|
||||
if (out_buffer_size + size > sizeof(out_buffer)) {
|
||||
flush();
|
||||
}
|
||||
if (size > sizeof(out_buffer) / 2) {
|
||||
TCPIPWriteTCP(ipid, data, size, true, false);
|
||||
return;
|
||||
}
|
||||
memcpy(out_buffer + out_buffer_size, data, size);
|
||||
out_buffer_size += size;
|
||||
}
|
||||
|
||||
|
||||
unsigned buffer_size;
|
||||
unsigned char buffer[2048]; // 1500 is normal MTU size?
|
||||
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
static EventRecord event;
|
||||
static srBuffer sr;
|
||||
static rrBuff rr;
|
||||
static char str[16];
|
||||
static cvtRec cvt;
|
||||
@ -288,25 +180,15 @@ static QuitRecGS qDCB = {2, 0, 0x4000};
|
||||
Word iLoaded;
|
||||
Word iConnected;
|
||||
Word iStarted;
|
||||
Word Quit;
|
||||
Word ipid;
|
||||
Handle dp;
|
||||
|
||||
|
||||
int i;
|
||||
Word key;
|
||||
Word err;
|
||||
unsigned char c;
|
||||
//int fd;
|
||||
int iac_state;
|
||||
int ok;
|
||||
|
||||
|
||||
Xpos = Ypos = 0;
|
||||
esc = 0;
|
||||
//iac = 0;
|
||||
iLoaded = iStarted = iConnected = false;
|
||||
__gno = false;
|
||||
|
||||
ipid = -1;
|
||||
|
||||
MyID = MMStartUp();
|
||||
|
||||
@ -321,58 +203,53 @@ static QuitRecGS qDCB = {2, 0, 0x4000};
|
||||
dp = NewHandle(0x0100, MyID,
|
||||
attrBank | attrPage |attrNoCross | attrFixed | attrLocked,
|
||||
0x000000);
|
||||
HLock(dp);
|
||||
EMStartUp((Word)*dp, 0x14, 0, 0, 0, 0, MyID);
|
||||
|
||||
|
||||
if (argc != 2)
|
||||
{
|
||||
// todo: -vt52 -> start in vt52 mode (DECANM = 0)
|
||||
// todo:keypad flag of some sort?
|
||||
|
||||
if (argc != 2) {
|
||||
ErrWriteCString("Usage: marlene host[:port]\r\n");
|
||||
goto _exit;
|
||||
}
|
||||
|
||||
init_screen();
|
||||
screen_init();
|
||||
|
||||
init_ansi();
|
||||
vt100_init();
|
||||
|
||||
|
||||
TCPIPStatus();
|
||||
if (_toolErr)
|
||||
{
|
||||
display_str("\n\rLoading Marinetti...\n\r", 23);
|
||||
if (_toolErr) {
|
||||
display_cstr("Loading Marinetti...\n\r");
|
||||
LoadOneTool(0x36, 0x200); //load Marinetti
|
||||
if (_toolErr)
|
||||
{
|
||||
ErrWriteCString("Unable to load Marinetti\r\n");
|
||||
if (_toolErr) {
|
||||
display_cstr("Unable to load Marinetti.\r\n");
|
||||
goto _exit;
|
||||
}
|
||||
iLoaded = true;
|
||||
}
|
||||
|
||||
// Marinetti now loaded
|
||||
if (!TCPIPStatus())
|
||||
{
|
||||
display_str("\n\rStarting Marinetti...\n\r", 24);
|
||||
if (!TCPIPStatus()) {
|
||||
display_cstr("Starting Marinetti...\n\r");
|
||||
TCPIPStartUp();
|
||||
iStarted = true;
|
||||
}
|
||||
|
||||
if (!TCPIPGetConnectStatus())
|
||||
{
|
||||
display_str("\n\rConnecting Marinetti...\n\r", 26);
|
||||
if (!TCPIPGetConnectStatus()) {
|
||||
display_cstr("Connecting Marinetti...\n\r");
|
||||
TCPIPConnect(printCallBack);
|
||||
if (_toolErr)
|
||||
{
|
||||
ErrWriteCString("Unable to establish network connection\r\n");
|
||||
if (_toolErr) {
|
||||
display_cstr("Unable to establish network connection.\r\n");
|
||||
goto _exit;
|
||||
}
|
||||
iConnected = true;
|
||||
}
|
||||
// marinetti is now connected
|
||||
|
||||
if (!ResolveHost(argv[1], &cvt))
|
||||
{
|
||||
ErrWriteCString("Unable to resolve address\r\n");
|
||||
if (!ResolveHost(argv[1], &cvt)) {
|
||||
display_cstr("Unable to resolve address.\r\n");
|
||||
goto _exit;
|
||||
}
|
||||
|
||||
@ -380,88 +257,69 @@ static QuitRecGS qDCB = {2, 0, 0x4000};
|
||||
|
||||
ipid = TCPIPLogin(MyID, cvt.cvtIPAddress, cvt.cvtPort, 0, 0x0040);
|
||||
|
||||
display_str("\n\rConnecting to ", 16);
|
||||
display_str(str, TCPIPConvertIPToCAscii(cvt.cvtIPAddress, str, 0));
|
||||
TCPIPConvertIPToCASCII(cvt.cvtIPAddress, str, 0);
|
||||
display_cstr("Connecting to ");
|
||||
display_cstr(str);
|
||||
display_cstr("...\n\r");
|
||||
|
||||
TCPIPOpenTCP(ipid);
|
||||
|
||||
// wait for the connection to occur.
|
||||
while (1)
|
||||
{
|
||||
ok = WaitForStatus(ipid, TCPSESTABLISHED);
|
||||
if (ok > 0) display_err(ok);
|
||||
if (ok != 0) goto _exit2;
|
||||
|
||||
|
||||
display_cstr("Connected.\n\r");
|
||||
|
||||
telnet_init();
|
||||
|
||||
//fd = open ("tcp.log", O_TRUNC | O_WRONLY | O_CREAT, 0777);
|
||||
|
||||
for(;;) {
|
||||
static rrBuff rr;
|
||||
|
||||
|
||||
TCPIPPoll();
|
||||
err = TCPIPStatusTCP(ipid, &sr);
|
||||
if (err)
|
||||
{
|
||||
|
||||
rr.rrBuffCount = 0;
|
||||
err = TCPIPReadTCP(ipid, 0, (Ref)buffer, sizeof(buffer), &rr);
|
||||
// tcperrConClosing and tcperrClosing aren't fatal.
|
||||
|
||||
buffer_size = rr.rrBuffCount;
|
||||
if (buffer_size) err = 0;
|
||||
if (err) {
|
||||
if (err == tcperrConClosing || err == tcperrClosing)
|
||||
display_cstr("\r\nTCP Connection Closed.\r\n");
|
||||
else
|
||||
display_err(err);
|
||||
goto _exit1;
|
||||
}
|
||||
|
||||
if (sr.srState == tcpsESTABLISHED) break;
|
||||
//if (sr.srState == tcpsCLOSED) goto _exit1;
|
||||
GetNextEvent(keyDownMask | autoKeyMask ,&event);
|
||||
if (event.what != keyDownEvt) continue;
|
||||
if (!(event.modifiers & appleKey)) continue;
|
||||
if ((Word)event.message == '.') goto _exit1;
|
||||
if ((Word)event.message == 'q') goto _exit1;
|
||||
if ((Word)event.message == 'Q') goto _exit1;
|
||||
if (buffer_size) {
|
||||
telnet_process();
|
||||
}
|
||||
|
||||
display_str("\n\rConnected\n\r", 13);
|
||||
|
||||
|
||||
//fd = open ("tcp.log", O_TRUNC | O_WRONLY | O_CREAT, 0777);
|
||||
|
||||
Quit = false;
|
||||
|
||||
|
||||
iac_state = 0;
|
||||
while (!Quit)
|
||||
{
|
||||
|
||||
TCPIPPoll();
|
||||
|
||||
// check for incoming data...
|
||||
// 0xffff = no data
|
||||
// 0 = data
|
||||
// otherwise = marinetti error.
|
||||
err = GetChar(ipid, &c);
|
||||
|
||||
if (err && (err != 0xffff))
|
||||
{
|
||||
display_err(err);
|
||||
Quit++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (err == 0)
|
||||
{
|
||||
//if (fd > 0) write(fd, &c, 1);
|
||||
if (iac_state)
|
||||
iac_state = do_iac(iac_state, c, ipid);
|
||||
else if (modeTelnet && c == IAC)
|
||||
iac_state = do_iac(0, c, ipid);
|
||||
else display_str(&c, 1);
|
||||
if (buffer_size) {
|
||||
vt100_process(buffer, buffer_size);
|
||||
}
|
||||
|
||||
GetNextEvent(keyDownMask | autoKeyMask, &event);
|
||||
if (event.what != keyDownEvt) continue;
|
||||
c = key = event.message;
|
||||
if (event.what == keyDownEvt) {
|
||||
|
||||
if (event.modifiers & appleKey)
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
unsigned char key = event.message;
|
||||
|
||||
if (event.modifiers & appleKey) {
|
||||
switch (key) {
|
||||
case 'Q': // quit
|
||||
case 'q':
|
||||
Quit++;
|
||||
goto _exit1;
|
||||
break;
|
||||
case 'V': // paste
|
||||
case 'V': // paste...
|
||||
case 'v':
|
||||
break;
|
||||
case 'Z': // suspend (gnome)
|
||||
case 'z':
|
||||
if (__gno)
|
||||
{
|
||||
if (__gno) {
|
||||
static struct sgttyb sb;
|
||||
static int err;
|
||||
gtty(1,&sb);
|
||||
@ -475,27 +333,29 @@ static QuitRecGS qDCB = {2, 0, 0x4000};
|
||||
}
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
|
||||
} else {
|
||||
vt100_event(&event);
|
||||
}
|
||||
else send_event(&event, ipid);
|
||||
|
||||
}
|
||||
flush();
|
||||
}
|
||||
|
||||
_exit1:
|
||||
//if (fd > 0) close(fd);
|
||||
TCPIPCloseTCP(ipid);
|
||||
TCPIPPoll(); // wait until closed...
|
||||
TCPIPLogout(ipid);
|
||||
flush();
|
||||
|
||||
// be nice and
|
||||
while (GetNextEvent(keyDownMask | autoKeyMask, &event));
|
||||
display_str("\n\rPress any key to exit.\n\r", 26);
|
||||
while (!GetNextEvent(keyDownMask | autoKeyMask, &event));
|
||||
display_cstr("\n\rClosing TCP Connection...\n\r");
|
||||
|
||||
TCPIPCloseTCP(ipid);
|
||||
WaitForStatus(ipid, TCPSCLOSED);
|
||||
|
||||
_exit2:
|
||||
|
||||
|
||||
_exit:
|
||||
|
||||
if (ipid != -1) TCPIPLogout(ipid);
|
||||
|
||||
if (iConnected)
|
||||
TCPIPDisconnect(false, printCallBack);
|
||||
|
||||
@ -506,10 +366,17 @@ _exit:
|
||||
UnloadOneTool(0x36);
|
||||
|
||||
|
||||
// flush q
|
||||
while (GetNextEvent(keyDownMask | autoKeyMask, &event)) ;
|
||||
display_cstr("\n\rPress any key to exit.\n\r");
|
||||
while (!GetNextEvent(keyDownMask | autoKeyMask, &event)) ;
|
||||
|
||||
|
||||
EMShutDown();
|
||||
DisposeHandle(dp);
|
||||
GrafOff();
|
||||
TextShutDown();
|
||||
QuitGS(&qDCB);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
3
makefile
3
makefile
@ -1,5 +1,5 @@
|
||||
PROG = fctelnet
|
||||
OBJS = fctelnet.o vt100.o ansi.o chars.o marinetti.o display.o
|
||||
OBJS = fctelnet.o vt100.o telnet.o ansi.o chars.o marinetti.o display.o
|
||||
|
||||
OPTIMIZE *= 79
|
||||
|
||||
@ -16,6 +16,7 @@ vt100.o: vt100.c
|
||||
ansi.o: ansi.asm
|
||||
chars.o: chars.asm
|
||||
marinetti.o: marinetti.c
|
||||
telnet.o: telnet.c
|
||||
|
||||
clean:
|
||||
$(RM) -f *.o *.root *.a *.r
|
||||
|
64
marinetti.c
64
marinetti.c
@ -60,25 +60,21 @@ EventRecord event;
|
||||
else
|
||||
{
|
||||
TCPIPDNRNameToIP(pstr, &dnr);
|
||||
if (_toolErr)
|
||||
{
|
||||
if (_toolErr) {
|
||||
free(pstr);
|
||||
return false;
|
||||
}
|
||||
while (dnr.DNRStatus == DNRPending)
|
||||
{
|
||||
while (dnr.DNRStatus == DNRPending) {
|
||||
TCPIPPoll();
|
||||
GetNextEvent(keyDownMask | autoKeyMask, &event);
|
||||
if ((event.what == keyDownEvt)
|
||||
&& (event.modifiers & appleKey)
|
||||
&& ((Word)event.message == '.'))
|
||||
{
|
||||
&& ((Word)event.message == '.')) {
|
||||
TCPIPCancelDNR(&dnr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (dnr.DNRStatus == DNROK)
|
||||
{
|
||||
if (dnr.DNRStatus == DNROK) {
|
||||
cvt->cvtIPAddress = dnr.DNRIPAddress;
|
||||
cvt->cvtPort = port;
|
||||
free(pstr);
|
||||
@ -91,47 +87,25 @@ EventRecord event;
|
||||
return false;
|
||||
}
|
||||
|
||||
int WaitForStatus(word ipid, word status) {
|
||||
static srBuffer sr;
|
||||
EventRecord event;
|
||||
Word err;
|
||||
|
||||
/*
|
||||
* pcnt is the next place to store data
|
||||
* bptr is the current ptr.
|
||||
*/
|
||||
static unsigned char buffer[1024];
|
||||
static unsigned char pushback[1024];
|
||||
static int pcnt = 0;
|
||||
static int bcnt = 0;
|
||||
static int bptr = 0;
|
||||
static rrBuff rr;
|
||||
|
||||
Word GetChar(word ipid, unsigned char *c)
|
||||
{
|
||||
word err;
|
||||
|
||||
*c = 0;
|
||||
|
||||
if (pcnt)
|
||||
{
|
||||
*c = pushback[--pcnt];
|
||||
return 0;
|
||||
}
|
||||
if (!bcnt)
|
||||
{
|
||||
err = TCPIPReadTCP(ipid, 0, (Ref)buffer, 1024, &rr);
|
||||
bcnt = rr.rrBuffCount;
|
||||
bptr = 0;
|
||||
for(;;) {
|
||||
TCPIPPoll();
|
||||
err = TCPIPStatusTCP(ipid, &sr);
|
||||
if (err) return err;
|
||||
|
||||
if (sr.srState == status) return 0;
|
||||
GetNextEvent(keyDownMask | autoKeyMask, &event);
|
||||
if (event.what != keyDownEvt) continue;
|
||||
if (!(event.modifiers & appleKey)) continue;
|
||||
if ((Word)event.message == '.') return -1;
|
||||
//if ((Word)event.message == 'q') return -1;
|
||||
//if ((Word)event.message == 'Q') return -1;
|
||||
}
|
||||
if (bcnt)
|
||||
{
|
||||
bcnt--;
|
||||
*c = buffer[bptr++];
|
||||
return 0;
|
||||
}
|
||||
return 0xffff;
|
||||
}
|
||||
|
||||
void UngetChar(char c)
|
||||
{
|
||||
pushback[pcnt++] = c;
|
||||
}
|
||||
|
||||
|
929
vt100.c
929
vt100.c
@ -1,45 +1,95 @@
|
||||
/*
|
||||
* This handles vt100 commands.
|
||||
*
|
||||
*/
|
||||
#pragma noroot
|
||||
|
||||
#include <Types.h>
|
||||
#include <texttool.h>
|
||||
#include <Event.h>
|
||||
#include <ctype.h>
|
||||
// handle vt100 escape codes
|
||||
|
||||
extern void ReverseScrollRegion(word, word);
|
||||
extern void ScrollRegion(word, word);
|
||||
extern void ScrollDown(void);
|
||||
extern void PrintChar(int the_char, unsigned int andMask);
|
||||
#define ESC "\x1b"
|
||||
#define send_str(x) send((const unsigned char *)x, sizeof(x)-1)
|
||||
|
||||
extern void send(const unsigned char *, unsigned);
|
||||
|
||||
extern unsigned char buffer[];
|
||||
extern unsigned buffer_size;
|
||||
|
||||
|
||||
|
||||
extern void ReverseScrollRegion(unsigned, unsigned);
|
||||
extern void ScrollRegion(unsigned, unsigned);
|
||||
extern void PrintChar(unsigned x, unsigned y, unsigned the_char, unsigned andMask, unsigned eorMask);
|
||||
|
||||
extern void ClearScreen(void);
|
||||
extern void ClearScreenFrom(int Y);
|
||||
extern void ClearLine(int Y);
|
||||
extern void ClearLineFrom(int Y, int X);
|
||||
extern void ClearScreen2(unsigned start, unsigned end);
|
||||
extern void ClearLine(unsigned line);
|
||||
extern void ClearLine2(unsigned line, unsigned start, unsigned end);
|
||||
|
||||
extern void SetCursor(unsigned x, unsigned y);
|
||||
|
||||
extern pascal void SysBeep2(Word) inline(0x3803,dispatcher);
|
||||
|
||||
|
||||
word Xpos;
|
||||
word Ypos;
|
||||
static word __pos[2]; // saved cursor position
|
||||
word __scroll[2];
|
||||
word and_mask;
|
||||
word xor_mask;
|
||||
int __x;
|
||||
int __y;
|
||||
|
||||
|
||||
void init_ansi(void)
|
||||
static unsigned saved_cursor[2]; // saved cursor position
|
||||
static unsigned window[2];
|
||||
static unsigned and_mask;
|
||||
static unsigned xor_mask;
|
||||
|
||||
|
||||
static unsigned DECANM = 1;
|
||||
static unsigned DECAWM = 1;
|
||||
static unsigned DECCKM = 0;
|
||||
static unsigned DECKPAM = 0;
|
||||
static unsigned DECCOLM = 80;
|
||||
static unsigned DECOM = 0;
|
||||
static unsigned DECSCNM = 0;
|
||||
static unsigned LNM = 0;
|
||||
|
||||
unsigned tabs[9] = { 0 };
|
||||
|
||||
static unsigned parms[10];
|
||||
static unsigned parm_count;
|
||||
static unsigned private;
|
||||
static unsigned state;
|
||||
|
||||
void vt100_init(void)
|
||||
{
|
||||
Xpos = 0;
|
||||
Ypos = 0;
|
||||
__pos[0] = 0;
|
||||
__pos[1] = 0;
|
||||
__scroll[0] = 0;
|
||||
__scroll[1] = 23;
|
||||
__x = 0;
|
||||
__y = 0;
|
||||
saved_cursor[0] = 0;
|
||||
saved_cursor[1] = 0;
|
||||
window[0] = 0;
|
||||
window[1] = 23;
|
||||
and_mask = 0xffff;
|
||||
xor_mask = 0x0000;
|
||||
|
||||
DECANM = 1;
|
||||
DECAWM = 1;
|
||||
DECCKM = 0;
|
||||
DECKPAM = 0;
|
||||
DECCOLM = 80;
|
||||
DECOM = 0;
|
||||
DECSCNM = 0;
|
||||
LNM = 0;
|
||||
|
||||
tabs[0] = 0x8080;
|
||||
tabs[1] = 0x8080;
|
||||
tabs[2] = 0x8080;
|
||||
tabs[3] = 0x8080;
|
||||
tabs[4] = 0x0080;
|
||||
|
||||
parms[0] = 0;
|
||||
parm_count = 0;
|
||||
private = 0;
|
||||
state = 0;
|
||||
}
|
||||
|
||||
//not yet added:
|
||||
//esc[6n - return sursor position report
|
||||
//esc[m - set graphics mode
|
||||
//
|
||||
|
||||
#if 0
|
||||
void dump(const char * buffer, word cnt, int impl)
|
||||
{
|
||||
int i;
|
||||
@ -57,165 +107,114 @@ char c;
|
||||
}
|
||||
WriteCString("\r\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
static void cursor_left(void){
|
||||
unsigned n = parms[0];
|
||||
if (n == 0) n = 1;
|
||||
|
||||
void handle_ansi(word code, char *buffer, word cnt)
|
||||
{
|
||||
word i;
|
||||
word r0;
|
||||
word r1;
|
||||
//word r2;
|
||||
//word r3;
|
||||
word pop = 0;
|
||||
|
||||
|
||||
if (buffer[1] == '[')
|
||||
{
|
||||
i = 2;
|
||||
|
||||
switch (code)
|
||||
{
|
||||
case 'A': //cursor up
|
||||
// esc[#A
|
||||
r0 = 0;
|
||||
while (isdigit(buffer[i]))
|
||||
r0 = r0 * 10 + (buffer[i++] - '0');
|
||||
if (buffer[i] != 'A') pop = 1;
|
||||
else
|
||||
{
|
||||
if (!r0) r0 = 1;
|
||||
Ypos -= r0;
|
||||
if (Ypos < __scroll[0]) Ypos = __scroll[0];
|
||||
//if (Ypos > r0) Ypos -= r0;
|
||||
//else Ypos = 0;
|
||||
__x -= n;
|
||||
if (__x < 0) __x = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'B': //cursor down
|
||||
// esc[#B
|
||||
r0 = 0;
|
||||
while (isdigit(buffer[i]))
|
||||
r0 = r0 * 10 + (buffer[i++] - '0');
|
||||
if (buffer[i] != 'B') pop = 1;
|
||||
else
|
||||
{
|
||||
if (!r0) r0 = 1;
|
||||
Ypos += r0;
|
||||
if (Ypos > __scroll[1]) Ypos = __scroll[1];
|
||||
//if (Ypos + r0 > 24) Ypos = 24;
|
||||
//else Ypos += r0;
|
||||
static void cursor_right(void){
|
||||
unsigned n = parms[0];
|
||||
if (n == 0) n = 1;
|
||||
// edge case
|
||||
if (__x == 80) return;
|
||||
__x += n;
|
||||
if (__x >= 80) n = 79;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'C': // cursor forward
|
||||
// esc[#C
|
||||
r0 = 0;
|
||||
while (isdigit(buffer[i]))
|
||||
r0 = r0 * 10 + (buffer[i++] - '0');
|
||||
if (buffer[i] != 'C') pop = 1;
|
||||
else
|
||||
{
|
||||
if (!r0) r0 = 1;
|
||||
Xpos += r0;
|
||||
if (Xpos > 79) Xpos = 79;
|
||||
static void cursor_up(void) {
|
||||
unsigned n = parms[0];
|
||||
if (n == 0) n = 1;
|
||||
|
||||
/* can't escape scrolling region */
|
||||
if (__y >= window[0]) {
|
||||
__y -= n;
|
||||
if (__y < window[0]) __y = window[0];
|
||||
} else {
|
||||
__y -= n;
|
||||
if (__y < 0) __y = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'D': // cursor backward
|
||||
// esc[#D
|
||||
r0 = 0;
|
||||
while (isdigit(buffer[i]))
|
||||
r0 = r0 * 10 + (buffer[i++] - '0');
|
||||
if (buffer[i] != 'D') pop = 1;
|
||||
else
|
||||
{
|
||||
if (!r0) r0 = 1;
|
||||
Xpos -= r0;
|
||||
if (Xpos < 0) Xpos = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'H': //cursor position
|
||||
case 'f':
|
||||
//esc[#;#H or esc[;H or esc[H <?>
|
||||
//esc[#;#f or esc[;f or esc[f <?>
|
||||
if (cnt > 3)
|
||||
{
|
||||
r0 = r1 = 0;
|
||||
while (isdigit(buffer[i]))
|
||||
r0 = r0 * 10 + (buffer[i++] - '0');
|
||||
if (buffer[i++] != ';') pop = 1;
|
||||
else while (isdigit(buffer[i]))
|
||||
r1 = r1 * 10 + (buffer[i++] - '0');
|
||||
if (buffer[i] != 'H' && buffer[i] != 'f') pop = 1;
|
||||
if (r0 == 0) r0++;
|
||||
if (r1 == 0) r1++;
|
||||
}
|
||||
else r0 = r1 = 1;
|
||||
|
||||
if (!pop)
|
||||
{
|
||||
Xpos = r1 - 1;
|
||||
Ypos = r0 - 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'J':
|
||||
if (cnt == 3) //clear c
|
||||
{
|
||||
ClearLineFrom(Ypos, Xpos);
|
||||
if (Ypos < 23)
|
||||
ClearScreenFrom(Ypos+1);
|
||||
|
||||
}
|
||||
else if (cnt == 4 && buffer[2] == '2')
|
||||
{
|
||||
ClearScreen();
|
||||
//Ypos = 0; // cursor position unchanged
|
||||
//Xpos = 0;
|
||||
|
||||
static void cursor_down(void) {
|
||||
unsigned n = parms[0];
|
||||
if (n == 0) n = 1;
|
||||
|
||||
/* can't escape scrolling region */
|
||||
if (__y <= window[1]) {
|
||||
__y += n;
|
||||
if (__y > window[1]) __y = window[1];
|
||||
} else {
|
||||
__y += n;
|
||||
if (__y >= 24) __y = 23;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'K': //erase from cursor to end-of-line (including cursor)
|
||||
if (cnt == 3) // no parms
|
||||
ClearLineFrom(Ypos, Xpos);
|
||||
else dump(buffer, cnt,1);
|
||||
break;
|
||||
static void cursor_position(void) {
|
||||
unsigned y = parms[0];
|
||||
unsigned x = parms[1];
|
||||
|
||||
case 'L': // erase current line and
|
||||
// scroll preceding lines down 1
|
||||
// esc[#L
|
||||
ReverseScrollRegion(Ypos, __scroll[1]);
|
||||
break;
|
||||
if (y) --y;
|
||||
if (x) --x;
|
||||
|
||||
case 'M': // erase current line and
|
||||
//scroll following lines up 1
|
||||
// esc[#M
|
||||
ScrollRegion(Ypos, __scroll[1]);
|
||||
break;
|
||||
__x = x;
|
||||
if (x >= 80) x = 79;
|
||||
if (DECOM) {
|
||||
__y = window[0] + y;
|
||||
if (__y > window[1]) __y = window[1];
|
||||
} else {
|
||||
__y = y;
|
||||
if (__y >= 24) __y = 23;
|
||||
}
|
||||
}
|
||||
|
||||
case 's': // save cursor position
|
||||
__pos[0] = Xpos;
|
||||
__pos[1] = Ypos;
|
||||
break;
|
||||
static void cursor_position_vt52(void) {
|
||||
unsigned y = parms[0];
|
||||
unsigned x = parms[1];
|
||||
|
||||
case 'u': // restore cursor position
|
||||
Xpos = __pos[0];
|
||||
Ypos = __pos[1];
|
||||
break;
|
||||
if (y) --y;
|
||||
if (x) --x;
|
||||
|
||||
// not yet added!
|
||||
case 'n':
|
||||
break;
|
||||
case 'm':
|
||||
while (1)
|
||||
{
|
||||
r0 = 0;
|
||||
while (isdigit(buffer[i]))
|
||||
r0 = r0 * 10 + (buffer[i++] - '0');
|
||||
// if x or y are out of range, do not move them.
|
||||
|
||||
switch(r0)
|
||||
{
|
||||
if (x < 80) __x = x;
|
||||
|
||||
if (DECOM) {
|
||||
y = window[0] + y;
|
||||
if (y <= window[1]) __y = y;
|
||||
} else {
|
||||
if (y < 24) __y = y;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void scrolling_region(void) {
|
||||
unsigned top = parms[0];
|
||||
unsigned bottom = parms[1];
|
||||
|
||||
if (top) --top;
|
||||
if (!bottom) bottom = 24;
|
||||
--bottom;
|
||||
|
||||
|
||||
if (top < bottom && bottom < 24) {
|
||||
window[0] = top;
|
||||
window[1] = bottom;
|
||||
__y = DECOM ? top : 0;
|
||||
__x = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void set_attributes(void) {
|
||||
unsigned i;
|
||||
for (i = 0; i < parm_count; ++i) {
|
||||
switch(parms[i]) {
|
||||
case 0: // all attributes off
|
||||
and_mask = 0xffff;
|
||||
xor_mask = 0x0000;
|
||||
@ -230,50 +229,574 @@ word pop = 0;
|
||||
case 7://reverse video
|
||||
xor_mask = 0xffff;
|
||||
break;
|
||||
case 8://cancel
|
||||
and_mask = 0x0000;
|
||||
break;
|
||||
}
|
||||
if (buffer[i] == ';') i++;
|
||||
else if (buffer[i] == 'm') break;
|
||||
}
|
||||
}
|
||||
|
||||
static void set_mode(void) {
|
||||
|
||||
unsigned i;
|
||||
for (i = 0; i < parm_count; ++i) {
|
||||
switch(parms[i]) {
|
||||
case 1: if (private) DECCKM = 1; break;
|
||||
case 2: if (private) DECANM = 1; break;
|
||||
case 3: if (private) DECCOLM = 132; break;
|
||||
case 6: if (private) { DECOM = 1; __x = 0; __y = window[0]; } break;
|
||||
case 7: if (private) DECAWM = 1; break;
|
||||
case 20: if (!private) LNM = 1; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void reset_mode(void) {
|
||||
|
||||
unsigned i;
|
||||
for (i = 0; i < parm_count; ++i) {
|
||||
switch(parms[i]) {
|
||||
case 1: if (private) DECCKM = 0; break;
|
||||
case 2: if (private) DECANM = 0; break;
|
||||
case 3: if (private) DECCOLM = 80; break;
|
||||
case 6: if (private) { DECOM = 0; __x = 0; __y = 0; } break;
|
||||
case 7: if (private) DECAWM = 0; break;
|
||||
case 20: if (!private) LNM = 0; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void save_cursor(void) {
|
||||
saved_cursor[0] = __y;
|
||||
saved_cursor[1] = __x;
|
||||
}
|
||||
|
||||
static void restore_cursor(void) {
|
||||
__y = saved_cursor[0];
|
||||
__x = saved_cursor[1];
|
||||
// vt220+ also saves/restores DECAWM and DECOM...
|
||||
}
|
||||
|
||||
static void tab(void) {
|
||||
unsigned chunk;
|
||||
unsigned mask;
|
||||
|
||||
if (__x >= 80) return;
|
||||
|
||||
__x = __x + 1;
|
||||
chunk = __x >> 0x4;
|
||||
mask = 1 << (__x & 0x0f);
|
||||
|
||||
while (chunk < 5) {
|
||||
unsigned bits = tabs[chunk];
|
||||
if (!bits) {
|
||||
__x += 16;
|
||||
} else {
|
||||
do {
|
||||
if (bits & mask) return;
|
||||
++__x;
|
||||
mask <<= 1;
|
||||
} while (mask);
|
||||
}
|
||||
mask = 1;
|
||||
++chunk;
|
||||
}
|
||||
// nothing... go to right margin.
|
||||
__x = 79;
|
||||
}
|
||||
|
||||
|
||||
static void set_tab(void) {
|
||||
unsigned chunk;
|
||||
unsigned mask;
|
||||
|
||||
if (__x >= 80) return;
|
||||
|
||||
chunk = __x >> 0x04;
|
||||
mask = 1 << (__x & 0x0f);
|
||||
|
||||
tabs[chunk] |= mask;
|
||||
}
|
||||
|
||||
static void clear_tabs(void) {
|
||||
unsigned i;
|
||||
|
||||
unsigned chunk;
|
||||
unsigned mask;
|
||||
|
||||
for (i = 0; i < parm_count; ++i) {
|
||||
switch(parms[i]) {
|
||||
case 0:
|
||||
if (__x < 80) {
|
||||
chunk = __x >> 0x04;
|
||||
mask = 1 << (__x & 0x0f);
|
||||
tabs[chunk] &= ~mask;
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
tabs[0] = 0;
|
||||
tabs[1] = 0;
|
||||
tabs[2] = 0;
|
||||
tabs[3] = 0;
|
||||
tabs[4] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
case 'r': // #;#r == set scrolling region
|
||||
// esc[#;#r
|
||||
r0 = r1 = 0;
|
||||
}
|
||||
|
||||
while (isdigit(buffer[i]))
|
||||
r0 = r0 * 10 + (buffer[i++] - '0');
|
||||
if (buffer[i++] != ';') pop = 1;
|
||||
else while (isdigit(buffer[i]))
|
||||
r1 = r1 * 10 + (buffer[i++] - '0');
|
||||
if (buffer[i] != 'r') pop = 1;
|
||||
if (r0 && r1 && !pop)
|
||||
static void linefeed(void) {
|
||||
if (__y == window[1]) {
|
||||
ScrollRegion(window[0], window[1]+1);
|
||||
} else ++__y;
|
||||
}
|
||||
|
||||
static void reverse_linefeed(void) {
|
||||
if (__y == window[0]) {
|
||||
ReverseScrollRegion(window[0], window[1]+1);
|
||||
} else --__y;
|
||||
}
|
||||
|
||||
static void erase_line(void) {
|
||||
unsigned i;
|
||||
for (i = 0; i < parm_count; ++i) {
|
||||
switch(parms[i]) {
|
||||
case 0:
|
||||
ClearLine2(__y, __x, 80);
|
||||
break;
|
||||
case 1:
|
||||
ClearLine2(__y, 0, __x + 1);
|
||||
break;
|
||||
case 2:
|
||||
ClearLine(__y);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void erase_screen(void) {
|
||||
unsigned i;
|
||||
for (i = 0; i < parm_count; ++i) {
|
||||
switch(parms[i]) {
|
||||
case 0:
|
||||
ClearLine2(__y, __x, 80);
|
||||
ClearScreen2(__y + 1, 24);
|
||||
break;
|
||||
case 1:
|
||||
ClearLine2(__y, 0, __x + 1);
|
||||
ClearScreen2(0, __y);
|
||||
break;
|
||||
case 2:
|
||||
ClearScreen();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Device Status Report */
|
||||
static void dsr(void) {
|
||||
unsigned i;
|
||||
for (i = 0; i < parm_count; ++i) {
|
||||
switch(parms[i]) {
|
||||
case 0: send_str(ESC "[0n"); break;
|
||||
case 5: { /* cursor position */
|
||||
static char buffer[16];
|
||||
unsigned i = 15;
|
||||
unsigned x = __x + 1;
|
||||
unsigned y = __y + 1;
|
||||
if (DECOM) y += window[0];
|
||||
buffer[i--] = ']';
|
||||
while(x) {
|
||||
buffer[i--] = '0' + (x % 10);
|
||||
x = x / 10;
|
||||
}
|
||||
buffer[i--] = ';';
|
||||
while(y) {
|
||||
buffer[i--] = '0' + (y % 10);
|
||||
y = y / 10;
|
||||
}
|
||||
buffer[i--] = '[';
|
||||
buffer[i] = 0x1b;
|
||||
send(buffer + i, 16 - i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum {
|
||||
st_text,
|
||||
st_escape,
|
||||
st_escape_v52,
|
||||
st_dca1,
|
||||
st_dca2,
|
||||
st_pound,
|
||||
st_rparen,
|
||||
st_lparen,
|
||||
st_lbracket,
|
||||
st_lbracket2,
|
||||
st_parm,
|
||||
};
|
||||
|
||||
static void do_control(char c) {
|
||||
switch(c) {
|
||||
case 005: /* ENQ */ break;
|
||||
case 007: /* BEL */ SysBeep2(0); break;
|
||||
case 010: /* BS */ if (__x) --__x; break;
|
||||
case 011: /* HT */ tab(); break;
|
||||
case 012: /* LF */
|
||||
case 013: /* VT */
|
||||
case 014: /* FF */
|
||||
linefeed();
|
||||
if (LNM) __x = 0;
|
||||
break;
|
||||
case 015: /* CR */ __x = 0; break;
|
||||
case 016: /* SO */ break;
|
||||
case 017: /* SI */ break;
|
||||
case 021: /* XON */ break;
|
||||
case 023: /* XOFF */ break;
|
||||
|
||||
case 030: /* CAN */
|
||||
case 032: /* SUB */
|
||||
state = st_text; break;
|
||||
case 033: /* ESC */
|
||||
switch (state) {
|
||||
case st_text: state = DECANM ? st_escape : st_escape_v52; break;
|
||||
case st_escape_v52:
|
||||
case st_escape:
|
||||
break;
|
||||
default:
|
||||
state = st_text;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void vt100_process(const unsigned char *buffer, unsigned buffer_size) {
|
||||
|
||||
unsigned i;
|
||||
for (i = 0; i < buffer_size; ++i) {
|
||||
unsigned char c = buffer[i] & 0x7f;
|
||||
if (c == 0 || c == 0x7f) continue;
|
||||
if (c < 0x20) {
|
||||
do_control(c);
|
||||
continue;
|
||||
}
|
||||
switch (state) {
|
||||
case st_text:
|
||||
if (__x == 80) {
|
||||
if (DECAWM) {
|
||||
__x = 0;
|
||||
if (__y == window[1]) {
|
||||
ScrollRegion(window[0], window[1]+1);
|
||||
} else ++__y;
|
||||
} else {
|
||||
__x = 79;
|
||||
}
|
||||
}
|
||||
PrintChar(__x, __y, c, and_mask, xor_mask);
|
||||
++__x;
|
||||
|
||||
break;
|
||||
|
||||
case st_escape:
|
||||
switch (c) {
|
||||
case '#': state = st_pound; break;
|
||||
case '(': state = st_lparen; break;
|
||||
case ')': state = st_rparen; break;
|
||||
case '[': state = st_lbracket; break;
|
||||
case 'E': /* next line */ __x = 0; /* drop through */
|
||||
case 'D': /* index */ linefeed(); break;
|
||||
case 'H': set_tab(); break;
|
||||
case 'M': /* reverse index */ reverse_linefeed(); break;
|
||||
case 'Z': send_str(ESC "[?1;0c"); break;
|
||||
case '7': save_cursor(); break;
|
||||
case '8': restore_cursor(); break;
|
||||
case '=': DECKPAM = 1; break;
|
||||
case '>': DECKPAM = 0; break;
|
||||
case 'c': vt100_init(); ClearScreen(); break;
|
||||
case '1': case '2': /* vt105 graphic stuff */ break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (state == st_escape) state = st_text;
|
||||
break;
|
||||
|
||||
case st_pound:
|
||||
/* #8 -> fill with Es */
|
||||
state = st_text; break;
|
||||
case st_lparen:
|
||||
case st_rparen:
|
||||
state = st_text; break;
|
||||
break;
|
||||
|
||||
case st_lbracket:
|
||||
private = 0;
|
||||
parm_count = 0;
|
||||
parms[0] = 0;
|
||||
parms[1] = 0;
|
||||
if (c == '?') { private = 1; state = st_parm; continue; }
|
||||
if (isdigit(c)) {
|
||||
parms[0] = c - '0';
|
||||
state = st_parm;
|
||||
break;
|
||||
}
|
||||
/* fall through */
|
||||
case st_lbracket2:
|
||||
lbracket2:
|
||||
switch (c) {
|
||||
case 'A': cursor_up(); break;
|
||||
case 'B': cursor_down(); break;
|
||||
case 'C': cursor_right(); break;
|
||||
case 'D': cursor_left(); break;
|
||||
case 'H': case 'f': cursor_position(); break;
|
||||
case 'K': erase_line(); break;
|
||||
case 'J': erase_screen(); break;
|
||||
case 'c': if (parms[0] == 0) send_str(ESC "[?1;0c"); break;
|
||||
case 'g': clear_tabs(); break;
|
||||
case 'h': set_mode(); break;
|
||||
case 'l': reset_mode(); break;
|
||||
case 'm': set_attributes(); break;
|
||||
case 'n': dsr(); break;
|
||||
case 'r': scrolling_region(); break;
|
||||
}
|
||||
state = st_text;
|
||||
break;
|
||||
|
||||
case st_parm:
|
||||
if (isdigit(c)) {
|
||||
parms[parm_count] *= 10;
|
||||
parms[parm_count] += c - '0';
|
||||
continue;
|
||||
}
|
||||
if (c == ';') {
|
||||
if (parm_count < 10) ++parm_count;
|
||||
parms[parm_count] = 0;
|
||||
continue;
|
||||
}
|
||||
state = st_lbracket2;
|
||||
goto lbracket2;
|
||||
|
||||
case st_escape_v52:
|
||||
parm_count = 0;
|
||||
parms[0] = 0;
|
||||
if (c == 'Y') { state = st_dca1; break; }
|
||||
switch (c) {
|
||||
case 'A': cursor_up(); break;
|
||||
case 'B': cursor_down(); break;
|
||||
case 'C': cursor_right(); break;
|
||||
case 'D': cursor_left(); break;
|
||||
case 'F': case 'G': break; /* graphics mode */
|
||||
case 'H': cursor_position(); break;
|
||||
case 'I': reverse_linefeed(); break;
|
||||
case 'J': erase_screen(); break;
|
||||
case 'K': erase_line(); break;
|
||||
case 'Z': send_str(ESC "/Z"); break;
|
||||
case '=': DECKPAM = 1; break;
|
||||
case '>': DECKPAM = 0; break;
|
||||
case '<': DECANM = 1; break;
|
||||
|
||||
}
|
||||
state = st_text;
|
||||
break;
|
||||
case st_dca1:
|
||||
parms[0] = c - 0x20;
|
||||
state = st_dca2;
|
||||
break;
|
||||
case st_dca2:
|
||||
parms[1] = c - 0x20;
|
||||
cursor_position_vt52();
|
||||
state = st_text;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// remap the iigs key to a vt100 code (if necessary) and send it out.
|
||||
|
||||
/*
|
||||
* see Apple IIgs Toolbox Ref Volume 1, 3-22. (ADB codes)
|
||||
*/
|
||||
void vt100_event(EventRecord *event) {
|
||||
unsigned char *cp;
|
||||
int len = 0;
|
||||
unsigned char key;
|
||||
word mods;
|
||||
|
||||
key = event->message;
|
||||
mods = event->modifiers;
|
||||
|
||||
|
||||
/* iigs -> vt100
|
||||
* clear -> PF1
|
||||
* = -> PF2
|
||||
* / -> PF3
|
||||
* * -> PF4
|
||||
* + -> -
|
||||
* - -> ,
|
||||
* . -> .
|
||||
*
|
||||
*
|
||||
* win32 layout:
|
||||
* numlock -> PF1
|
||||
* / -> PF2
|
||||
* * -> PF3
|
||||
* - -> PF4
|
||||
* shift+ -> -
|
||||
* + -> ,
|
||||
*
|
||||
* ------
|
||||
* option - , 1 2 3 4 to use normal keys as keypad.
|
||||
*/
|
||||
|
||||
if (mods & keyPad) {
|
||||
switch (key) {
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
case '.':
|
||||
case '-':
|
||||
case ',':
|
||||
{
|
||||
__scroll[0] = r0 - 1;
|
||||
__scroll[1] = r1 - 1;
|
||||
static unsigned char buffer[3] = { 0x1b, 'x', 'x' };
|
||||
if (DECKPAM) {
|
||||
cp = buffer; len = 3;
|
||||
buffer[2] = key | 0x40;
|
||||
buffer[1] = DECANM ? 'O' : '?';
|
||||
} else {
|
||||
len = 1;
|
||||
cp = &key;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x0d: // enter
|
||||
if (DECKPAM) {
|
||||
cp = DECANM ? ESC "OM" : ESC "?M";
|
||||
len = 3;
|
||||
} else goto enter;
|
||||
break;
|
||||
|
||||
|
||||
case 0x7a: // f1
|
||||
if (DECANM) { cp = ESC "OP"; len = 3; }
|
||||
else { cp = ESC "P"; len = 2; }
|
||||
break;
|
||||
|
||||
case 0x78: // f2
|
||||
if (DECANM) { cp = ESC "OQ"; len = 3; }
|
||||
else { cp = ESC "Q"; len = 2; }
|
||||
break;
|
||||
|
||||
case 0x63: // f3
|
||||
if (DECANM) { cp = ESC "OR"; len = 3; }
|
||||
else { cp = ESC "R"; len = 2; }
|
||||
break;
|
||||
|
||||
case 0x76: // f4
|
||||
if (DECANM) { cp = ESC "OS"; len = 3; }
|
||||
else { cp = ESC "S"; len = 2; }
|
||||
break;
|
||||
|
||||
/* Real IIgs keyboard - clear = 0x18, =, /, * for PF1-4? */
|
||||
case 0x18: // clear - PF1 on IIgs keyboard
|
||||
if (0) {
|
||||
if (DECANM) { cp = ESC "OP"; len = 3; }
|
||||
else { cp = ESC "P"; len = 2; }
|
||||
}
|
||||
break;
|
||||
|
||||
case '=': // PF2 on IIgs keyboard
|
||||
if (0) {
|
||||
if (DECANM) { cp = ESC "OQ"; len = 3; }
|
||||
else { cp = ESC "Q"; len = 2; }
|
||||
}
|
||||
break;
|
||||
|
||||
case '/': // PF3 on IIgs keyboard
|
||||
if (0) {
|
||||
if (DECANM) { cp = ESC "OR"; len = 3; }
|
||||
else { cp = ESC "R"; len = 2; }
|
||||
} else {
|
||||
len = 1;
|
||||
cp = &key;
|
||||
}
|
||||
break;
|
||||
|
||||
case '*': // PF4 on IIgs keyboard
|
||||
if (0) {
|
||||
if (DECANM) { cp = ESC "OS"; len = 3; }
|
||||
else { cp = ESC "S"; len = 2; }
|
||||
} else {
|
||||
len = 1;
|
||||
cp = &key;
|
||||
}
|
||||
break;
|
||||
|
||||
case '+':
|
||||
// send as normal key.
|
||||
len = 1;
|
||||
cp = &key;
|
||||
break;
|
||||
|
||||
default: return;
|
||||
}
|
||||
} else if (mods & controlKey) {
|
||||
cp = &key;
|
||||
len = 1;
|
||||
} else {
|
||||
switch(key) {
|
||||
case 0x0d:
|
||||
enter:
|
||||
if (LNM) { cp = "\r\n"; len = 2; }
|
||||
else { cp = "\r"; len = 1; }
|
||||
break;
|
||||
case 0x08: // <--- arrow
|
||||
// todo -- cursor keys
|
||||
if (DECANM) {
|
||||
cp = DECCKM ? ESC "OD" : ESC "[D";
|
||||
len = 3;
|
||||
} else { cp = ESC "D"; len = 2; }
|
||||
break;
|
||||
case 0x0A: // down arrow
|
||||
if (DECANM) {
|
||||
cp = DECCKM ? ESC "OB" : ESC "[B";
|
||||
len = 3;
|
||||
} else { cp = ESC "B"; len = 2; }
|
||||
break;
|
||||
case 0x0B: // up arrow
|
||||
if (DECANM) {
|
||||
cp = DECCKM ? ESC "OA" : ESC "[A";
|
||||
len = 3;
|
||||
} else { cp = ESC "A"; len = 2; }
|
||||
|
||||
break;
|
||||
case 0x15: // ---> arrow
|
||||
if (DECANM) {
|
||||
cp = DECCKM ? ESC "OC" : ESC "[C";
|
||||
len = 3;
|
||||
} else { cp = ESC "C"; len = 2; }
|
||||
break;
|
||||
|
||||
// backspace to delete char
|
||||
case 0x7f: // delete
|
||||
cp = "\x08";
|
||||
len = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
dump(buffer, cnt,1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(buffer[1])
|
||||
{
|
||||
case 'M': // scroll screen down 1 line
|
||||
ReverseScrollRegion(__scroll[0], __scroll[1]);
|
||||
break;
|
||||
case '=': // alt key pad
|
||||
case '>': // normal key pad
|
||||
break;
|
||||
default:
|
||||
dump(buffer, cnt,1);
|
||||
|
||||
if (key < 0x7f) {
|
||||
cp = &key; len = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (len) send(cp, len);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user