Compare commits

...

7 Commits
r2 ... master

Author SHA1 Message Date
Kelvin Sherlock 4da75367c1 (re)set the controlling terminal.
This is necessary to read input from the console (via the Event Manager) since opening a pseudo terminal screws up the controlling terminal (and there is no O_NOCTTY flag).
2019-10-03 00:05:21 -04:00
Kelvin Sherlock d77291a0c0 default tabstops were off by 1. 2019-01-08 20:33:38 -05:00
Kelvin Sherlock d3addc3050 esc [ 3 g is clear all tabs. was esc [ 5 g . 2019-01-08 19:31:39 -05:00
Kelvin Sherlock 2079d4b442 ADB extended keycodes (from OS X Events) 2019-01-04 21:15:08 -05:00
Kelvin Sherlock 58ab674589 add FillChar routine to support ESC #8 2018-05-26 22:49:12 -04:00
Kelvin Sherlock 5c0764e5b9 flags to initialize vt100 parameters. 2018-05-14 09:20:05 -04:00
Kelvin Sherlock 58e63dc252 tweak cursor positioning. fix for esc [ ; H, etc 2018-05-13 08:42:14 -04:00
9 changed files with 532 additions and 47 deletions

View File

@ -19,7 +19,7 @@ marlene: $(MARLENE_OBJS) $(COMMON_OBJS)
darlene: $(DARLENE_OBJS) $(COMMON_OBJS)
$(CC) -lutil -o $@ $^
iix chtyp -a 0xdc00 $@
# iix chtyp -a 0xdc00 $@

137
ansi.asm
View File

@ -1,8 +1,14 @@
case on
mcopy ansi.mac
dummy start
end
RDMAINRAM gequ $E0C002 ; Read from main memory
RDCARDRAM gequ $E0C003 ; Read from auxiliary memory
WRMAINRAM gequ $E0C004 ; Write to main memory
WRCARDRAM gequ $E0C005 ; Write to auxiliary memory
tables privdata
;
@ -641,6 +647,137 @@ exit anop
end
; FillChar(char, andMask, xorMask)
gen on
FillChar START
using tables
subroutine (2:char,2:andMask,2:xorMask),(16:cdata)
xx equ andMask
yy equ xorMask
lda <char
cmp #$7f
bcs space
sec
sbc #$20
bmi space
asl a ; x2
asl a ; x4
asl a ; x8
asl a ; x16
tax
bra ok
space anop
ldx #0 ; char
ok anop
; pre-calc the char mask to data.
lda CHAR_SPACE,x
eor <xorMask
and <andMask
sta cdata
lda CHAR_SPACE+2,x
eor <xorMask
and <andMask
sta cdata+2
lda CHAR_SPACE+4,x
eor <xorMask
and <andMask
sta cdata+4
lda CHAR_SPACE+6,x
eor <xorMask
and <andMask
sta cdata+6
lda CHAR_SPACE+8,x
eor <xorMask
and <andMask
sta cdata+8
lda CHAR_SPACE+10,x
eor <xorMask
and <andMask
sta cdata+10
lda CHAR_SPACE+12,x
eor <xorMask
and <andMask
sta cdata+12
lda CHAR_SPACE+14,x
eor <xorMask
and <andMask
sta cdata+14
pea $e1e1
plb
plb
lda #24
sta yy
ldx #0*8*160+4*160+$2000
yloop anop
lda cdata+0
jsr one_line
lda cdata+2
jsr one_line
lda cdata+4
jsr one_line
lda cdata+6
jsr one_line
lda cdata+8
jsr one_line
lda cdata+10
jsr one_line
lda cdata+12
jsr one_line
lda cdata+14
jsr one_line
dec yy
bne yloop
exit anop
return
end
one_line private
; a = character data
; x = memory address
ldy #80
loop anop
sta |$0000,x
inx
inx
dey
bne loop
rts
end
HideCursor start
using cursor_data

245
ansi.mac Normal file
View File

@ -0,0 +1,245 @@
macro
&l _ldy &r
&l anop
aif "&r"="@a",.a
aif "&r"="@x",.x
aif "&r"="@y",.y
ldy &r
ago .y
.a
tay
ago .y
.x
txy
ago .y
.y
mend
macro
&l subroutine &parms,&locals
&l anop
gbla &totallen
gbla &worklen
gbla &returnlen
&worklen seta 0
&totallen seta 0
&returnlen seta 4
lclc &len
lclc &p
lcla &i
phb
aif c:&locals=0,.doparms
.dolocals
&i seta 1
.bb
&p setc &locals(&i)
&len amid &p,2,1
aif "&len"=":",.cc
&len amid &p,1,2
&p amid &p,4,l:&p-3
ago .dd
.cc
&len amid &p,1,1
&p amid &p,3,l:&p-2
.dd
&p equ &worklen+1
&worklen seta &worklen+&len
&i seta &i+1
aif &i<=c:&locals,^bb
.doparms
aif c:&parms=0,.e
&i seta 1
.b
&p setc &parms(&i)
&len amid &p,2,1
aif "&len"=":",.c
&len amid &p,1,2
&p amid &p,4,l:&p-3
ago .d
.c
&len amid &p,1,1
&p amid &p,3,l:&p-2
.d
&p equ &totallen+&returnlen+1+&worklen
&totallen seta &totallen+&len
&i seta &i+1
aif &i<=c:&parms,^b
.e
tsc
aif &worklen=0,.f
sec
sbc #&worklen
tcs
.f
phd
tcd
mend
macro
&l lsubroutine &parms,&locals
&l anop
gbla &totallen
gbla &worklen
gbla &returnlen
&worklen seta 0
&totallen seta 0
&returnlen seta 2
lclc &len
lclc &p
lcla &i
aif c:&locals=0,.doparms
.dolocals
&i seta 1
.bb
&p setc &locals(&i)
&len amid &p,2,1
aif "&len"=":",.cc
&len amid &p,1,2
&p amid &p,4,l:&p-3
ago .dd
.cc
&len amid &p,1,1
&p amid &p,3,l:&p-2
.dd
&p equ &worklen+1
&worklen seta &worklen+&len
&i seta &i+1
aif &i<=c:&locals,^bb
.doparms
aif c:&parms=0,.e
&i seta 1
.b
&p setc &parms(&i)
&len amid &p,2,1
aif "&len"=":",.c
&len amid &p,1,2
&p amid &p,4,l:&p-3
ago .d
.c
&len amid &p,1,1
&p amid &p,3,l:&p-2
.d
&p equ &totallen+&return+1+&worklen
&totallen seta &totallen+&len
&i seta &i+1
aif &i<=c:&parms,^b
.e
tsc
aif &worklen=0,.f
sec
sbc #&worklen
tcs
.f
phd
tcd
mend
macro
&l return &r
&l anop
lclc &len
aif c:&r,.a
lclc &r
&r setc 0
&len setc 0
ago .h
.a
&len amid &r,2,1
aif "&len"=":",.b
&len amid &r,1,2
&r amid &r,4,l:&r-3
ago .c
.b
&len amid &r,1,1
&r amid &r,3,l:&r-2
.c
aif &len<>2,.d
_ldy &r
ago .h
.d
aif &len<>4,.e
ldx &r+2
ldy &r
ago .h
.e
aif &len<>10,.g
ldy #&r
ldx #^&r
ago .h
.g
mnote 'Not a valid return length',16
mexit
.h
aif &totallen=0,.i
lda &worklen+3
sta &worklen+&totallen+3
lda &worklen+1
sta &worklen+&totallen+1
.i
pld
tsc
clc
adc #&worklen+&totallen
tcs
aif &len=0,.j
tya
.j
plb
rtl
mend
macro
&l lreturn &r
&l anop
lclc &len
aif c:&r,.a
lclc &r
&r setc 0
&len setc 0
ago .h
.a
&len amid &r,2,1
aif "&len"=":",.b
&len amid &r,1,2
&r amid &r,4,l:&r-3
ago .c
.b
&len amid &r,1,1
&r amid &r,3,l:&r-2
.c
aif &len<>2,.d
_ldy &r
ago .h
.d
aif &len<>4,.e
ldx &r+2
ldy &r
ago .h
.e
aif &len<>10,.g
ldy #&r
ldx #^&r
ago .h
.g
mnote 'Not a valid return length',16
mexit
.h
aif &totallen=0,.i
lda &worklen+1
sta &worklen+&totallen+1
.i
pld
tsc
clc
adc #&worklen+&totallen
tcs
aif &len=0,.j
tya
.j
rts
mend

View File

@ -25,9 +25,7 @@
#include <gno/gno.h>
#include <gno/kerntool.h>
extern void vt100_init(void);
extern void vt100_process(const unsigned char *buffer, unsigned buffer_size);
extern void vt100_event(EventRecord *event);
#include "vt100.h"
extern void screen_init(void);
extern void screen_on(void);
@ -182,7 +180,7 @@ int main(int argc, char **argv) {
int pid;
unsigned i;
Word MyID;
unsigned vt100_flags = vtDEFAULT;
Handle dpHandle = NULL;
Handle shrHandle = NULL;
Handle shdHandle = NULL;
@ -194,17 +192,24 @@ int main(int argc, char **argv) {
return 1;
}
if (!isatty(STDIN_FILENO)) {
ErrWriteCString("stdin required.\r\n");
return 1;
}
term_var.value = "\x05\x00vt100";
child_argv = NULL;
for (i = 1; i < argc; ++i) {
char *cp = argv[i];
if (cp[0] != '-') break;
if (strcmp(cp, "--vt52") == 0) {
if (strcmp(cp, "--") == 0) {
break;
} else if (strcmp(cp, "--vt52") == 0) {
term_var.value = "\x04\x00vt52";
vt100_flags &= ~vtDECANM;
} else if (strcmp(cp, "--vt100") == 0) {
term_var.value = "\x05\x00vt100";
} else if (strcmp(cp,"--") == 0) {
break;
vt100_flags |= vtDECANM;
} else {
ErrWriteCString("Unknown option: ");
ErrWriteCString(cp);
@ -251,7 +256,7 @@ int main(int argc, char **argv) {
screen_init();
vt100_init();
vt100_init(vt100_flags);
signal(SIGCHLD,sigchild);
pid = forkpty2(&master, NULL, NULL, NULL);
@ -260,6 +265,11 @@ int main(int argc, char **argv) {
goto _exit;
}
/* reset the controlling terminal, which was clobbered by opening a pty */
/* standard TIOCSCTTY causes ORCA/C shift errors */
#undef TIOCSCTTY
#define TIOCSCTTY (0x20000000ul | ('t' << 8) | 97)
ioctl(STDIN_FILENO, TIOCSCTTY, (void *)0);
for(;;) {

View File

@ -22,7 +22,7 @@
#include "telnet.h"
#include "marinetti.h"
#include "vt100.h"
void display_pstr(const char *);
void display_cstr(const char *);
@ -31,9 +31,6 @@ void display_err(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);
extern void screen_init(void);
extern void screen_on(void);
@ -113,7 +110,7 @@ int main(int argc, char **argv) {
int mf = 0;
Word MyID;
Word __gno;
unsigned vt100_flags = vtDEFAULT;
__gno = false;
ipid = -1;
@ -131,10 +128,12 @@ int main(int argc, char **argv) {
for (i = 1; i < argc; ++i) {
char *cp = argv[i];
if (cp[0] != '-') break;
if (strcmp(cp, "--vt52") == 0) {
if (strcmp(cp, "--") == 0) {
break;
} else if (strcmp(cp, "--vt52") == 0) {
vt100_flags &= ~vtDECANM;
} else if (strcmp(cp, "--vt100") == 0) {
vt100_flags |= vtDECANM;
} else {
ErrWriteCString("Unknown option: ");
ErrWriteCString(cp);
@ -177,7 +176,7 @@ int main(int argc, char **argv) {
screen_init();
vt100_init();
vt100_init(vt100_flags);
mf = StartUpTCP(printCallBack);
if (mf < 0) {

View File

@ -108,12 +108,16 @@ void telnet_process(void) {
IAC, SE
};
static unsigned char telopt_ttype[] = {
static unsigned char telopt_ttype_vt100[] = {
IAC, SB, TELOPT_TTYPE, TELQUAL_IS,
'V', 'T', '1', '0', '0',
IAC, SE
};
static unsigned char telopt_ttype_vt52[] = {
IAC, SB, TELOPT_TTYPE, TELQUAL_IS,
'V', 'T', '5', '2',
IAC, SE
};
/* don't need to process if no state, no IACs in buffer */
@ -186,7 +190,7 @@ void telnet_process(void) {
send(telopt_tspeed, sizeof(telopt_tspeed));
break;
case TELOPT_TTYPE:
send(telopt_ttype, sizeof(telopt_ttype));
send(telopt_ttype_vt100, sizeof(telopt_ttype_vt100));
break;
default:

111
vt100.c
View File

@ -2,11 +2,12 @@
* This handles vt100 commands.
*
*/
#pragma noroot
#include <Event.h>
#include <ctype.h>
#include "vt100.h"
#define ESC "\x1b"
#define send_str(x) send((const unsigned char *)x, sizeof(x)-1)
@ -20,6 +21,7 @@ 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 FillChar(unsigned the_char, unsigned andMask, unsigned eorMask);
extern void ClearScreen(void);
extern void ClearScreen2(unsigned start, unsigned end);
@ -63,8 +65,11 @@ static unsigned parm_count;
static unsigned private;
static unsigned state;
void vt100_init(void)
static unsigned initial_state = vtDEFAULT;
void vt100_init(unsigned flags)
{
__x = 0;
__y = 0;
saved_cursor[0] = 0;
@ -74,20 +79,32 @@ void vt100_init(void)
and_mask = 0xffff;
xor_mask = 0x0000;
DECANM = 1;
DECAWM = 1;
DECCKM = 0;
DECKPAM = 0;
DECCOLM = 80;
DECOM = 0;
DECSCNM = 0;
LNM = 0;
initial_state = flags;
if (flags == -1) {
DECANM = 1;
DECAWM = 1;
DECCKM = 0;
DECKPAM = 0;
DECCOLM = 80;
DECOM = 0;
DECSCNM = 0;
LNM = 0;
} else {
DECANM = flags & vtDECANM;
DECAWM = flags & vtDECAWM;
DECCKM = flags & vtDECCKM;
DECKPAM = flags & vtDECKPAM;
DECCOLM = flags & vtDECCOLM ? 132 : 80;
DECOM = flags & vtDECOM;
DECSCNM = flags & vtDECSCNM;
LNM = flags & vtLNM;
}
tabs[0] = 0x8080;
tabs[1] = 0x8080;
tabs[2] = 0x8080;
tabs[3] = 0x8080;
tabs[4] = 0x0080;
tabs[0] = 0x0100;
tabs[1] = 0x0101;
tabs[2] = 0x0101;
tabs[3] = 0x0101;
tabs[4] = 0x0101;
parms[0] = 0;
parm_count = 0;
@ -170,15 +187,15 @@ static void cursor_position(void) {
if (y) --y;
if (x) --x;
__x = x;
if (x >= 80) x = 79;
if (DECOM) {
__y = window[0] + y;
if (__y > window[1]) __y = window[1];
y = window[0] + y;
if (y > window[1]) y = window[1];
} else {
__y = y;
if (__y >= 24) __y = 23;
if (y >= 24) y = 23;
}
__x = x;
__y = y;
}
static void cursor_position_vt52(void) {
@ -338,7 +355,7 @@ static void clear_tabs(void) {
tabs[chunk] &= ~mask;
}
break;
case 5:
case 3:
tabs[0] = 0;
tabs[1] = 0;
tabs[2] = 0;
@ -521,7 +538,7 @@ void vt100_process(const unsigned char *buffer, unsigned buffer_size) {
case '8': restore_cursor(); break;
case '=': DECKPAM = 1; break;
case '>': DECKPAM = 0; break;
case 'c': vt100_init(); ClearScreen(); break;
case 'c': vt100_init(initial_state); ClearScreen(); break;
case '1': case '2': /* vt105 graphic stuff */ break;
default:
break;
@ -531,6 +548,9 @@ void vt100_process(const unsigned char *buffer, unsigned buffer_size) {
case st_pound:
/* #8 -> fill with Es */
if (c == '8') {
FillChar('E', 0xffff, 0x0000);
}
state = st_text; break;
case st_lparen:
case st_rparen:
@ -548,6 +568,12 @@ void vt100_process(const unsigned char *buffer, unsigned buffer_size) {
state = st_parm;
break;
}
if (c == ';') {
++parm_count;
parms[parm_count] = 0;
state = st_parm;
break;
}
/* fall through */
case st_lbracket2:
lbracket2:
@ -623,6 +649,39 @@ void vt100_process(const unsigned char *buffer, unsigned buffer_size) {
ShowCursor(__x, __y);
}
/* adb codes for extended keys. passed as-is with keypad bit set */
/* nb - kegs gobbles up fkeys for his own use */
enum {
kVK_F17 = 0x40,
kVK_VolumeUp = 0x48,
kVK_VolumeDown = 0x49,
kVK_Mute = 0x4A,
kVK_F18 = 0x4F,
kVK_F19 = 0x50,
kVK_F20 = 0x5A,
kVK_F5 = 0x60,
kVK_F6 = 0x61,
kVK_F7 = 0x62,
kVK_F3 = 0x63,
kVK_F8 = 0x64,
kVK_F9 = 0x65,
kVK_F11 = 0x67,
kVK_F13 = 0x69,
kVK_F16 = 0x6A,
kVK_F14 = 0x6B,
kVK_F10 = 0x6D,
kVK_F12 = 0x6F,
kVK_F15 = 0x71,
kVK_Help = 0x72,
kVK_Home = 0x73,
kVK_PageUp = 0x74,
kVK_ForwardDelete = 0x75,
kVK_F4 = 0x76,
kVK_End = 0x77,
kVK_F2 = 0x78,
kVK_PageDown = 0x79,
kVK_F1 = 0x7A
};
//
// remap the iigs key to a vt100 code (if necessary) and send it out.
@ -698,22 +757,22 @@ void vt100_event(EventRecord *event) {
break;
case 0x7a: // f1
case kVK_F1: // f1
if (DECANM) { cp = ESC "OP"; len = 3; }
else { cp = ESC "P"; len = 2; }
break;
case 0x78: // f2
case kVK_F2: // f2
if (DECANM) { cp = ESC "OQ"; len = 3; }
else { cp = ESC "Q"; len = 2; }
break;
case 0x63: // f3
case kVK_F3: // f3
if (DECANM) { cp = ESC "OR"; len = 3; }
else { cp = ESC "R"; len = 2; }
break;
case 0x76: // f4
case kVK_F4: // f4
if (DECANM) { cp = ESC "OS"; len = 3; }
else { cp = ESC "S"; len = 2; }
break;

11
vt100.gsh Normal file
View File

@ -0,0 +1,11 @@
#
#
# some settings so gsh works better with vt100.
# source vt100.gsh
#
set term=vt100
bindkey backward-delete-char "^H"
bindkey up-history "^[[A"
bindkey down-history "^[[B"
bindkey forward-char "^[[C"
bindkey backward-char "^[[D"

20
vt100.h Normal file
View File

@ -0,0 +1,20 @@
#ifndef vt100_h
#define vt100_h
enum {
vtDECCKM = 1 << 1, /* Cursor key */
vtDECANM = 1 << 2, /* ANSI/VT52 */
vtDECCOLM = 1 << 3, /* Column */
vtDECSCNM = 1 << 4, /* Screen */
vtDECOM = 1 << 6, /* Origin */
vtDECAWM = 1 << 7, /* Auto wrap */
vtDECKPAM = 1 << 8, /* Keypad Application Mode */
vtLNM = 1 << 9, /* Line Feed/New Line Mode */
vtDEFAULT = vtDECANM | vtDECAWM,
};
void vt100_init(unsigned flags);
extern void vt100_process(const unsigned char *buffer, unsigned buffer_size);
extern void vt100_event(struct EventRecord *event);
#endif