From 235be90c217a49b9f4897c56371180b55df20f02 Mon Sep 17 00:00:00 2001 From: David Goodwin Date: Sun, 30 Jun 2024 14:56:55 +1200 Subject: [PATCH 1/5] ADDS Regent 25 emulation An initial attempt at ADDS Regent 25 emulation based on documented behaviour. It seems to work OK against linux, but hasn't been compared to a real terminal yet so may have bugs/differences in behaviour that affect software written specifically for a Regent 25. --- README.md | 3 +- kermit/k95/ckoads.c | 501 ++++++++++++++++++++++++++++++++++++++++++ kermit/k95/ckoads.h | 10 + kermit/k95/ckoco3.c | 48 ++++ kermit/k95/ckocon.h | 1 + kermit/k95/ckoker.mak | 5 +- kermit/k95/ckokey.c | 71 ++++++ kermit/k95/ckuus5.c | 1 + kermit/k95/ckuus7.c | 2 + kermit/k95/ckuusr.h | 25 ++- 10 files changed, 663 insertions(+), 4 deletions(-) create mode 100644 kermit/k95/ckoads.c create mode 100644 kermit/k95/ckoads.h diff --git a/README.md b/README.md index e67d4f54..96fa8769 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ requirement: Supported Terminal Emulations ----------------------------- -ANSI-BBS; Avatar/0+; AT386; BeBox ANSI; Data General DASHER D200, D210; +ADDS Regent 25; ANSI-BBS; Avatar/0+; AT386; BeBox ANSI; Data General DASHER D200, D210; Data General DASHER D217 in native and Unix modes; DEC VT52; DEC VT100, VT102, VT220, VT320 with color extensions; Hazeltine 1500; Heath/Zenith 19; Hewlett Packard 2621A; HPTERM; IBM HFT and AIXTERM; IBM 3151; Linux console; @@ -137,6 +137,7 @@ Additionally, a number of new features have been added: * Support for 64bit Windows (x86-64, Itanium, ARM64, AXP64) * Ports to new CPU architectures: MIPS, Itanium, x86-64, ARM, ARM64 * A selection of other bugs fixed and other minor features added +* ADDS Regent 25 Emulation A full [Change Log](doc/changes.md) is available and updated for major releases. diff --git a/kermit/k95/ckoads.c b/kermit/k95/ckoads.c new file mode 100644 index 00000000..fb7842df --- /dev/null +++ b/kermit/k95/ckoads.c @@ -0,0 +1,501 @@ +/* C K O A D S . C -- ADDS Regent Emulation */ + +/* + Author: David Goodwin + + Copyright (C) 2024 David Goodwin + Copyright (C) 1985, 2004, Trustees of Columbia University in the City of New + York. +*/ + +/* + * Currently only the Regent 20 and Regent 25 are implemented. + * + * Stubs for the Regent 200 are present, but not yet implemented. Many of this + * terminals unique features (compared to the Regent 25) may be difficult to + * implement. WYSE terminal emulation has protected/unprotected fields, but + * I don't think Kermit 95 implements something like the Regent 200s Page Mode + * for any terminal type, or the ability to transmit a filled out form. + * + * If support for ADDS ViewPoint terminals is ever implemented, the Wyse WY-60 + * supports switching to an ADDS ViewPoint A2 and VP-60 emulation mode - see + * around line 4869 of ckowys.c + */ + + +#include "ckcdeb.h" +#ifndef NOTERM +#include "ckcker.h" /* For logchar, autodown, autoexitchk */ +#include "ckcasc.h" +#include "ckcuni.h" /* for utf8_to_ucs2 */ +#include "ckocon.h" /* For is_xprint, is_uprint, prtchar, wrtch, + * VscrnIsDirty, ES_GOTESC, VTERM, debugses, + * cursorleft*/ +#include "ckoads.h" +#ifdef NETCONN +#ifdef TCPSOCKET +#include "ckcnet.h" +extern int network, nettype, ttnproto, u_binary; +#endif /* TCPSOCKET */ +#endif /* NETCONN */ + +extern int tt_type, tt_type_mode, tt_status[VNUM]; +extern int keylock; +extern int printon, aprint, uprint, xprint, cprint, seslog ; +extern int escstate, debses; +extern int wherex[], wherey[]; +extern int ttpush; +int store_ctrl = FALSE; +extern bool crm; + +/* This is a direct copy from ckoadm.c, which is also identical to what's in + * ckohzl.c and probably a bunch of others. Probably should be refactored out + * to a common function */ +int +addsinc(void) { + extern int pmask, cmask; + extern int tt_utf8; + int ch; + + loop: + ch = ttinc(0); + if ( ch < 0 ) + return ch; + + if ( seslog ) + logchar(ch); + + /* Handle the UTF8 conversion if we are in that mode */ + if ( tt_utf8 ) { + USHORT * ucs2 = NULL; + int rc = utf8_to_ucs2( (CHAR)(ch & 0xFF), &ucs2 ); + if ( rc > 0 ) + goto loop; + else if ( rc < 0 ) + ch = 0xfffd; + else + ch = *ucs2; + } + + if ( !xprint ) { +#ifndef NOXFER + autodown(ch); +#endif /* NOXFER */ + autoexitchk(ch); + } + ch = ch & pmask & cmask; + debugses(ch); + if (printon && (is_xprint() || is_uprint())) + prtchar(ch); + return ch; +} + +void +addsctrl( int ch ) { + if ( !xprint ) { + switch (ch) { + case SOH: { /* Send cursor home */ + int h; + if (debses) + break; + + /* + * The manual says the home position varies depending on + * the auto-scroll switch setting. + * + * If auto-scroll is ON, the home position is the bottom + * left corner. + * + * If auto-scroll is OFF, the home position is the top + * left corner. + */ + + /* TODO: If autoscroll is off, go to top left: + * lgotoxy(VTERM,1,1); + */ + + /* If autoscroll is on, to to bottom left: */ + h = VscrnGetHeight(VTERM) - (tt_status[VTERM] ? 1 : 0); + + lgotoxy(VTERM, 1, h); + + break; + } + case STX: + if ( debses ) + break; + keylock = FALSE; + break; + + case ETX: + debug(F111, "ADDS Regent", "unused Ctrl", ch); + break; + + case EOT: + if ( debses ) + break; + + /* TODO: Regent 200 - The manual doesn't say EOT locks the + * keyboard - instead it uses EM. The Regent 200 might use EOT + * for something else, or not use it at all.*/ + + keylock = TRUE; + break; + + case ENQ: + debug(F111, "ADDS Regent", "unused Ctrl", ch); + break; + + case ACK: /* Cursor Right */ + if ( debses ) + break; + cursorright(0); /* TODO: Check this wraps to the beginning of the next line */ + break; + + case BEL: /* Terminal bell */ + if ( debses ) + break; + bleep(BP_BEL); + break; + + case BS: /* Cursor Left */ + if ( debses ) + break; + cursorleft(0); + break; + + case HT: + /* TODO: Regent 200: Tab + * Move to the first position in the next unprotected field */ + break; + + case LF: /* Cursor Down */ + if ( debses ) + break; + wrtch((CHAR)LF); + + /* TODO: if auto-scroll is off, send the cursor up to the top + * of the screen. + */ + + break; + + case VT: { /* Move cursor to vertical position */ + int line; + line = addsinc(); + if (debses) + break; + + line &= 0x1F; + + lgotoxy(VTERM, wherex[VTERM], line); + break; + } + case FF: /* Clear screen and home cursor */ + if ( debses ) + break; + clrscreen( VTERM, SP ) ; + lgotoxy(VTERM,1,1); /* and home the cursor */ + break; + + case CK_CR: + if ( debses ) + break; + wrtch((char) CK_CR); + break; + + case SO: + case SI: + debug(F111,"ADDS Regent","unused Ctrl",ch); + break; + + case DLE: { /* Move cursor to horizontal position */ + int col, group; + col = addsinc(); + if (debses) + break; + + /* Only care about the lower 7 bits */ + col &= 0x7F; + + /* The three most significant are a group number */ + group = col >> 4; + + /* And the remaining is the position in the group, BCD */ + col &= 0xF; + + if (col < 10) { + col += group * 10; + lgotoxy(VTERM, col, wherey[VTERM]); + } + break; + } + case DC1: + debug(F111,"ADDS Regent","unused Ctrl",ch); + break; + + case DC2: /* AUX port ON */ + debug(F110, "ADDS Regent", "AUX Port ON", NULL); + /* TODO: All incoming data until we see a DC4 should be sent to + * the printer (transparent print?) */ + break; + + case DC3: + debug(F111,"ADDS Regent","unused Ctrl",ch); + break; + + case DC4: /* AUX port OFF */ + debug(F110, "ADDS Regent", "AUX Port OFF", NULL); + /* TODO: The DC4 should be sent to the printer, then we should */ + break; + + case NAK: /* Cursor Back */ + if ( debses ) + break; + cursorleft(0); + + case SYN: + case ETB: + case CAN: + debug(F111,"ADDS Regent","unused Ctrl",ch); + break; + case ESC: + debug(F111,"ADDS Regent","ESC",ch); + if ( debses ) + break; + escstate = ES_GOTESC; + break; + + case XEM: + if (ISREGENT200(tt_type_mode)) { + if ( debses ) + break; + keylock = TRUE; + } + break; + + case SUB: /* Cursor Up */ + if ( debses ) + break; + cursorup(0); + break; + + case XFS: + case XGS: + case XRS: + case US: + default: + debug(F111,"ADDS Regent","unused Ctrl",ch); + } + } /* xprint */ + else { + switch ( ch ) { + case ESC: + debug(F111,"ADDS Regent","ESC",ch); + if ( debses ) + break; + escstate = ES_GOTESC ; + break; + default: + break; /* There are no other print commands */ + } + } +} + +void +addsascii( int ch ) { + if (printon && (is_xprint() || is_uprint())) { + /* + * TODO: We should probably try to avoid sending the ESC,4 (disable + * transparent print) to the printer somehow. + */ + prtchar(ch); + } + + if ( escstate == ES_GOTESC ) /* Process character as part of an escstate sequence */ + { + escstate = ES_ESCSEQ ; + if (!xprint) { + switch (ch) { + case 'G': + if (ISREGENT200(tt_type_mode)) { + /* TODO: Erase Variable + * replace all unprotected data on the screen with + * spaces, and homes the cursor + */ + } + break; + case 'K': /* Erase to end of current line */ + if (debses) + break; + + /* TODO: Regent 200: If in a formatted screen, erases to the + * end of the current field + */ + + clreol_escape(VTERM, SP); + break; + case 'k': /* Erase to the end of the screen */ + if (debses) + break; + clreoscr_escape(VTERM, SP); + break; + case 'R': + /* TODO: Regent 200 + * Switch to Form Generation Mode. + */ + break; + case 's': + /* TODO: Regent 200 + * Resets the terminal to Conversational Mode aborting any + * active buffered transmission or print local function and + * replies with a status message. The screen is not affected. + */ + break; + case 'X': + /* TODO: Regent 200 - Print Local + * Conversational, message and page modes + * print all variable and print-only data. Attributes and + * protected data are output as spaces. + */ + break; + case 'x': + /* TODO: Regent 200 - Print Local + * print all data, both protected and variable. In Forms mode, + * all data including attribute information is sent. + */ + break; + case 'Y': { + int col = 0, line = 0; + line = addsinc(); +#ifdef NETCONN +#ifdef TCPSOCKET + if ( network && IS_TELNET() && !TELOPT_U(TELOPT_BINARY) && col == CK_CR ) { + /* Handle TELNET CR-NUL or CR-LF if necessary */ + int dummy = ttinc(0); + debug(F111,"ADDS Regent 25","Addr cursor in page found CR",dummy); + if ( dummy != NUL ) + ttpush = dummy; + } +#endif /* TCPSOCKET */ +#endif /* NETCONN */ + col = addsinc(); + if (debses) + break; + + /* SP == 1, ! == 2, " == 3, etc */ + line -= US; + col -= US; + + debug(F111, "ADDS Regent 25", "Go to column", col); + debug(F111, "ADDS Regent 25", "Go to line", line); + + lgotoxy(VTERM, col, line); + + + break; + } + case 'Z': /* Store control character */ + if (debses) + break; + store_ctrl = TRUE; + crm = TRUE; + break; + case '0': + /* TODO: Regent 200 - Back Tab + * Move cursor to the first position of the previous unprotected + * field */ + break; + case '1': + /* TODO: Regent 200 - switch to line drawing character set + * Receiving any valid control code exits. + * See page 4-18 for the available symbols + */ + break; + case '2': + /* TODO: Regent 200 - exit line drawing character set + * This should be effectively a no-op as any control code + * should exit line drawing mode. + */ + break; + case '3': /* Enable print transparent */ + if (debses) + break; + xprint = TRUE; + if (!printon) + printeron(); + break; +#ifdef COMMENT + /* This is handled down the bottom of the function */ + case '4': /* Disable print transparent */ + if (debses) + break; + xprint = FALSE; + if (!cprint && !uprint && !xprint && !aprint && printon) + printeroff(); + break; +#endif /* COMMENT */ + case '5': /* Keyboard Lock */ + if (debses) + break; + keylock = TRUE; + break; + case '6': /* Keyboard unlock */ + if (debses) + break; + keylock = FALSE; + break; + case NUL: { + /* TODO: Regent 200 - Field Attribute follows + * (form generation mode only) + * One byte will follow indicating the field characteristic */ + int attr; + attr = addsinc(); + if (debses) + break; + /* TODO: apply the attribute */ + break; + } + case DC1: + /* TODO: Regent 200: Transmit */ + break; + case ENQ: + /* TODO: Regent 200: Transmit status + * Ctrl+X should also transmit it. + * Byte 10 is the data under the cursor - it should only + * be transmitted if send-data is enabled, otherwise it + * this field should be sent as SP. + * Auto-line-feed can come from the Kermit 95 setting. + * */ + break; + } + } + else { /* xprint */ + switch (ch) { + case '4': /* Disable print transparent */ + if (debses) + break; + xprint = FALSE; + if (!cprint && !uprint && !xprint && !aprint && printon) + printeroff(); + break; + } + } + escstate = ES_NORMAL ; + } + else { /* Handle as a normal character */ + if ( ch < SP && !store_ctrl) { + addsctrl(ch); + } else if ( !debses && ch != DEL && !xprint ) { + wrtch(ch); + + if (store_ctrl) { + crm = FALSE; + store_ctrl = FALSE; + } + } + } + VscrnIsDirty(VTERM) ; +} + +#endif /* NOTERM */ \ No newline at end of file diff --git a/kermit/k95/ckoads.h b/kermit/k95/ckoads.h new file mode 100644 index 00000000..111863dc --- /dev/null +++ b/kermit/k95/ckoads.h @@ -0,0 +1,10 @@ +/* C K O A D S . H -- Header for ADDS Emulation */ + +/* + Author: David Goodwin + + Copyright (C) 2024 David Goodwin +*/ +_PROTOTYP( void addsascii, ( int ) ) ; + + diff --git a/kermit/k95/ckoco3.c b/kermit/k95/ckoco3.c index d0f62816..e4e90c70 100644 --- a/kermit/k95/ckoco3.c +++ b/kermit/k95/ckoco3.c @@ -29,6 +29,7 @@ #include "ckoi31.h" #include "ckoqnx.h" #include "ckoadm.h" +#include "ckoads.h" #endif /* NOLOCAL */ #include /* Character types */ @@ -549,6 +550,7 @@ struct tt_info_rec tt_info[] = { /* Indexed by terminal type */ "ADM3A", {NULL}, "", /* LSI ADM 3A */ "ADM5", {NULL}, "", /* LSI ADM 5 */ "VTNT", {NULL}, "", /* Microsoft NT VT */ + "REGENT25",{NULL}, "", /* ADDS Regent 25 */ "IBM3101",{"I3101",NULL}, "" /* IBM 31xx */ }; int max_tt = TT_MAX; /* Highest terminal type */ @@ -4266,6 +4268,28 @@ clrbol_escape( BYTE vmode, CHAR fillchar ) { } } +/* Clear from current cursor position to end of line */ +void +clreol_escape( BYTE vmode, CHAR fillchar ) { + videoline * line = NULL ; + int x ; + unsigned char cellcolor = geterasecolor(vmode) ; + + if ( fillchar == NUL ) + fillchar = SP ; + if ( vmode == VTERM && decsasd == SASD_STATUS ) + vmode = VSTATUS ; + + /* take care of current line */ + line = VscrnGetLineFromTop(vmode,wherey[vmode]-1) ; + for ( x=wherex[vmode]-1 ; x < MAXTERMCOL ; x++ ) + { + line->cells[x].c = fillchar ; + line->cells[x].a = cellcolor; + line->vt_char_attrs[x] = VT_CHAR_ATTR_NORMAL ; + } +} + void clrline_escape( BYTE vmode, CHAR fillchar ) { videoline * line = NULL ; @@ -8770,6 +8794,8 @@ dokverb(int mode, int k) { /* 'k' is the kverbs[] table i if ( !kbdlocked() ) { if ( mode == VTERM || mode == VCMD && activecmd == XXOUT ) { + + /* Handle arrow keys */ if (k >= K_ARR_MIN && k <= K_ARR_MAX) { if ( ISDG200( tt_type_mode ) ) { /* Data General */ @@ -8923,6 +8949,23 @@ dokverb(int mode, int k) { /* 'k' is the kverbs[] table i break; } } + else if ( ISREGENT25( tt_type_mode ) ) { + /* ADDS Regent 25 */ + switch ( k ) { + case K_UPARR: + sendcharduplex(SUB,TRUE); + break; + case K_RTARR: + sendcharduplex(ACK,TRUE); + break; + case K_LFARR: + sendcharduplex(NAK,TRUE); + break; + case K_DNARR: + sendcharduplex(LF,TRUE); + break; + } + } else if ( ISWYSE( tt_type_mode ) ) { switch ( k ) { case K_UPARR: @@ -10731,6 +10774,11 @@ cwrite(unsigned short ch) { /* Used by ckcnet.c for */ return; } + if (ISREGENT25(tt_type_mode)) { + addsascii(ch); + return; + } + if ( ISVC(tt_type_mode) ) { vcascii(ch); diff --git a/kermit/k95/ckocon.h b/kermit/k95/ckocon.h index 4f4fa3a9..5697f0d0 100644 --- a/kermit/k95/ckocon.h +++ b/kermit/k95/ckocon.h @@ -511,6 +511,7 @@ _PROTOTYP(void clrtoeoln, (BYTE,CHAR)); _PROTOTYP(void clrbol_escape, (BYTE,CHAR)); _PROTOTYP(void clrbos_escape, (BYTE,CHAR)); _PROTOTYP(void clreoscr_escape, (BYTE,CHAR)); +_PROTOTYP(void clreol_escape, (BYTE,CHAR)); _PROTOTYP(void clrline_escape, (BYTE,CHAR)); _PROTOTYP(void clrcol_escape, (BYTE,CHAR)); _PROTOTYP(void clrrect_escape, (BYTE, int, int, int, int, CHAR)) ; diff --git a/kermit/k95/ckoker.mak b/kermit/k95/ckoker.mak index 849dfa9f..501b0b11 100644 --- a/kermit/k95/ckoker.mak +++ b/kermit/k95/ckoker.mak @@ -859,7 +859,7 @@ OBJS = ckcmai$(O) ckcfns$(O) ckcfn2$(O) ckcfn3$(O) ckcnet$(O) ckcpro$(O) \ ckonet$(O) \ ckoslp$(O) ckosyn$(O) ckothr$(O) ckotek$(O) ckotio$(O) ckowys$(O) \ ckodg$(O) ckoava$(O) ckoi31$(O) ckotvi$(O) ckovc$(O) \ - ckoadm$(O) ckohzl$(O) ckohp$(O) ckoqnx$(O) + ckoadm$(O) ckohzl$(O) ckohp$(O) ckoqnx$(O) ckoads$(O) !if "$(PLATFORM)" == "NT" OBJS = $(OBJS) cknnbi$(O) !else @@ -1254,7 +1254,7 @@ ckoco2$(O): ckoco2.c ckcker.h ckcdeb.h ckoker.h ckclib.h ckcasc.h ckoker.h c ckoco3$(O): ckoco3.c ckcker.h ckcdeb.h ckoker.h ckclib.h ckcasc.h ckoker.h ckocon.h \ ckokey.h ckokvb.h ckuusr.h ckowys.h ckodg.h ckoava.h ckoi31.h \ ckohp.h ckoadm.h ckohzl.h ckoqnx.h ckotvi.h ckovc.h ckcuni.h \ - ckcnet.h ckctel.h kui\ikui.h ckossh.h + ckcnet.h ckctel.h kui\ikui.h ckossh.h ckoads.h ckoco4$(O): ckoco4.c ckcdeb.h ckoker.h ckclib.h ckocon.h ckokey.h ckokvb.h ckuusr.h ckcasc.h \ ckokey.h ckokvb.h ckoco5$(O): ckoco5.c ckcdeb.h ckoker.h ckclib.h ckocon.h @@ -1268,6 +1268,7 @@ ckohzl$(O): ckohzl.c ckohzl.h ckcdeb.h ckoker.h ckclib.h ckcker.h ckcasc.h c ckcnet.h ckctel.h ckcuni.h ckoadm$(O): ckoadm.c ckoadm.h ckcdeb.h ckoker.h ckclib.h ckcker.h ckcasc.h ckocon.h ckuusr.h \ ckcnet.h ckctel.h ckcuni.h +ckoads$(O): ckoads.c ckoads.h ckcdeb.h ckcker.h ckcuni.h ckocon.h ckcnet.h ckcasc.h ckoi31$(O): ckoi31.c ckoi31.h ckcdeb.h ckoker.h ckclib.h ckcker.h ckcasc.h ckocon.h ckuusr.h ckcxla.h ckokey$(O): ckokey.c ckcdeb.h ckoker.h ckclib.h ckcasc.h ckcker.h ckuusr.h ckctel.h \ ckocon.h ckokey.h ckokvb.h ckcxla.h ckuxla.h ckcuni.h kui\ikui.h diff --git a/kermit/k95/ckokey.c b/kermit/k95/ckokey.c index 1e4f752d..6772bd66 100644 --- a/kermit/k95/ckokey.c +++ b/kermit/k95/ckokey.c @@ -7559,6 +7559,71 @@ defi31km( int tt ) return 0; } +/* ADDS Regent 20 */ +int +defregent20km( int tt ) { + if ( defbasekm(tt) || + /* Scan Kverb Regent Key PC Key PC Key Group */ + insertkeymap( tt, 269, mkkeyevt(CK_CR)) || /* NEW LINE Enter */ + insertkeymap( tt, 1293, mkkeyevt(LF)) || /* LINE FEED Ctrl+Enter */ + insertkeymap( tt, 4388, mkkeyevt(SOH)) || /* HOME Gray-Home */ + /*insertkeymap( tt, 4398, mkkeyevt(F_ESC | 'K')) ||*/ /* ERASE Gray-Delete */ + insertkeymap( tt, 5422, mkkeyevt(FF)) || /* Ctrl+ERASE Ctrl-Gray-Delete */ + insertkeymap( tt, 264, mkkeyevt(BS )) /* BACK SPACE Backspace */ + ) + return -1; + return 0; +} + +/* ADDS Regent 25 - like a Regent 20, but with arrow keys and a numeric key pad */ +int +defregent25km( int tt ) { + if ( defregent20km(tt) || + /* Scan Kverb Regent Key PC Key PC Key Group */ + + /* + Cursor keys + */ + insertkeymap( tt, 4390, mkkeyevt(F_KVERB | K_UPARR )) || /* Up Arrow Up Arrow Cursor keypad */ + insertkeymap( tt, 4392, mkkeyevt(F_KVERB | K_DNARR )) || /* Down Arrow Down Arrow Cursor keypad */ + insertkeymap( tt, 4391, mkkeyevt(F_KVERB | K_RTARR )) || /* Right Arrow Right Arrow Cursor keypad */ + insertkeymap( tt, 4389, mkkeyevt(F_KVERB | K_LFARR )) || /* Left Arrow Left Arrow Cursor keypad */ + + insertkeymap( tt, 4365, mkkeyevt(CK_CR)) /* KP Enter */ + ) + return -1; + return 0; +} + +int +defregent200km( int tt ) { + if ( defregent25km(tt) || + /* Scan Kverb Regent Key PC Key PC Key Group */ + + /* + Function Keys + */ + insertkeymap( tt, 368, mkliteralevt("\0021")) || /* F1 F1 Top F keys */ + insertkeymap( tt, 369, mkliteralevt("\0022")) || /* F2 F2 Top F keys */ + insertkeymap( tt, 370, mkliteralevt("\0023")) || /* F3 F3 Top F keys */ + insertkeymap( tt, 371, mkliteralevt("\0024")) || /* F4 F4 Top F keys */ + insertkeymap( tt, 372, mkliteralevt("\0025")) || /* F5 F5 Top F keys */ + insertkeymap( tt, 373, mkliteralevt("\0026")) || /* F6 F6 Top F keys */ + insertkeymap( tt, 374, mkliteralevt("\0027")) || /* F7 F7 Top F keys */ + insertkeymap( tt, 375, mkliteralevt("\0028")) || /* F8 F8 Top F keys */ + insertkeymap( tt, 880, mkliteralevt("\002!")) || /* SHIFT+F1 SHIFT+F1 Top F keys */ + insertkeymap( tt, 881, mkliteralevt("\002\"")) || /* SHIFT+F2 SHIFT+F2 Top F keys */ + insertkeymap( tt, 882, mkliteralevt("\002#")) || /* SHIFT+F3 SHIFT+F3 Top F keys */ + insertkeymap( tt, 883, mkliteralevt("\002$")) || /* SHIFT+F4 SHIFT+F4 Top F keys */ + insertkeymap( tt, 884, mkliteralevt("\002%")) || /* SHIFT+F5 SHIFT+F5 Top F keys */ + insertkeymap( tt, 885, mkliteralevt("\002&")) || /* SHIFT+F6 SHIFT+F6 Top F keys */ + insertkeymap( tt, 886, mkliteralevt("\002'")) || /* SHIFT+F7 SHIFT+F7 Top F keys */ + insertkeymap( tt, 887, mkliteralevt("\002(")) /* SHIFT+F8 SHIFT+F8 Top F keys */ + ) + return -1; + return 0; +} + int insertkmtolist( struct keynode ** plist, int key, con_event def ) { @@ -7723,6 +7788,12 @@ defaultkeymap( int terminal ) { return defqnxkm(terminal); case TT_IBM31: return defi31km(terminal); + case TT_REGENT20: + return defregent20km(terminal); + case TT_REGENT25: + return defregent25km(terminal); + case TT_REGENT200: + return defregent200km(terminal); case TT_NONE: default: return defbasekm(terminal); diff --git a/kermit/k95/ckuus5.c b/kermit/k95/ckuus5.c index d5b785cf..6a888bf3 100644 --- a/kermit/k95/ckuus5.c +++ b/kermit/k95/ckuus5.c @@ -5353,6 +5353,7 @@ struct keytab shokeymtab[] = { "linux", TT_LINUX, 0, /* Linux */ "qansi", TT_QANSI, 0, /* QNX ANSI */ "qnx", TT_QNX, 0, /* QNX */ + "regent25", TT_REGENT25,0, /* ADDS Regent 25 */ "russian", TT_KBM_RUSSIAN, 0, /* Russian mode */ "scoansi", TT_SCOANSI, 0, /* SCO ANSI */ "sni-97801", TT_97801, 0, /* Sinix 97801 */ diff --git a/kermit/k95/ckuus7.c b/kermit/k95/ckuus7.c index 0083fa2c..02647879 100644 --- a/kermit/k95/ckuus7.c +++ b/kermit/k95/ckuus7.c @@ -1561,6 +1561,7 @@ struct keytab ttyptab[] = { { "linux", TT_LINUX, 0 }, /* Linux */ { "qansi", TT_QANSI, 0 }, /* QNX ANSI */ { "qnx", TT_QNX, 0 }, /* QNX Console */ + { "regent25", TT_REGENT25,0 }, /* ADDS Regent 25 */ { "scoansi", TT_SCOANSI, 0 }, /* SCO ANSI */ { "sni-97801",TT_97801, 0 }, /* SNI 97801 */ { "sun", TT_SUN, 0 }, /* SUN Console */ @@ -1651,6 +1652,7 @@ struct keytab ttkeytab[] = { { "linux", TT_LINUX, 0 }, /* Linux */ { "qansi", TT_QANSI, 0 }, /* QNX ANSI */ { "qnx", TT_QNX, 0 }, /* QNX */ + { "regent25", TT_REGENT25, 0 }, /* ADDS Regent 25 */ { "russian", TT_KBM_RUSSIAN,0 }, /* Russian mode */ { "scoansi", TT_SCOANSI, 0 }, /* SCO ANSI */ { "sni-97801", TT_97801, 0 }, /* SNI 97801 */ diff --git a/kermit/k95/ckuusr.h b/kermit/k95/ckuusr.h index d3f90f0a..6f712168 100644 --- a/kermit/k95/ckuusr.h +++ b/kermit/k95/ckuusr.h @@ -1062,11 +1062,21 @@ struct stringint { /* String and (wide) integer */ #define TT_ADM3A 39 /* LSI ADM 3A */ #define TT_ADM5 40 /* LSI ADM 5 */ #define TT_VTNT 41 /* Microsoft NT Virtual Terminal */ -#define TT_MAX TT_VTNT +#define TT_REGENT25 42 /* ADDS Regent 25 */ +#define TT_MAX TT_REGENT25 #define TT_VT420 96 /* DEC VT-420 */ #define TT_VT520 97 /* DEC VT-520/525 */ #define TT_XTERM 98 /* XTerm */ #define TT_TEK40 99 /* Tektronix 401x */ + +/* Other ADDS Regent terminals - not currently emulated */ +#define TT_REGENT20 100 /* ADDS Regent 20 */ +#define TT_REGENT40 101 /* ADDS Regent 40 */ +#define TT_REGENT40P 102 /* ADDS Regent 40+ */ +#define TT_REGENT60 103 /* ADDS Regent 60 */ +#define TT_REGENT100 104 /* ADDS Regent 100 */ +#define TT_REGENT200 105 /* ADDS Regent 200 */ + #define TT_KBM_EMACS TT_MAX+1 #define TT_KBM_HEBREW TT_MAX+2 #define TT_KBM_RUSSIAN TT_MAX+3 @@ -1126,6 +1136,19 @@ struct stringint { /* String and (wide) integer */ #define ISVTNT(x) (x == TT_VTNT) #define ISADM3A(x) (x == TT_ADM3A) #define ISADM5(x) (x == TT_ADM5) +/* ADDS Regent Terminals */ +#define ISREGENT20(x) (x == TT_REGENT20) +#define ISREGENT25(x) (x == TT_REGENT25 || x == TT_REGENT20) +#define ISREGENT40(x) (x == TT_REGENT40 || x == TT_REGENT25 \ + || x == TT_REGENT20) +#define ISREGENT40P(x) (x == TT_REGENT40P || x == TT_REGENT40 \ + || x == TT_REGENT25 || x == TT_REGENT20) +#define ISREGENT60(x) (x == TT_REGENT60 || x == TT_REGENT40P \ + || x == TT_REGENT40 || x == TT_REGENT25 \ + || x == TT_REGENT20) +#define ISREGENT200(x) (x == TT_REGENT60 || x == TT_REGENT40P \ + || x == TT_REGENT40 || x == TT_REGENT25 \ + || x == TT_REGENT20 || x == TT_REGENT200) #define ISXTERM(x) (x == TT_XTERM) #endif /* OS2 */ From d37ef5cc60e26f7538a4dfde25cd48096504e83c Mon Sep 17 00:00:00 2001 From: David Goodwin Date: Sun, 30 Jun 2024 15:08:27 +1200 Subject: [PATCH 2/5] Fix OS/2 build error by directly including ckuusr.h --- kermit/k95/ckoads.c | 1 + kermit/k95/ckoker.mak | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/kermit/k95/ckoads.c b/kermit/k95/ckoads.c index fb7842df..a4c30d2d 100644 --- a/kermit/k95/ckoads.c +++ b/kermit/k95/ckoads.c @@ -31,6 +31,7 @@ #include "ckocon.h" /* For is_xprint, is_uprint, prtchar, wrtch, * VscrnIsDirty, ES_GOTESC, VTERM, debugses, * cursorleft*/ +#include "ckuusr.h" #include "ckoads.h" #ifdef NETCONN #ifdef TCPSOCKET diff --git a/kermit/k95/ckoker.mak b/kermit/k95/ckoker.mak index 501b0b11..d03559d5 100644 --- a/kermit/k95/ckoker.mak +++ b/kermit/k95/ckoker.mak @@ -1268,7 +1268,7 @@ ckohzl$(O): ckohzl.c ckohzl.h ckcdeb.h ckoker.h ckclib.h ckcker.h ckcasc.h c ckcnet.h ckctel.h ckcuni.h ckoadm$(O): ckoadm.c ckoadm.h ckcdeb.h ckoker.h ckclib.h ckcker.h ckcasc.h ckocon.h ckuusr.h \ ckcnet.h ckctel.h ckcuni.h -ckoads$(O): ckoads.c ckoads.h ckcdeb.h ckcker.h ckcuni.h ckocon.h ckcnet.h ckcasc.h +ckoads$(O): ckoads.c ckoads.h ckcdeb.h ckcker.h ckcuni.h ckocon.h ckcnet.h ckcasc.h ckuusr.h ckoi31$(O): ckoi31.c ckoi31.h ckcdeb.h ckoker.h ckclib.h ckcker.h ckcasc.h ckocon.h ckuusr.h ckcxla.h ckokey$(O): ckokey.c ckcdeb.h ckoker.h ckclib.h ckcasc.h ckcker.h ckuusr.h ckctel.h \ ckocon.h ckokey.h ckokvb.h ckcxla.h ckuxla.h ckcuni.h kui\ikui.h From 41be737c1c63f6692d6b8bd1b308ce250ee5312d Mon Sep 17 00:00:00 2001 From: David Goodwin Date: Sun, 30 Jun 2024 15:10:46 +1200 Subject: [PATCH 3/5] Fix GCC build Forgot to update the GCC makefile! --- kermit/k95/Makefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/kermit/k95/Makefile b/kermit/k95/Makefile index 9d79d76a..feec965a 100644 --- a/kermit/k95/Makefile +++ b/kermit/k95/Makefile @@ -141,7 +141,8 @@ OBJS = $(OUTDIR)/ckcmai$(O) $(OUTDIR)/ckcfns$(O) $(OUTDIR)/ckcfn2$(O) \ $(OUTDIR)/ckohzl$(O) $(OUTDIR)/ckohp$(O) $(OUTDIR)/ckoqnx$(O) \ $(OUTDIR)/cknnbi$(O) $(OUTDIR)/ckop$(O) $(OUTDIR)/p_callbk$(O) \ $(OUTDIR)/p_global$(O) $(OUTDIR)/p_omalloc$(O) $(OUTDIR)/p_error$(O) \ - $(OUTDIR)/p_common$(O) $(OUTDIR)/p_tl$(O) $(OUTDIR)/p_dir$(O) + $(OUTDIR)/p_common$(O) $(OUTDIR)/p_tl$(O) $(OUTDIR)/p_dir$(O) \ + $(OUTDIR)/ckoads$(O) # For SSH-enabled builds #OBJS = $(OBJS) ckossh$(O) ckorbf$(O) ckoshs$(O) @@ -416,6 +417,8 @@ $(OUTDIR)/ckovc$(O): ckovc.c ckovc.h ckcdeb.h ckoker.h ckclib.h ckcker.h \ ckcasc.h ckocon.h ckuusr.h $(OUTDIR)/ckoadm$(O): ckoadm.c ckoadm.h ckcdeb.h ckoker.h ckclib.h ckcker.h \ ckcasc.h ckocon.h ckuusr.h ckcnet.h ckctel.h ckcuni.h +$(OUTDIR)/ckoads$(O): ckoads.c ckoads.h ckcdeb.h ckcker.h ckcuni.h ckocon.h \ + ckcnet.h ckcasc.h ckuusr.h $(OUTDIR)/ckohzl$(O): ckohzl.c ckohzl.h ckcdeb.h ckoker.h ckclib.h ckcker.h \ ckcasc.h ckocon.h ckuusr.h ckcnet.h ckctel.h ckcuni.h $(OUTDIR)/ckohp$(O): ckohp.c ckohp.h ckcdeb.h ckoker.h ckclib.h ckcker.h \ From b674ce435c6a1b7ad3021ded81a6deb700056fd5 Mon Sep 17 00:00:00 2001 From: David Goodwin Date: Tue, 2 Jul 2024 22:22:47 +1200 Subject: [PATCH 4/5] Autoscroll option --- kermit/k95/ckoads.c | 22 ++++++++-------------- kermit/k95/ckoco3.c | 10 ++++++---- kermit/k95/ckuus2.c | 7 +++++-- 3 files changed, 19 insertions(+), 20 deletions(-) diff --git a/kermit/k95/ckoads.c b/kermit/k95/ckoads.c index a4c30d2d..d3df0e0b 100644 --- a/kermit/k95/ckoads.c +++ b/kermit/k95/ckoads.c @@ -46,6 +46,7 @@ extern int printon, aprint, uprint, xprint, cprint, seslog ; extern int escstate, debses; extern int wherex[], wherey[]; extern int ttpush; +extern int autoscroll; int store_ctrl = FALSE; extern bool crm; @@ -111,15 +112,12 @@ addsctrl( int ch ) { * left corner. */ - /* TODO: If autoscroll is off, go to top left: - * lgotoxy(VTERM,1,1); - */ - - /* If autoscroll is on, to to bottom left: */ - h = VscrnGetHeight(VTERM) - (tt_status[VTERM] ? 1 : 0); - - lgotoxy(VTERM, 1, h); - + if (autoscroll) { + h = VscrnGetHeight(VTERM) - (tt_status[VTERM] ? 1 : 0); + lgotoxy(VTERM, 1, h); + } else { + lgotoxy(VTERM,1,1); + } break; } case STX: @@ -173,11 +171,7 @@ addsctrl( int ch ) { case LF: /* Cursor Down */ if ( debses ) break; - wrtch((CHAR)LF); - - /* TODO: if auto-scroll is off, send the cursor up to the top - * of the screen. - */ + cursordown(0); break; diff --git a/kermit/k95/ckoco3.c b/kermit/k95/ckoco3.c index e4e90c70..84f0a847 100644 --- a/kermit/k95/ckoco3.c +++ b/kermit/k95/ckoco3.c @@ -3756,16 +3756,18 @@ cursordown(int wrap) { ((ISWYSE(tt_type_mode) || ISTVI(tt_type_mode) || ISHZL(tt_type_mode) || - ISDG200(tt_type_mode)) && - !autoscroll || protect || wy_autopage) ) + ISDG200(tt_type_mode) || + ISREGENT25(tt_type_mode)) && + !autoscroll || protect || wy_autopage)) { if ( printon && is_aprint() ) { prtline( wherey[VTERM], LF ) ; } lgotoxy(VTERM, wherex[VTERM], (relcursor ? margintop : 1)); - } else if ( (ISWYSE(tt_type_mode) || ISTVI(tt_type_mode)) && - autoscroll && !protect) + } else if ( (ISWYSE(tt_type_mode) || ISTVI(tt_type_mode) || ISREGENT25(tt_type_mode)) && + autoscroll && !protect) { wrtch(LF); + } } if ( wrapit ) wrapit = FALSE; diff --git a/kermit/k95/ckuus2.c b/kermit/k95/ckuus2.c index d63ae428..a1d918b3 100644 --- a/kermit/k95/ckuus2.c +++ b/kermit/k95/ckuus2.c @@ -8212,11 +8212,14 @@ static char *hxyterm[] = { " For Wyse and Televideo terminals, Autopage mode causes the cursor to move", " to the top of the next page of terminal memory when it scrolls off the ", " bottom of the current page. In K95, it moves the cursor to the top line ", -" from the bottom since K95 only supports a single page of terminal memory", +" from the bottom since K95 only supports a single page of terminal memory.", " ", "SET TERMINAL AUTOSCROLL { ON, OFF }", " Autoscroll mode is used on Televideo terminals when the size of a page of", -" terminal memory is larger than the view screen.", +" terminal memory is larger than the view screen. On ADDS Regent terminals,", +" when autoscroll is off anything that causes the cursor to move down from ", +" the bottom line of the screen will cause the cursor to wrap around to the", +" top of the screen.", " ", #else /* OS2 */ "SET TERMINAL AUTODOWNLOAD { ON, OFF, ERROR { STOP, CONTINUE } }", From b0580a6878798b0d1d438f4b12b9a8b02489da55 Mon Sep 17 00:00:00 2001 From: David Goodwin Date: Thu, 4 Jul 2024 07:56:01 +1200 Subject: [PATCH 5/5] Give the default key map the Regent 40/60/100/200 function keys --- kermit/k95/ckokey.c | 62 ++++++++++++++++++++++++++++++++------------- 1 file changed, 45 insertions(+), 17 deletions(-) diff --git a/kermit/k95/ckokey.c b/kermit/k95/ckokey.c index 6772bd66..f50538f2 100644 --- a/kermit/k95/ckokey.c +++ b/kermit/k95/ckokey.c @@ -7589,7 +7589,34 @@ defregent25km( int tt ) { insertkeymap( tt, 4391, mkkeyevt(F_KVERB | K_RTARR )) || /* Right Arrow Right Arrow Cursor keypad */ insertkeymap( tt, 4389, mkkeyevt(F_KVERB | K_LFARR )) || /* Left Arrow Left Arrow Cursor keypad */ - insertkeymap( tt, 4365, mkkeyevt(CK_CR)) /* KP Enter */ + insertkeymap( tt, 4365, mkkeyevt(CK_CR)) || /* KP Enter */ + + /* + Function Keys + TEMPORARY: The Regent 25 does not have function keys, but the + Regent 40, 60, 100 and 200 all do. These terminals all understand + the same subset of escape sequences with the main enhancements in + the higher end models being text attributes (underline, reverse video, etc) + and forms. So by giving the Regent 25 the function keys it may + make it a good enough subsititute for a Regent 40/60/100/200. + */ + /* TODO: Support alternate EOL sequences (CR ETX, CR EOT) after STX n */ + insertkeymap( tt, 368, mkliteralevt("\0021\x0D")) || /* F1 F1 Top F keys */ + insertkeymap( tt, 369, mkliteralevt("\0022\x0D")) || /* F2 F2 Top F keys */ + insertkeymap( tt, 370, mkliteralevt("\0023\x0D")) || /* F3 F3 Top F keys */ + insertkeymap( tt, 371, mkliteralevt("\0024\x0D")) || /* F4 F4 Top F keys */ + insertkeymap( tt, 372, mkliteralevt("\0025\x0D")) || /* F5 F5 Top F keys */ + insertkeymap( tt, 373, mkliteralevt("\0026\x0D")) || /* F6 F6 Top F keys */ + insertkeymap( tt, 374, mkliteralevt("\0027\x0D")) || /* F7 F7 Top F keys */ + insertkeymap( tt, 375, mkliteralevt("\0028\x0D")) || /* F8 F8 Top F keys */ + insertkeymap( tt, 880, mkliteralevt("\002!\x0D")) || /* SHIFT+F1 SHIFT+F1 Top F keys */ + insertkeymap( tt, 881, mkliteralevt("\002\"\x0D"))|| /* SHIFT+F2 SHIFT+F2 Top F keys */ + insertkeymap( tt, 882, mkliteralevt("\002#\x0D")) || /* SHIFT+F3 SHIFT+F3 Top F keys */ + insertkeymap( tt, 883, mkliteralevt("\002$\x0D")) || /* SHIFT+F4 SHIFT+F4 Top F keys */ + insertkeymap( tt, 884, mkliteralevt("\002%\x0D")) || /* SHIFT+F5 SHIFT+F5 Top F keys */ + insertkeymap( tt, 885, mkliteralevt("\002&\x0D")) || /* SHIFT+F6 SHIFT+F6 Top F keys */ + insertkeymap( tt, 886, mkliteralevt("\002'\x0D")) || /* SHIFT+F7 SHIFT+F7 Top F keys */ + insertkeymap( tt, 887, mkliteralevt("\002(\x0D")) /* SHIFT+F8 SHIFT+F8 Top F keys */ ) return -1; return 0; @@ -7603,22 +7630,23 @@ defregent200km( int tt ) { /* Function Keys */ - insertkeymap( tt, 368, mkliteralevt("\0021")) || /* F1 F1 Top F keys */ - insertkeymap( tt, 369, mkliteralevt("\0022")) || /* F2 F2 Top F keys */ - insertkeymap( tt, 370, mkliteralevt("\0023")) || /* F3 F3 Top F keys */ - insertkeymap( tt, 371, mkliteralevt("\0024")) || /* F4 F4 Top F keys */ - insertkeymap( tt, 372, mkliteralevt("\0025")) || /* F5 F5 Top F keys */ - insertkeymap( tt, 373, mkliteralevt("\0026")) || /* F6 F6 Top F keys */ - insertkeymap( tt, 374, mkliteralevt("\0027")) || /* F7 F7 Top F keys */ - insertkeymap( tt, 375, mkliteralevt("\0028")) || /* F8 F8 Top F keys */ - insertkeymap( tt, 880, mkliteralevt("\002!")) || /* SHIFT+F1 SHIFT+F1 Top F keys */ - insertkeymap( tt, 881, mkliteralevt("\002\"")) || /* SHIFT+F2 SHIFT+F2 Top F keys */ - insertkeymap( tt, 882, mkliteralevt("\002#")) || /* SHIFT+F3 SHIFT+F3 Top F keys */ - insertkeymap( tt, 883, mkliteralevt("\002$")) || /* SHIFT+F4 SHIFT+F4 Top F keys */ - insertkeymap( tt, 884, mkliteralevt("\002%")) || /* SHIFT+F5 SHIFT+F5 Top F keys */ - insertkeymap( tt, 885, mkliteralevt("\002&")) || /* SHIFT+F6 SHIFT+F6 Top F keys */ - insertkeymap( tt, 886, mkliteralevt("\002'")) || /* SHIFT+F7 SHIFT+F7 Top F keys */ - insertkeymap( tt, 887, mkliteralevt("\002(")) /* SHIFT+F8 SHIFT+F8 Top F keys */ + /* TODO: Support alternate EOL sequences (CR ETX, CR EOT) after STX n */ + insertkeymap( tt, 368, mkliteralevt("\0021\x0D")) || /* F1 F1 Top F keys */ + insertkeymap( tt, 369, mkliteralevt("\0022\x0D")) || /* F2 F2 Top F keys */ + insertkeymap( tt, 370, mkliteralevt("\0023\x0D")) || /* F3 F3 Top F keys */ + insertkeymap( tt, 371, mkliteralevt("\0024\x0D")) || /* F4 F4 Top F keys */ + insertkeymap( tt, 372, mkliteralevt("\0025\x0D")) || /* F5 F5 Top F keys */ + insertkeymap( tt, 373, mkliteralevt("\0026\x0D")) || /* F6 F6 Top F keys */ + insertkeymap( tt, 374, mkliteralevt("\0027\x0D")) || /* F7 F7 Top F keys */ + insertkeymap( tt, 375, mkliteralevt("\0028\x0D")) || /* F8 F8 Top F keys */ + insertkeymap( tt, 880, mkliteralevt("\002!\x0D")) || /* SHIFT+F1 SHIFT+F1 Top F keys */ + insertkeymap( tt, 881, mkliteralevt("\002\"\x0D"))|| /* SHIFT+F2 SHIFT+F2 Top F keys */ + insertkeymap( tt, 882, mkliteralevt("\002#\x0D")) || /* SHIFT+F3 SHIFT+F3 Top F keys */ + insertkeymap( tt, 883, mkliteralevt("\002$\x0D")) || /* SHIFT+F4 SHIFT+F4 Top F keys */ + insertkeymap( tt, 884, mkliteralevt("\002%\x0D")) || /* SHIFT+F5 SHIFT+F5 Top F keys */ + insertkeymap( tt, 885, mkliteralevt("\002&\x0D")) || /* SHIFT+F6 SHIFT+F6 Top F keys */ + insertkeymap( tt, 886, mkliteralevt("\002'\x0D")) || /* SHIFT+F7 SHIFT+F7 Top F keys */ + insertkeymap( tt, 887, mkliteralevt("\002(\x0D")) /* SHIFT+F8 SHIFT+F8 Top F keys */ ) return -1; return 0;