home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Columbia Kermit
/
kermit.zip
/
old
/
ckermit5a190
/
ckocon.c
< prev
next >
Wrap
C/C++ Source or Header
|
2020-01-01
|
175KB
|
5,792 lines
char *connv = "OS/2 CONNECT command 5A(155), 4 Oct 94";
/* C K O C O N -- Kermit connect command for OS/2 systems */
/*
Author: Frank da Cruz (fdc@columbia.edu, FDCCU@CUVMA.BITNET),
Columbia University Academic Information Systems, New York City.
Copyright (C) 1985, 1994, Trustees of Columbia University in the City of New
York. The C-Kermit software may not be, in whole or in part, licensed or
sold for profit as a software product itself, nor may it be included in or
distributed with commercial products or otherwise distributed by commercial
concerns to their clients or customers without written permission of the
Office of Kermit Development and Distribution, Columbia University. This
copyright notice must not be removed, altered, or obscured.
Originally adapted to OS/2 by Chris Adie of Edinburgh University, Scotland
(C.Adie@edinburgh.ac.uk), 1988, from UNIX C-Kermit CONNECT module by Frank
da Cruz, Columbia University. VT102 terminal emulation originally by Chris
Adie, 1988 ("If the code looks a bit funny sometimes, it's because it was
machine translated to C.")
Adapted to C-Kermit 5A by Kai Uwe Rommel (rommel@informatik.tu-muenchen.de),
1992-93 (present address: rommel@ars.muc.de).
Many changes by Frank da Cruz (fdc@columbia.edu): numerous bug fixes (tabs,
cursor/attributes save/restore, scrolling, keypad modes, etc), new SET
TERMINAL commands, TCP/IP TELNET support, printer support, character-set
support, APC escape sequence handling, print/dump screen, complete rewrite
of character attribute handling & screen reversal and rollback, addition of
VT220 and ANSI emulations, keyboard verbs, Compose key, Hebrew features,
context-sensitive popup screens, cosmetic improvements, commentary, etc:
1992-present. (Hopefully much of the funny-looking code looks less
funny now.)
Additional code by Jeffrey Altman ( p00118@psilink.com ):
changes to keyboard handling, mouse support, ...: 1993 to present.
*/
/*
* =============================#includes=====================================
*/
#include "ckcdeb.h" /* Typedefs, debug formats, etc */
#include "ckcker.h" /* Kermit definitions */
#include "ckcasc.h" /* ASCII character symbols */
#include "ckcxla.h" /* Character set translation */
#include "ckcnet.h" /* Network support */
#include "ckuusr.h" /* For terminal type definitions, etc. */
#include "ckocon.h" /* Keyboard verb definitions */
#include <ctype.h> /* Character types */
#include <io.h> /* File io function declarations */
#include <process.h> /* Process-control function declarations */
#include <stdlib.h> /* Standard library declarations */
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#ifndef __32BIT__
#define far _far
#define near _near
#define pascal _pascal
#endif /* __32BIT__ */
#ifdef OS2MOUSE
#define INCL_MOU
#endif /* OS2MOUSE */
#define INCL_NOPM
#define INCL_VIO
#define INCL_ERRORS
#define INCL_DOSPROCESS
#define INCL_DOSSEMAPHORES
#define INCL_DOSDEVIOCTL
#define INCL_WINCLIPBOARD
#include <os2.h>
#undef COMMENT /* COMMENT is defined in os2.h */
#ifdef CK_NETBIOS
#include "ckonbi.h"
extern UCHAR NetBiosRemote[] ;
#endif /* CK_NETBIOS */
#ifndef min
#define min(a,b) ((a) <= (b) ? (a) : (b))
#endif /* min */
#define MAXCOL 132 /* Maximum screen columns */
#define MAXROW 255 /* Maximum screen rows */
/*
* =============================#defines======================================
*/
#ifdef TRUE
#undef TRUE
#endif /* TRUE */
#define TRUE 1
#ifdef FALSE
#undef FALSE
#endif /* FALSE */
#define FALSE 0
#define UPWARD 6 /* Scroll up */
#define DOWNWARD 7 /* Scroll down */
#define LBUFSIZE roll.bufsize /* Maximum lines in rollback buffer */
/*
*
* =============================typedefs======================================
*/
typedef int bool;
typedef struct ascreen_rec { /* Structure for saving screen info */
unsigned char ox;
unsigned char oy;
unsigned char att;
char *scrncpy;
} ascreen;
/* Key names */
static char *keynam[512]; /* Names of keys, by scan code */
static struct vik_rec { /* Very Important Keys - */
KEY help; /* We look these up once */
KEY exit; /* and remember where they are... */
KEY upscn;
KEY dnscn;
KEY upone;
KEY dnone;
KEY homscn;
KEY endscn;
KEY hangup;
KEY xbreak;
KEY lbreak;
KEY dump;
KEY prtscn;
KEY os2;
KEY printff;
KEY flipscn;
KEY debug;
KEY reset;
KEY compose;
} vik;
/*
*
* =============================externals=====================================
*/
extern CHAR (*xls[MAXTCSETS+1][MAXFCSETS+1])(CHAR); /* Character set xlate */
extern CHAR (*xlr[MAXTCSETS+1][MAXFCSETS+1])(CHAR); /* functions. */
extern int language; /* Current language. */
extern struct langinfo langs[]; /* Language info. */
extern struct csinfo fcsinfo[]; /* File character set info */
extern int tcsr, tcsl; /* Terminal character sets, remote & local. */
extern int tnlm, tn_nlm; /* Terminal newline mode, ditto for TELNET */
extern int tt_crd; /* Carriage-return display mode */
extern int tt_bell; /* How to handle incoming Ctrl-G characters */
extern long speed, vernum;
extern int local, escape, duplex, parity, flow, seslog, sessft,
cmdmsk, cmask, sosi, xitsta, debses, mdmtyp, carrier, what;
extern int cflg, cnflg, stayflg;
extern int network, nettype, ttnproto;
#ifndef NOSPL
extern struct mtab *mactab; /* Main macro table */
extern int nmac; /* Number of macros */
#endif /* NOSPL */
extern KEY *keymap;
extern MACRO *macrotab;
extern char ttname[], sesfil[];
extern void cc_trap();
extern char *printfile;
#ifdef __32BIT__
extern HMTX hmtxScreenSem ;
extern HMUX hmuxKeyStroke ;
#endif /* __32BIT__ */
#ifdef OS2MOUSE
extern HMTX hmtxMouseSem ;
extern HMOU hMouse ;
#endif /* OS2MOUSE */
/*
* =============================variables==============================
*/
/*
These are RGB bits for the fore- and background colors in the PC's video
adapter, 3 bits for each color. These default values can be changed by the
SET TERMINAL COLOR command (in ckuus7.c) or by CSI3x;4xm escape sequences
from the host.
*/
#ifdef MONO
int colornormal = 0x07;
int colorunderline = 0x01;
int colorreverse = 0x70;
int colorstatus = 0x70;
int colorhelp = 0x70;
#else
int colornormal = 0x30;
int colorunderline = 0x3E;
int colorreverse = 0x70;
int colorstatus = 0x74;
int colorhelp = 0x27;
#endif /* MONO */
int colorborder = 0x00;
int colorcmd;
int scrninitialised = 0;
/*
The video adapter stores each screen character in a two-byte cell. The
first byte of each cell contains the 8-bit character value. The second byte
contains the video attributes for the character, and looks like this:
Background Foreground
Color Color
+---+---+---+---+---+---+---+---+
| b | R | G | B | i | R | G | B |
+---+---+---+---+---+---+---+---+
b = blink i = intensity
0 = nonblinking 0 = normal
1 = blinking 1 = high
The i bit applies to the foreground color. The meaning of the b bit depends
on the VIO state; it can mean (a) the foreground character blinks, or (b) the
background color is high-intensity. C-Kermit uses (b) because blinking only
works in a fullscreen session. See the call to VioSetState(). The RGB
bits select the desired mixture of Red, Green, and Blue.
The swapcolors macro exchanges the fore- and background colors (the RGB
bits) but leaves the intensity/blink bits where there are. Thus if the
foreground color is bold and the background color is not bold, the same
will be true after swapcolors().
*/
#define swapcolors(x) (((x)&(unsigned)0x88)|(((x)&0x70)>>4)|(((x)&0x07)<<4))
static int tn_bold = 0; /* TELNET negotiation bold */
int esc_exit = 0; /* Escape back = exit */
char * esc_msg;
static long waittime; /* Timeout on CTS during CONNECT */
#define INTERVAL 100L
static char termessage[MAXCOL];
static FILE *lst = NULL; /* List (print) device */
static bool lstclosed = TRUE; /* List device closed flag */
#ifdef CK_APC
extern int apcactive; /* Application Program Command (APC) */
extern int apcstatus; /* items ... */
static int apclength = 0;
#ifdef DCMDBUF
extern char *apcbuf;
#else
extern char apcbuf[];
#endif /* DCMDBUF */
static int apcbuflen = APCBUFLEN - 2;
#endif /* CK_APC */
char * keydefptr = NULL;
int keymac = 0;
int keymacx = -1;
int
xsize = -1, /* Screen width */
ysize = -1; /* Screen height */
ascreen /* For saving screens: */
vt100screen, /* terminal screen */
commandscreen, /* OS/2 screen */
savedscreen, /* (various uses) */
helpscreen; /* Screen behind popup help */
extern ascreen mousescreen; /* Screen during mouse actions */
static unsigned char /* Video attribute bytes */
attribute = NUL, /* Current video attribute byte */
savedattribute = NUL, /* Saved video attribute byte */
defaultattribute = NUL; /* Default video attribute byte */
/*
Note, the following are related to the VT terminal screen, not the PC video
adapter. That is, 'attribute' (above) is the PC video attribute byte,
'attrib' (below) is the VT terminal attribute structure. etc.
*/
static struct { /* Character attributes, 1 bit each */
unsigned reversed:1; /* Reverse video */
unsigned blinking:1; /* Blinking */
unsigned underlined:1; /* Underlined (simulated) */
unsigned bold:1; /* Bold (high intensity) */
unsigned invisible:1; /* Invisible */
} attrib, savedattrib;
/* Screen rollback buffer, circular... */
static struct paging_record {
int flag; /* Nonzero means we are rolled back */
int numlines; /* How many lines saved in buffer */
int topline; /* Index of top line */
int botline; /* Index of bottom line */
int current; /* Index of current line */
char *buffer; /* Pointer to buffer */
int bufsize; /* Size of buffer */
int linesleft; /* How many lines above current line */
int nextline; /* Next line in rollback buffer */
} roll;
int wherex; /* Screen column, 1-based */
int wherey; /* Screen row, 1-based */
static int margintop = 1; /* Top of scrolling region, 1-based */
static int marginbot = 24; /* Bottom of same, 1-based */
static int active, quitnow, hangnow, inshift, outshift, tcs, langsv;
static char answerback[81] = "OS/2 C-Kermit\r"; /* Default answerback */
static char usertext[(MAXCOL) + 1]; /* Status line and its parts */
static char statusline[MAXCOL + 1];
static char exittext[(20) + 1];
#define HLPTXTLEN 41
static char helptext[HLPTXTLEN];
static char filetext[(20) + 1];
static char savefiletext[(20) + 1] = { NUL };
#define HSTNAMLEN 41
static char hostname[HSTNAMLEN];
static unsigned char graphicset[32] = { /* VT100/200 graphic characters */
0x20, 0x04, 0xB0, 0x1A, 0x17, 0x1B, 0x19, 0xF8,
0xF1, 0x15, 0x12, 0xD9, 0xBF, 0xDA, 0xC0, 0xC5,
0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC3, 0xB4, 0xC1,
0xC2, 0xB3, 0xF3, 0xF2, 0xE3, 0x9D, 0x9C, 0xFA
};
#define DEFTABS \
"0T0000000T0000000T0000000T0000000T0000000T0000000T0000000T0000000T0000000\
T0000000T0000000T0000000T0000000T0000000T0000000T0000000T000";
static char htab[133] = DEFTABS /* Default tab settings */
static VIOCURSORINFO crsr_command;
static VIOCURSORINFO crsr_info;
static int row = 0;
static int column = 0;
static int achar;
static unsigned char g0 = 'B'; /* Default G0 charset is US ASCII. */
static unsigned char g1 = 'B'; /* G1 also. */
static unsigned char *g0g1 = &g0;
static bool printon = FALSE; /* Printer is on */
static bool printregion = FALSE; /* Print extent = full screen */
static bool xprintff = FALSE; /* Print formfeed */
static bool turnonprinter = FALSE; /* Time to turn on printer */
static bool xprint = FALSE; /* Transparent print in progress */
static bool turnoffprinter = FALSE; /* Time to turn it off */
static bool wrapit = FALSE;
static bool literal = FALSE;
static bool screenon = TRUE;
static bool cursoron = TRUE; /* For speed, turn off when busy */
static bool cursorena = TRUE; /* Cursor enabled / disabled */
static bool relcursor = FALSE;
static bool keylock = FALSE;
static bool vt52graphics = FALSE;
static unsigned char saveg0, saveg1, *saveg0g1;
static bool saverelcursor, saved=FALSE;
static bool dwl[MAXROW]; /* Double-width line buffer */
static bool dwls = FALSE; /* For optimisation */
static bool deccolm = FALSE; /* 80/132-column mode */
static bool decscnm = FALSE; /* Normal/reverse screen mode */
static bool insertmode = FALSE; /* Insert/replace mode */
/*
Terminal parameters that can also be set externally by SET commands.
Formerly they were declared and initialized here, and had different
names, as shown in the comments. Now they are declared and
initialized in ckuus7.c. - fdc
*/
static int my_tt_type; /* Prevailing terminal type */
static bool tt_hebrew = 0; /* Keyboard is in Hebrew mode */
static int c1controls; /* Flag for C1 controls allowed */
static bool send_c1 = FALSE; /* Flag for sending C1 controls */
/*
VT220 and higher Pn's for terminal ID string are (* = Not supported):
* 1 - 132 columns
2 - Printer port
* 3 - ReGIS graphics
* 4 - Sixel graphics
* 6 - DECSED - Selective erase
* 7 - DRCS - Soft character sets
* 8 - UDK - User-defined keys
* 9 - National Replacement Character Sets can be designated by host
* 13 - Local editing
15 - Technical character set
* 18 - Windowing Capability
* 19 - Dual sessions
*/
struct tt_info_rec tt_info[] = { /* Indexed by terminal type */
"NONE", "", /* None */
"VT52", "/Z", /* DEC VT52 */
"ANSI", "", /* "ANSI" (BBS) */
"VT100", "[?1c", /* DEC VT100 */
"VT102", "[?6c", /* DEC VT102 */
"VT220", "[?62;2;15c" /* DEC VT220 */
#ifdef COMMENT
, "VT320" "[?63;2;15c", /* DEC VT320 */
#endif /* COMMENT */
};
int max_tt = TT_VT320; /* Highest terminal type */
/* SET TERMINAL values ... */
extern int tt_arrow; /* Arrow-key mode */
extern int tt_keypad; /* Keypad mode */
extern int tt_wrap; /* Autowrap */
extern int tt_type; /* Terminal type */
extern int tt_cursor; /* Cursor type */
extern int tt_answer; /* Answerback enabled/disabled */
extern int tt_scrsize; /* Scrollback buffer size */
extern int tt_roll; /* Scrollback style */
extern int tt_rows; /* Screen rows */
extern int tt_cols; /* Screen columns */
extern int tt_ctstmo; /* CTS timeout */
extern int tt_hide; /* Hide-cursor */
extern int tt_pacing; /* Output-pacing */
extern int tt_mouse; /* Mouse */
/* Escape-sequence parser state definitions. */
/* For explanation, see ckucon.c, where this code is copied from. */
#define ES_NORMAL 0 /* Normal, not in escape sequence */
#define ES_GOTESC 1 /* Current character is ESC */
#define ES_ESCSEQ 2 /* Inside an escape sequence */
#define ES_GOTCSI 3 /* Inside a control sequence */
#define ES_STRING 4 /* Inside DCS,OSC,PM, or APC string */
#define ES_TERMIN 5 /* 1st char of string terminator */
#define ESCBUFLEN 128
static int escstate = ES_NORMAL;
static int escnext = 1;
static int esclast = 0;
/* Escape-sequence processing buffer */
static unsigned char escbuffer[ESCBUFLEN+1];
/*
For pushing back input characters,
e.g. converting 8-bit controls to 7-bit escape sequences.
*/
static int f_pushed = 0, c_pushed = 0, f_popped = 0;
static unsigned char sgrcols[8] = {0, 4, 2, 6, 1, 5, 3, 7};
/* Function prototypes */
static CHAR (*sxo)(CHAR); /* Character translation functions */
static CHAR (*rxo)(CHAR); /* for output (sending) terminal chars */
static CHAR (*sxi)(CHAR); /* and for input (receiving) terminal chars. */
static CHAR (*rxi)(CHAR);
#ifndef NOTTOCI
int ttoci(char c);
#endif /* NOTTOCI */
static int popuphelp(int); /* Pop-up help panel maker */
static void ipadl25(void); /* Default status-line maker */
static void line25(void); /* General-purpose status-line maker */
static void xline25(char *);
static void save_status_line(void);
static void restore_status_line(void);
static void resethebrewmode(void);
static int status_saved = -1;
int restorescreen(ascreen *);
static int sendchar(unsigned char);
static void bleep(void);
static void checkscreenmode(void);
static void clearscreen(int, int);
static void clrtoeoln(void);
static void doesc(int c);
static void esc25(int);
static void flipscreen(void);
static void helpline(char *);
static void killcursor(void);
static void lgotoxy(int, int);
static void movetoscreen(char *, int, int, int);
static void newcursor(void);
static void printeron(void);
static void printeroff(void);
static void prtscreen(int, int);
static void restorecursormode(void);
void savescreen(ascreen *, int, int);
static void scroll(int, int, int, int);
static void scrollback(int);
static void setcursormode(void);
static void setmargins(int, int);
static void strinsert(char *, char *);
static void toplinetocyclicbuffer(void);
static void wrtch(char);
static int sendescseq(char *);
int ckcgetc(int);
void cwrite(unsigned char);
extern int concooked(void);
extern int conraw(void);
extern int xxesc(char **);
/* Thread stuff... */
#ifdef __32BIT__
HEV threadsem, threadsem2 ;
ULONG semcount, semcount2;
#define THRDSTKSIZ 131072 /* Needed for Mouse Thread */
#else
static long int threadsem, threadsem2; /* Semaphore for thread running */
#define THRDSTKSIZ 2048
static char stack[THRDSTKSIZ]; /* Stack for second thread */
static char stack2[THRDSTKSIZ]; /* Stack for third thread */
#endif /* __32BIT__ */
static TID threadid,threadid2;
static int
#ifdef COMMENT
iskipesc = 0, /* Skip over ANSI escape sequences */
inesc = ES_NORMAL, /* State of sequence recognizer */
#endif /* COMMENT */
oskipesc = 0, /* Esc seq recognizer for keys... */
outesc = ES_NORMAL;
/*
C H K A E S -- Check ANSI Escape Sequence state.
Previously used for both input and output, now (edit 190) used only
for output of keystrokes. Input is handled in cwrite().
*/
int
chkaes(int esc, char c) {
if (c == CAN || c == SUB) /* CAN and SUB cancel any sequence */
esc = ES_NORMAL;
else /* Otherwise */
switch (esc) { /* enter state switcher */
case ES_NORMAL: /* NORMAL state */
if (c == ESC) /* Got an ESC */
esc = ES_GOTESC; /* Change state to GOTESC */
break; /* Otherwise stay in NORMAL state */
case ES_GOTESC: /* GOTESC state */
if (c == '[') /* Left bracket after ESC is CSI */
esc = ES_GOTCSI; /* Change to GOTCSI state */
else if (c == 'P' || (c > 0134 && c < 0140)) /* P, ], ^, or _ */
esc = ES_STRING; /* Switch to STRING-absorption state */
else if (c > 057 && c < 0177) /* Final character '0' thru '~' */
esc = ES_NORMAL; /* Back to normal */
else if (c != ESC) /* ESC in an escape sequence... */
esc = ES_ESCSEQ; /* starts a new escape sequence */
break; /* Intermediate or ignored ctrl char */
case ES_ESCSEQ: /* ESCSEQ -- in an escape sequence */
if (c > 057 && c < 0177) /* Final character '0' thru '~' */
esc = ES_NORMAL; /* Return to NORMAL state. */
else if (c == ESC) /* ESC ... */
esc = ES_GOTESC; /* starts a new escape sequence */
break; /* Intermediate or ignored ctrl char */
case ES_GOTCSI: /* GOTCSI -- In a control sequence */
if (c > 077 && c < 0177) /* Final character '@' thru '~' */
esc = ES_NORMAL; /* Return to NORMAL. */
else if (c == ESC) /* ESC ... */
esc = ES_GOTESC; /* starts over. */
break; /* Intermediate or ignored ctrl char */
case ES_STRING: /* Inside a string */
if (c == ESC) /* ESC may be 1st char of terminator */
esc = ES_TERMIN; /* Go see. */
break; /* Absorb all other characters. */
case ES_TERMIN: /* May have a string terminator */
if (c == '\\') /* which must be backslash */
esc = ES_NORMAL; /* If so, back to NORMAL */
else /* Otherwise */
esc = ES_STRING; /* Back to string absorption. */
}
return(esc);
}
/* ------------------------------------------------------------------ */
/* ipadl25 - Make normal CONNECT-mode status line */
/* ------------------------------------------------------------------ */
static void
ipadl25() {
int i, j, n;
char *s, *p;
strcpy(usertext," C-Kermit ");
if (debses)
strcat(usertext,"DEBUG");
else if (tt_type > -1 && tt_type <= max_tt)
strcat(usertext,tt_info[tt_type].x_name);
if (tt_hebrew)
strcat(usertext,"-H");
if (printon) {
strcpy(filetext,"PRINTER ON");
} else if ( !network )
sprintf(filetext, "Serial %ld", speed);
else
switch ( nettype ) {
case NET_DEC:
switch ( ttnproto ) {
case NP_LAT:
strcpy(filetext, "DECnet LAT");
break;
case NP_CTERM:
strcpy(filetext, "DECnet CTERM");
break;
default:
strcpy(filetext, "DECnet");
break;
}
break;
case NET_TCPB:
switch ( ttnproto ) {
case NP_TELNET:
strcpy(filetext, "TELNET");
break;
default:
strcpy(filetext, "TCP/IP");
break;
}
break;
case NET_PIPE:
strcpy(filetext, "Named Pipe");
break;
case NET_BIOS:
strcpy(filetext, "NetBIOS");
break;
}
if (vik.help > 255 && keynam[vik.help - 256])
sprintf(helptext, "Help: %s", keynam[vik.help - 256]);
else
sprintf(helptext, "Help: ^%c?", ctl(escape));
if (vik.exit > 255 && keynam[vik.exit - 256])
sprintf(exittext, "%s %s", esc_msg, keynam[vik.exit - 256]);
else
sprintf(exittext, "%s ^%c?", esc_msg, ctl(escape));
strncpy(hostname, ttname, 40);
#ifdef CK_NETBIOS
if ( ( nettype == NET_BIOS ) && ( *ttname == '*' ) )
strncpy(hostname+1, NetBiosRemote, NETBIOS_NAME_LEN ) ;
#endif /* CK_NETBIOS */
if (!network)
strupr(hostname);
line25();
}
/* ------------------------------------------------------------------ */
/* CursorUp - */
/* ------------------------------------------------------------------ */
static void
cursorup() {
if ((relcursor ? margintop : 1) != wherey)
lgotoxy(wherex, wherey - 1);
}
/* ------------------------------------------------------------------ */
/* CursorDown - */
/* ------------------------------------------------------------------ */
static void
cursordown() {
if ((relcursor ? marginbot : ysize) != wherey)
lgotoxy(wherex, wherey + 1);
}
/* ------------------------------------------------------------------ */
/* CursorRight - */
/* ------------------------------------------------------------------ */
static void
cursorright() {
if (wherex < (dwl[wherey - 1] ? xsize - 1 : xsize))
lgotoxy(wherex + 1, wherey);
}
/* ------------------------------------------------------------------ */
/* CursorLeft - */
/* ------------------------------------------------------------------ */
static void
cursorleft() {
if (wherex > 1)
lgotoxy(wherex - 1, wherey);
}
/* ------------------------------------------------------------------ */
/* ReverseScreen */
/* fixed by fdc, edit 190 */
/* ------------------------------------------------------------------ */
static void
reversescreen() {
int i, r, c, x;
USHORT n;
unsigned char cell[MAXCOL * 2];
#ifdef OS2MOUSE
os2_mousehide() ;
#endif /* OS2MOUSE */
n = xsize * 2;
for (r = 0; r < ysize; r++) { /* Loop for each row */
VioReadCellStr(cell, &n, r, 0, 0); /* Read this row from the screen */
for (c = 0; c < xsize; c++) { /* Loop for each character in row */
x = c + c + 1; /* Location of attribute byte */
cell[x] = swapcolors(cell[x]);
}
VioWrtCellStr(cell, n, r, 0, 0); /* Write the row back. */
}
#ifdef OS2MOUSE
os2_mouseshow() ;
#endif
}
void
reverserange( SHORT fromrow, SHORT fromcol, SHORT torow, SHORT tocol ) {
int r, c;
SHORT temp;
USHORT n;
unsigned char cell[2];
unsigned char D[80];
#ifdef OS2MOUSE
os2_mousehide() ;
#endif /* OS2MOUSE */
sprintf( D, "ReverseRange: from (%d,%d) to (%d,%d)",
fromrow,fromcol,torow,tocol);
debug(F100,D,"",0);
if ( fromrow > torow || ( fromrow == torow && fromcol > tocol ) ) {
temp = fromcol ;
fromcol = tocol ;
tocol = temp ;
}
if ( fromrow > torow ) {
temp = fromrow ;
fromrow = torow ;
torow = temp ;
}
for ( r = fromrow ; r <= torow ; r++ ) {
for ( c = ( r==fromrow ? fromcol : 0 ) ;
c <= ( r == torow ? tocol : xsize -1 ) ;
c++ ) {
n = 2 ;
VioReadCellStr(cell, &n, r, c, 0 ) ;
cell[1] = swapcolors(cell[1]) ;
VioWrtCellStr( cell, n, r, c, 0 ) ;
}
}
#ifdef OS2MOUSE
os2_mouseshow() ;
#endif
}
static void /* Flip screen between */
flipscreen() { /* normal and reverse video */
unsigned char fg, bg;
reversescreen();
if (decscnm) { /* Currently reverse-video? */
defaultattribute = colornormal; /* Yes, go back to normal color */
decscnm = FALSE; /* Change DECSCNM value */
} else {
defaultattribute = swapcolors(colornormal);
decscnm = TRUE;
}
/* Subsequent chars are written with current attributes, colors swapped. */
attribute = swapcolors(attribute);
colorunderline = swapcolors(colorunderline);
}
/* ----------------------------------------------------------------- */
/* ClrScreen - */
/* ----------------------------------------------------------------- */
static void
clrscreen() {
int i, j;
int nlines;
USHORT n;
char cells[MAXCOL * 2];
#ifdef OS2MOUSE
os2_mousehide() ;
#endif
/* Copy lines on screen to extended display buffer */
n = xsize * 2; /* Size of screen-line buffer */
for (i = ysize - 1; i >= 0; i--) { /* Start at screen bottom */
VioReadCellStr((char *) cells, &n, i, 0, 0); /* Get screen line */
for (j = 0; j < xsize; j++) { /* Look at the characters in it */
if (cells[j * 2] != ' ') /* Is this one nonblank? */
break; /* Yes, stop looking at this line */
}
if (j < xsize) /* If this is a nonblank line, */
break; /* quit the big loop too. */
}
/* Now we've located the lowest nonblank line */
nlines = i; /* Number of lines to clear, minus 1 */
for (i = 0; i <= nlines; ++i) {
roll.botline = (roll.botline + 1) % LBUFSIZE;
if (roll.numlines < LBUFSIZE)
roll.numlines++;
else
roll.topline = (roll.topline + 1) % LBUFSIZE;
VioReadCellStr((roll.buffer + xsize * 2 * roll.botline),&n, i, 0, 0);
}
for (i = 0; i < ysize; i++)
dwl[i] = FALSE;
dwls = FALSE;
clearscreen(0, defaultattribute);
#ifdef OS2MOUSE
os2_mouseshow() ;
#endif
}
/* ----------------------------------------------------------------- */
/* PrtScreen - Copy lines on screen to printer. */
/* parameters = Top line to print, bottom line to print, 1-based. */
/* ----------------------------------------------------------------- */
static void
prtscreen(int top, int bot) {
int i, j, first, last;
USHORT n;
char cells[MAXCOL * 2];
char outbuf[MAXCOL + 1];
if (printon) /* Printer already on? */
return;
if (top < 1 || bot > ysize) /* Args out of bounds? */
return;
printeron(); /* Turn on printer */
#ifdef OS2MOUSE
os2_mousehide() ;
#endif
if (lst) { /* If printer on */
n = xsize * 2; /* Line width, incl attributes */
for (i = top; i <= bot; i++) { /* For each screen line, i... */
/* Internally, screen lines are 0-based, so "i-1". */
VioReadCellStr((char *) cells, &n, i-1, 0, 0); /* Get line i */
for (j = 0; j < xsize; j++) /* Strip away the attribute bytes */
outbuf[j] = cells[j+j];
for (j = xsize - 1; j >= 0; j--) /* Strip trailing blanks */
if (outbuf[j] != SP) break;
outbuf[j+1] = NUL; /* Terminate with NUL */
fprintf(lst,"%s\r\n",outbuf); /* Print the line */
}
if (xprintff /* && top == 1 && bot == ysize */ )
fprintf(lst,"%c",FF);
#ifdef OS2MOUSE
os2_mouseshow() ;
#endif
printeroff();
}
}
static int
pnumber(int *achar) {
int num = 0;
while (isdigit(*achar)) { /* Get number */
num = (num * 10) + (*achar) - 48;
*achar = (escnext<=esclast)?escbuffer[escnext++]:0;
}
return (num);
}
static void
clreoscr_escape() {
char cell[2];
int i;
if (wherex == 1 && wherey == 1) {
clrscreen();
return;
}
cell[0] = ' ';
#ifdef COMMENT
/* Wrong! - fdc */
cell[1] = attribute;
#else
cell[1] = defaultattribute;
#endif /* COMMENT */
i = (xsize * ysize) - (((wherey - 1) * xsize) + (wherex - 1));
#ifdef OS2MOUSE
os2_mousehide() ;
#endif /* OS2MOUSE */
VioWrtNCell(cell, i, wherey - 1, wherex - 1, 0);
#ifdef OS2MOUSE
os2_mouseshow() ;
#endif
for (i = wherey - 1; i < ysize; i++)
dwl[i] = FALSE;
dwls = FALSE;
for (i = 0; i < ysize; i++)
if (dwl[i]) {
dwls = TRUE;
break;
}
}
static void
clrboscr_escape() {
char cell[2];
int i;
cell[0] = ' ';
#ifdef COMMENT
/* Wrong! - fdc */
cell[1] = attribute;
#else
cell[1] = defaultattribute;
#endif /* COMMENT */
i = ((wherey - 1) * xsize) + wherex;
#ifdef OS2MOUSE
os2_mousehide() ;
#endif /* OS2MOUSE */
VioWrtNCell(cell, i, 0, 0, 0);
#ifdef OS2MOUSE
os2_mouseshow() ;
#endif
for (i = 0; i < wherey; i++)
dwl[i] = FALSE;
dwls = FALSE;
for (i = 0; i < ysize; i++)
if (dwl[i]) {
dwls = TRUE;
break;
}
}
static void
clrbol_escape() {
char cell[2];
cell[0] = ' ';
#ifdef COMMENT
cell[1] = attribute;
#else
cell[1] = defaultattribute;
#endif /* COMMENT */
#ifdef OS2MOUSE
os2_mousehide() ;
#endif /* OS2MOUSE */
VioWrtNCell(cell, wherex, wherey - 1, 0, 0);
#ifdef OS2MOUSE
os2_mouseshow() ;
#endif
}
static void
clrline_escape() {
char cell[2];
cell[0] = ' ';
#ifdef COMMENT
cell[1] = attribute;
#else
cell[1] = defaultattribute;
#endif /* COMMENT */
#ifdef OS2MOUSE
os2_mousehide() ;
#endif /* OS2MOUSE */
VioWrtNCell(cell, xsize, wherey - 1, 0, 0);
#ifdef OS2MOUSE
os2_mouseshow() ;
#endif
}
static void
decdwl_escape(bool dwlflag) {
unsigned char linenumber;
unsigned char newx;
char cells[MAXCOL * 2];
int i;
USHORT n;
#ifdef OS2MOUSE
os2_mousehide() ;
#endif /* OS2MOUSE */
/* DECDWL */
linenumber = wherey - 1;
if (dwlflag != dwl[linenumber]) {
/* change size */
n = xsize * 2;
VioReadCellStr((char *) cells, &n, linenumber, 0, 0);
if (dwlflag) { /* Make this line double size */
for (i = xsize / 2 - 1; i >= 0; --i) { /* Expand */
cells[4 * i] = cells[2 * i];
cells[4 * i + 2] = ' ';
}
newx = (wherex - 1) * 2 + 1;
dwls = TRUE;
} else { /* Make this line single size */
for (i = 0; i <= xsize / 2 - 1; ++i)
cells[2 * i] = cells[4 * i];
for (i = xsize / 2; i < xsize; ++i)
cells[2 * i] = ' ';
newx = (wherex - 1) / 2 + 1;
dwls = FALSE;
for (i = 0; i < ysize; i++)
if (dwl[i]) {
dwls = TRUE;
break;
}
}
VioWrtCellStr((char *) cells, n, linenumber, 0, 0);
dwl[linenumber] = dwlflag;
if (newx >= xsize)
newx = xsize - 1;
lgotoxy(newx, wherey);
}
#ifdef OS2MOUSE
os2_mouseshow() ;
#endif
}
static void
printeron() {
if (printon) /* It's already on. */
return;
if (lstclosed || !lst) { /* Open printer device */
if (!printfile) /* If printer not redirected */
lst = fopen("prn", "w"); /* open the PRN device */
else /* otherwise */
lst = fopen(printfile, "ab"); /* open the file in append mode. */
}
if (lst) { /* Open OK? */
strcpy(savefiletext,filetext);
strcpy(filetext,"PRINTER ON");
line25();
lstclosed = FALSE; /* So not closed */
printon = TRUE; /* and printer is on. */
}
}
static void
printeroff() { /* Turn off printer */
if (!printon) /* It's already off. */
return;
if (lst && !lstclosed)
fclose(lst);
lstclosed = TRUE;
printon = FALSE;
if (savefiletext[0]) { /* Fix status line */
strcpy(filetext,savefiletext);
savefiletext[0] = NUL;
}
line25();
}
#define CK_BORDER /* Allow border colors */
static int cmd_border = -1;
static void
setborder() {
#ifdef CK_BORDER
VIOOVERSCAN vo; /* Set border (overscan) color */
vo.cb = sizeof(vo); /* for terminal emulation window */
vo.type = 1;
vo.color = colorborder;
VioSetState((PVOID) &vo, 0);
#endif /* CK_BORDER */
}
static void
saveborder() { /* Save command-screen border */
#ifdef CK_BORDER
VIOOVERSCAN vo;
vo.cb = sizeof(vo);
vo.type = 1;
VioGetState((PVOID) &vo, 0);
cmd_border = vo.color;
#endif /* CK_BORDER */
}
static void
restoreborder() {
#ifdef CK_BORDER
VIOOVERSCAN vo; /* Restore command-screen border */
if (cmd_border < 0) /* None saved. */
return;
vo.cb = sizeof(vo);
vo.type = 1;
vo.color = cmd_border;
cmd_border = 0;
VioSetState((PVOID) &vo, 0);
#endif /* CK_BORDER */
}
static void /* Reset the terminal emulator */
doreset(int x) { /* x = 0 (soft), nonzero (hard) */
int i;
defaultattribute = colornormal; /* Normal colors */
if (decscnm)
colorunderline = swapcolors(colorunderline);
attribute = defaultattribute; /* Default attributes */
attrib.blinking = FALSE; /* No blink */
attrib.bold = FALSE; /* No bold */
attrib.invisible = FALSE; /* Not invisible */
attrib.underlined = FALSE; /* No underline */
attrib.reversed = FALSE; /* No reverse video */
g0 = g1 = 'B'; /* ASCII (not UK) in G0 and G1 */
g0g1 = &g0; /* (sort of...) */
printon = FALSE; /* Printer is not on */
printregion = FALSE; /* Printer extent is full screen */
screenon = TRUE; /* The screen is turned on */
#ifdef CK_APC
apcactive = 0; /* An APC command is not active */
apclength = 0; /* ... */
#endif /* CK_APC */
vt52graphics = FALSE; /* Get out of VT52 graphics mode */
saved = FALSE; /* Nothing is saved */
tnlm = tt_crd = FALSE; /* We're not in newline mode */
insertmode = FALSE; /* Not in character-insert mode */
tt_arrow = TTK_NORM; /* Arrow keypad to cursor mode */
tt_keypad = TTK_NORM; /* Auxilliary keypad to numeric mode */
tt_wrap = TRUE; /* (FALSE for real VT terminal!) */
tt_type = my_tt_type; /* Terminal type back to original */
send_c1 = FALSE; /* Don't send C1 controls */
keylock = FALSE; /* Keyboard is not locked */
deccolm = FALSE; /* 80-column mode */
decscnm = FALSE; /* Screen is not in reverse video */
for (i = 0; i < ysize; i++) /* Not in double-width-line mode */
dwl[i] = FALSE;
dwls = FALSE;
for (i = 1; i < xsize; i++) /* Tab settings every 8 spaces */
htab[i] = (i % 8) == 1 ? 'T' : '0'; /* was "== 0" */
relcursor = FALSE; /* Cursor position is absolute */
setmargins(1, ysize); /* Scrolling region is whole screen */
escstate = ES_NORMAL; /* In case we're stuck in a string */
setborder(); /* Restore border color */
cursorena = TRUE; /* Cursor is enabled */
resethebrewmode(); /* Leave Hebrew keyboard mode */
setcursormode(); /* Get rid of any unwanted blinking */
if (x) clrscreen(); /* Now clear the screen */
newcursor(); /* Put up a cursor */
if (roll.flag) /* Were we rolled back? */
roll.flag = 0; /* Not any more ... */
ipadl25(); /* Put back regular status line */
}
static void
savecurpos(int x) { /* x: 0 = cursor only, 1 = all */
saved = TRUE; /* Remember they are saved */
row = wherey; /* Current row (absolute) */
column = wherex; /* Current column (absolute) */
if (x) {
savedattribute = attribute; /* Current PC video attributes */
savedattrib = attrib; /* Current DEC character attributes */
saverelcursor = relcursor; /* Cursor addressing mode */
saveg0 = g0; /* Character sets */
saveg1 = g1;
saveg0g1 = g0g1;
}
}
static void
restorecurpos(int x) {
if (saved == FALSE) { /* Nothing saved, home the cursor */
lgotoxy(1, relcursor ? margintop : 1);
return;
}
#ifdef COMMENT
/* Wrong! Restoring the saved parameters does not unsave them. -fdc */
saved = FALSE;
#endif /* COMMENT */
lgotoxy(column, row); /* Goto saved position */
if (x) {
attribute = savedattribute; /* Restore saved attributes */
attrib = savedattrib;
relcursor = saverelcursor; /* Restore cursor addressing mode */
g0 = saveg0; /* Restore character sets */
g1 = saveg1;
g0g1 = saveg0g1;
}
}
/*
Hebrew keyboard-mode support functions. These are needed when using a
non-Hebrew keyboard to enter Hebrew letters during CONNECT mode. When
the keyboard is in "English" mode, the main keypad acts normally. When it
is in Hebrew mode, the lowercase letters (and some punctuation marks) are
mapped to Hebrew letters. Keyboard mode is set via the keyboard verbs
\KkbHebrew and \KkbHebrew, and also by DECHEBM escape sequences
(CSI ? 35 h / l) from the host (handled in vtescape()). Both methods
invoke these routines.
*/
static void
sethebrewmode() { /* Enter Hebrew keyboard mode */
/*
This is the WordPerfect / Windows / Microsoft Word mapping. If different
mappings are needed, we can add them via a parameter to this function,
settable by a SET TERMINAL HEBREW-KEYMAP command. Note that we don't change
the keymap by executing a macro (like MS-DOS Kermit's KEYBOARDS/KEYBOARDR
macros) since that causes disconcerting and lengthy screen flashes as Kermit
pops back and forth between CONNECT and command mode.
*/
keymap[ 39] = 44; /* ' (Apostrophe) = , (Comma) */
keymap[ 44] = 154; /* , (Comma) = Taw */
keymap[ 46] = 149; /* . (Period) = Final Zade */
keymap[ 47] = 46; /* / (Slash) = . (Period) */
keymap[ 59] = 147; /* ; (Semicolon) = Terminal Pe */
keymap[ 97] = 153; /* a = Shin */
keymap[ 98] = 144; /* b = Nun */
keymap[ 99] = 129; /* c = Bet */
keymap[100] = 130; /* d = Gimel */
keymap[101] = 151; /* e = Qoph */
keymap[102] = 139; /* f = Kaph */
keymap[103] = 146; /* g = Ayin */
keymap[104] = 137; /* h = Yod */
keymap[105] = 143; /* i = Final Nun */
keymap[106] = 135; /* j = Chet */
keymap[107] = 140; /* k = Lamed */
keymap[108] = 138; /* l = Final Kaph */
keymap[109] = 150; /* m = Zade */
keymap[110] = 142; /* n = Mem */
keymap[111] = 141; /* o = Final Mem */
keymap[112] = 148; /* p = Pe */
keymap[113] = 47; /* q = / (slash) */
keymap[114] = 152; /* r = Resh */
keymap[115] = 131; /* s = Dalet */
keymap[116] = 128; /* t = Aleph */
keymap[117] = 133; /* u = Waw */
keymap[118] = 132; /* v = He */
keymap[119] = 39; /* w = ' (Apostrophe) */
keymap[120] = 145; /* x = Samech */
keymap[121] = 136; /* y = Tet */
keymap[122] = 134; /* z = Zain */
tt_hebrew = TRUE;
if (!roll.flag)
ipadl25() ;
}
static void
resethebrewmode() { /* Enter English keyboard mode */
/*
Warning: This routine assumes that main keypad keys (lowercase Roman letters
and punctuation marks) are normally mapped to themselves.
*/
KEY k;
keymap[39] = 39; /* Apostrophe */
keymap[44] = 44; /* Comma */
keymap[46] = 46; /* Period */
keymap[47] = 47; /* Slash */
keymap[59] = 59; /* Semicolon */
for (k = 97; k < 123; k++) /* Letters a-z */
keymap[k] = k;
tt_hebrew = FALSE;
if (!roll.flag)
ipadl25() ;
}
/*
The flow of characters from the communication device to the screen is:
+---(debug)----+
| |
rdcomwrtscr --> cwrite --+--> vt100 --> wrtch
| |
+--> vtescape--+
rdcomwrtscr() reads character from communication device via ttinc() and:
- converts 8-bit controls to 7-bit ESC sequences
- handles TELNET negotiations
- handles SO/SI (NOTE: this prevents
- handles charset translation
- handles newline-mode and cr-display
- handles connection loss
- passes all output chars to cwrite()
cwrite()
- handles debug output, direct to wrtch().
- detects and parses escape-sequences:
. builds up escape sequence in buffer
. when complete, calls vtescape(), or does APC.
- when not debugging & not in esc seq, sends all other chars to vt100().
vt100()
- handles ctrl chars in straightforward, modeless way (ENQ, tab, BS, beep)
- *thinks* it handles SO/SI, but never gets called for this (???)
- handles graphic chars via mode (g0, g1, vtgraphics, etc) -> wrtch()
- handles wraparound
vtescape()
- acts on escape sequences, changes state, moves cursor, etc.
*/
/* V T E S C A P E -- Interpret a VT52/100/102/220 escape sequence */
/*
Called after an escape sequence has been received and collected
into escbuffer[]. To be added:
ISO 2022 Character-set designation
DEC national vs multinational character-set (DECNRCM)
Addition of G2, G3
Single shifts
Locking shifts beyond SO/SI (G2, G3)
Soft character sets (DRCS)
User Defined Keys (DECUDK)
DECSTR 220 CSI ! p Soft reset, keeps screen
DECSCL 220 CSI Pl; Pc " p Set conformance level + soft reset
DECSCA 220 CSI Ps " q Select erasable/not erasable
DECSEL 220 CSI ? Pn K Selective erase
etc etc...
*/
static void
vtescape() {
unsigned char j;
unsigned char k;
unsigned char l;
unsigned char blankcell[2];
int i;
int pn[11];
bool private;
char tempstr[20];
int fore, back;
escstate = ES_NORMAL; /* Set escape state back to normal */
escnext = 1; /* Point to beginning of esc seq buf */
if (debses) /* If TERMINAL DEBUG ON, */
return; /* we don't actually do anything. */
achar = (escnext<=esclast)?escbuffer[escnext++]:0;
if (screenon || (achar == '[')) {
/* screen escape sequences */
switch (achar) { /* First Level */
case '[': /* CSI */
{
achar = (escnext<=esclast)?escbuffer[escnext++]:0;
switch (achar) { /* Second level */
case 'A': /* Cursor up one line */
cursorup();
wrapit = FALSE;
break;
case 'B': /* Cursor down one line */
cursordown();
wrapit = FALSE;
break;
case 'C': /* Cursor forward, stay on same line */
cursorright();
if (dwl[wherey - 1])
cursorright();
break;
case 'D': /* Cursor back, stay on same line */
cursorleft();
if (dwl[wherey - 1])
cursorleft();
break;
case 'J': /* Erase from cursor to end of scrn */
clreoscr_escape();
break;
case 'K': /* Erase from cursor to end of line */
clrtoeoln();
break;
case '?': /* DEC private */
private = TRUE;
achar = (escnext<=esclast)?escbuffer[escnext++]:0;
goto LB2001;
case 'f':
case 'H': /* Cursor Home */
lgotoxy(1, relcursor ? margintop : 1);
break;
case 'g': /* Tab Clear at this position */
htab[wherex] = '0';
break;
case '}':
case 'm': /* Normal Video - Exit all attribute modes */
attribute = defaultattribute;
attrib.blinking = FALSE;
attrib.bold = FALSE;
attrib.invisible = FALSE;
attrib.underlined = FALSE;
attrib.reversed = FALSE;
break;
case 'r': /* Reset Margin */
setmargins(1, ysize);
lgotoxy(1, 1);
break;
case 's': /* ANSI.SYS save cursor position */
savecurpos(0);
break;
case 'u': /* ANSI.SYS restore cursor position */
restorecurpos(0);
break;
case 'c':
case 'h':
case 'l':
case 'n':
case 'x':
pn[1] = 0;
private = FALSE;
k = 1;
goto LB2003;
case ';': /* As in ESC [ ; 7 m */
pn[1] = 0;
private = FALSE;
k = 1;
goto LB2002;
case 'L':
case 'M':
case '@':
case 'P':
pn[1] = 1;
private = FALSE;
k = 1;
goto LB2002;
default: /* Pn - got a number */
private = FALSE;
LB2001:
{ /* Esc [ Pn...Pn x functions */
pn[1] = pnumber(&achar);
k = 1;
LB2002:
while (achar == ';') { /* get Pn[k] */
achar = (escnext<=esclast)?escbuffer[escnext++]:0;
k++;
if (achar == '?')
achar = (escnext<=esclast)?escbuffer[escnext++]:0;
pn[k] = pnumber(&achar);
}
pn[k + 1] = 1;
LB2003:
switch (achar) { /* Third level */
case 'A': /* Cursor up Pn lines */
do {
cursorup();
wrapit = FALSE;
pn[1] = pn[1] - 1;
} while (!(pn[1] <= 0));
break;
case 'B': /* Cursor down pn lines */
do {
cursordown();
wrapit = FALSE;
pn[1] = pn[1] - 1;
} while (!(pn[1] <= 0));
break;
case 'C': /* Cursor right pn chars */
do {
cursorright();
if (dwl[wherey - 1])
cursorright();
pn[1] = pn[1] - 1;
} while (pn[1] > 0);
break;
case 'D': /* Cursor Left pn characters */
do {
cursorleft();
if (dwl[wherey - 1])
cursorleft();
pn[1] = pn[1] - 1;
} while (pn[1] > 0);
break;
case 'f': /* Direct cursor address */
case 'H':
if (pn[1] == 0)
pn[1] = 1;
if (relcursor)
pn[1] += margintop - 1;
if (pn[1] > ysize)
pn[1] = ysize;
if (pn[2] == 0)
pn[2] = 1;
if (dwl[pn[1] - 1]) {
pn[2] = 2 * pn[2] - 1;
if (pn[2] > xsize)
pn[2] = xsize - 1;
} else if (pn[2] > xsize)
pn[2] = xsize;
wrapit = FALSE;
lgotoxy(pn[2], pn[1]);
break;
case 'c': /* Device Attributes */
if (pn[1] == 0)
if (tt_type >= 0 && tt_type <= max_tt) {
if (!network) msleep(100);
sendescseq(tt_info[tt_type].x_id);
}
break;
case 'g':
if (pn[1] == 3) {
/* clear all tabs */
for (j = 1; j <=xsize; ++j)
htab[j] = '0';
} else if (pn[1] == 0)
/* clear tab at current position */
htab[wherex] = '0';
break;
case 'h': /* Set Mode */
for (j = 1; j <= k; ++j)
if (private)
switch (pn[j]) { /* Field specs */
case 1: /* DECCKM */
tt_arrow = TTK_APPL;
break;
case 2: /* DECANM : ANSI/VT52 */
tt_type = my_tt_type;
vt52graphics = FALSE;
break;
case 3: /* DECCOLM = 132 Columns */
deccolm = TRUE;
clrscreen();
break;
case 4: /* DECSCLM - Smooth scroll */
break;
case 5: /* DECSCNM - Reverse screen */
if (decscnm) /* Already reverse */
break;
else
flipscreen();
break;
case 6: /* DECOM - Relative origin */
relcursor = TRUE;
lgotoxy(1, margintop);
break;
case 7: /* DECAWM - Auto Wrap mode */
tt_wrap = TRUE;
break;
#ifdef COMMENT
case 8: /* DECARM - Autorepeat */
break;
case 9: /* DECINLM - Interlace */
break;
#endif /* COMMENT */
#ifdef __32BIT__
case 18: /* DECPFF - Print Form Feed */
xprintff = TRUE;
break;
case 19: /* DECPEX - Printer extent */
printregion = FALSE; /* Full screen */
break;
#endif /* __32BIT__ */
case 25: /* DECTCEM - Cursor On */
newcursor();
cursorena = TRUE;
break;
case 35: /* DECHEBM */
/* Enter Hebrew keyboard mode */
sethebrewmode();
break;
#ifdef COMMENT
case 38: /* DECTEK */
/* Enter Tektronix 4010/4014 mode */
break;
case 42: /* DECNRCM */
/* Use 7-bit NRC */
break;
case 43: /* DECGEPM */
/* Graphics Expanded Print mode */
case 44: /* DECGPCM */
/* Graphics Print Color mode */
case 45: /* DECGPCS */
/* Graphics Print Color syntax = RGB */
case 46: /* DECGPBM */
/* Graphics Print Background mode */
case 47: /* DECGRCM */
/* Graphics Rotated Print mode */
break;
#endif /* COMMENT */
default:
break;
} else /* Not private */
switch (pn[j]) {
case 2: /* Keyboard locked */
keylock = TRUE;
break;
case 4: /* ANSI insert mode */
if (tt_type >= TT_VT102)
insertmode = TRUE;
break;
case 12: /* SRM - Send Receive ON */
duplex = 0; /* Remote echo */
break;
case 20:
/* LNM - linefeed / newline mode */
tt_crd = tnlm = TRUE;
break;
default:
break;
}
break;
case 'l': /* Reset Mode */
for (j = 1; j <= k; ++j) /* Go thru all pn's */
if (private)
switch ((pn[j])) { /* Field specs */
case 1: /* DECCKM - Cursor key mode */
tt_arrow = TTK_NORM;
break;
case 2: /* DECANM : ANSI/VT52 */
tt_type = TT_VT52;
vt52graphics = FALSE;
break;
case 3: /* DECCOLM - 80 Columns */
deccolm = FALSE;
clrscreen();
break;
case 4: /* DECSCLM - Jump scrolling */
break;
case 5: /* DECSCNM - Normal screen */
if (!decscnm) /* Already normal? */
break;
else
flipscreen();
break;
case 6: /* DECOM - Absolute origin */
relcursor = FALSE;
lgotoxy(1, 1);
break;
case 7: /* DECAWM - Auto wrap */
tt_wrap = FALSE;
break;
#ifdef COMMENT
case 8: /* DECARM - Auto repeat */
break;
case 9: /* DECINLM - Interlace */
break;
#endif /* COMMENT */
#ifdef __32BIT__
case 18: /* DECPFF - Print Form Feed */
xprintff = FALSE;
break;
case 19: /* DECPEX - Print extent */
printregion = TRUE; /* Region */
break;
#endif /* __32BIT__ */
case 25: /* DECTCEM - Cursor Off */
if (cursorena)
killcursor();
cursorena = FALSE;
break;
case 35: /* DECHEBM */
/* Enter English keyboard mode */
resethebrewmode();
break;
#ifdef COMMENT
case 38: /* DECTEK */
/* Exit Tektronix 4010/4014 mode */
break;
case 42: /* DECNRCM */
/* Use 8-bit multinational char set */
break;
case 43: /* DECGEPM */
/* Graphics Normal Print mode */
case 44: /* DECGPCM */
/* Graphics Print Monochrome mode */
case 45: /* DECGPCS */
/* Graphics Print Color syntax = HLS */
case 46: /* DECGPBM */
/* Graphics Print No-Background mode */
case 47: /* DECGRCM */
/* Graphics Unrotated Print mode */
break;
#endif /* COMMENT */
default:
break;
} else /* Not private */
switch (pn[j]) {
case 2: /* Keyboard unlocked */
keylock = FALSE;
break;
case 4: /* ANSI insert mode */
insertmode = FALSE;
break;
case 12: /* SRM - Send Receive OFF */
duplex = 1; /* Local echo */
break;
case 20:
/* LNM - linefeed / newline mode */
tt_crd = tnlm = FALSE;
break;
default:
break;
}
break;
case 'i': /* Media Copy */
#ifdef __32BIT__
/*
This code crashes the 16-bit version with Stack Overflow.
Print-Whole-Screen & Print-Cursor-Line support added in edit 190, fdc.
*/
if (pn[1] == 0) /* Print whole screen */
prtscreen(printregion?margintop:1,
printregion?marginbot:ysize);
else if (pn[1] == 1 && /* Print cursor line */
private == TRUE) /* Only if ESC [?1i */
prtscreen(wherey,wherey);
/*
For pn = 4 or 5, we should differentiate here between transparent print
(private == FALSE) and autoprint (private == TRUE). As presently coded,
we always do transparent print. Autoprint means that the current screen
line is printed as soon as the cursor leaves it, i.e. when the terminal
receives a linefeed, form feed, or vertical tab, or when it wraps.
*/
else if (pn[1] == 4) {
turnoffprinter = TRUE;
xprint = FALSE;
} else if (pn[1] == 5)
turnonprinter = xprint = TRUE;
/* 6 and 7 are not in the VT102 manual. Maybe in the Scottish version? */
else if (pn[1] == 6) /* Turn off screen display */
screenon = FALSE;
else if (pn[1] == 7) /* Turn on screen display */
screenon = TRUE;
#endif /* __32BIT__ */
break;
case 'q': /* Load LEDs */
break; /* (nothing) */
case 'n':
/* Pages 103-104, VT220 manual */
if (pn[1] == 5) /* Terminal Status Report */
sendescseq("[0n"); /* Terminal is OK */
else if (pn[1] == 6) { /* Cursor position report */
#ifndef __32BIT__
/*
16-bit version must use a hand-coded in-line version of sprintf to avoid
the function call that would crash the program with a stack overflow.
Handles numbers 0 - 999. No range checking. - fdc
*/
int i = 0, j;
tempstr[i++] = '[';
if ((j = wherey / 100) > 0)
tempstr[i++] = (char) (j + 48);
if ((j = (wherey % 100) / 10) > 0 ||
wherey > 99)
tempstr[i++] = (char) (j + 48);
if ((j = wherey % 10) > 0 ||
wherey > 9)
tempstr[i++] = (char) (j + 48);
tempstr[i++] = ';';
if ((j = wherex / 100) > 0)
tempstr[i++] = (char) (j + 48);
if ((j = (wherex % 100) / 10) > 0 ||
wherex > 99)
tempstr[i++] = (char) (j + 48);
if ((j = wherex % 10) > 0 ||
wherex > 9)
tempstr[i++] = (char) (j + 48);
tempstr[i++] = 'R';
tempstr[i] = '\0';
sendescseq(tempstr);
#else
/* 32-bit version can call sprintf() here. */
sprintf(tempstr,"[%d;%dR", wherey, wherex);
sendescseq(tempstr);
#endif /* __32BIT__ */
} else if (pn[1] == 15) {
/* DECDSR Printer status */
sendescseq("[?10n"); /* Printer is ready */
} else if (pn[1] == 26) {
/* DECDSR Keyboard language, UK or US */
sendescseq((g0 == (CHAR) 'A') ?
"[?27;2n" :
"[?27;1n" );
} else if (pn[1] == 25) {
/* DECDSR UDK status; 20=unlocked, 21=locked */
sendescseq("[?21n");
}
break;
case 'x': /* DECREQTPARM Request Terminal Parameters */
if (pn[1] > 1)
break;
tempstr[0] = '[';
tempstr[1] = (pn[1] == 0) ? '2' : '3';
tempstr[2] = ';';
tempstr[5] = '2'; /* Nbits = 7 */
switch (parity) {
case 0:
tempstr[3] = '1'; /* Parity = None */
/* Nbits depends on TERMINAL BYTESIZE */
if (cmask == 0xFF)
tempstr[5] = '1'; /* Nbits = 8 */
break;
case 'e':
tempstr[3] = '5'; /* Parity = Even */
break;
case 'o':
tempstr[3] = '4'; /* Parity = Odd */
break;
case 'm':
tempstr[3] = '3'; /* Parity = Mark */
break;
default:
tempstr[3] = '2'; /* Parity = Space */
break;
}
tempstr[4] = ';';
switch (speed) {
case 50:
i = 0;
break;
case 75:
i = 8;
break;
case 110:
i = 16;
break;
case 133:
i = 14;
break;
case 150:
i = 32;
break;
case 200:
i = 40;
break;
case 300:
i = 48;
break;
case 600:
i = 56;
break;
case 1200:
i = 64;
break;
case 1800:
i = 72;
break;
case 2000:
i = 80;
break;
case 2400:
i = 88;
break;
case 3600:
i = 96;
break;
case 4800:
i = 104;
break;
case 9600:
i = 112;
break;
case 19200:
i = 120;
break;
default:
i = 128;
break;
}
#ifndef __32BIT__
/*
Hand-coded sprintf() again. - fdc.
*/
{
int x, j;
x = i;
i = 6;
tempstr[i++] = ';';
if ((j = x / 100) > 0)
tempstr[i++] = (char) (j + 48);
if ((j = (wherey % 100) / 10) > 0 ||
wherey > 99)
tempstr[i++] = (char) (j + 48);
if ((j = wherey % 10) > 0 ||
wherey > 9)
tempstr[i++] = (char) (j + 48);
tempstr[i++] = ';';
if ((j = x / 100) > 0)
tempstr[i++] = (char) (j + 48);
if ((j = (wherey % 100) / 10) > 0 ||
wherey > 99)
tempstr[i++] = (char) (j + 48);
if ((j = wherey % 10) > 0 ||
wherey > 9)
tempstr[i++] = (char) (j + 48);
tempstr[i++] = ';';
tempstr[i++] = '1';
tempstr[i++] = ';';
tempstr[i++] = '0';
tempstr[i++] = 'x';
tempstr[i++] = '\0';
}
#else
sprintf(&tempstr[6], ";%d;%d;1;0x", i, i);
#endif /* __32BIT__ */
sendescseq(tempstr);
break;
case 'm': /* Select Graphic Rendition (SGR) */
case '}': /* (Why this?) */
for (j = 1; j <= k; ++j) /* Go thru all Pn's */
switch ((pn[j])) { /* This one... */
case 0: /* Set all attributes to normal */
attribute = defaultattribute;
attrib.blinking = FALSE;
attrib.bold = FALSE;
attrib.invisible = FALSE;
attrib.underlined = FALSE;
attrib.reversed = FALSE;
break;
case 1: /* Turn on BOLD */
/* No colors involved. */
if (attrib.bold) /* Already bold? */
break;
attribute ^= 8; /* No, flip the bit. */
attrib.bold = TRUE; /* Remember */
break;
case 4: /* Turn on UNDERLINE */
/* Simulated by color */
if (attrib.underlined)
break;
attrib.underlined = TRUE;
#ifdef COMMENT
attribute = (attribute & (unsigned) 0x80) |
(colorunderline & 0x7F);
#else
attribute = colorunderline;
if (attrib.bold) /* If currently bold */
attribute ^= 0x08; /* flip bold bit */
if (attrib.blinking) /* If blinking */
attribute ^= 0x80; /* flip blink bit */
#endif /* COMMENT */
if (attrib.reversed)
attribute = swapcolors(attribute);
break;
case 5: /* Turn on BLINK */
/* Simulated by background intensity) */
if (attrib.blinking)
break;
attrib.blinking = TRUE;
attribute ^= (unsigned) 0x80;
break;
case 7: /* Turn on REVERSE VIDEO */
if (attrib.reversed)
break;
attrib.reversed = TRUE;
attribute = swapcolors(attribute);
break;
case 8: /* Turn on INVISIBLE */
attrib.invisible = TRUE; /* (see wrtch) */
break;
/* 22-27 are VT220 extensions. */
case 22: /* Turn BOLD Off */
if (!attrib.bold)
break;
attrib.bold = FALSE;
attribute ^= 8;
break;
case 24: /* Turn UNDERLINE Off */
if (!attrib.underlined)
break;
attrib.underlined = FALSE;
/* Go back to normal coloring */
#ifdef COMMENT
attribute = (attribute & (unsigned)0x80) |
(colornormal & 0x7F);
#else
attribute = defaultattribute;
if (attrib.bold) /* If currently bold */
attribute ^= 0x08; /* flip bold bit */
if (attrib.blinking) /* If blinking */
attribute ^= 0x80; /* flip blink bit */
#endif /* COMMENT */
if (attrib.reversed)
attribute = swapcolors(attribute);
break;
case 25: /* Turn BLINK Off */
if (!attrib.blinking)
break;
attrib.blinking = FALSE;
attribute ^= (unsigned)0x80;
break;
case 27: /* Turn REVERSE VIDEO Off */
if (!attrib.reversed)
break;
attrib.reversed = FALSE;
attribute = swapcolors(attribute);
break;
case 28:/* Turn INVISIBLE Off */
attrib.invisible = FALSE;
break;
case 30: /* Colors */
case 31:
case 32:
case 33:
case 34:
case 35:
case 36:
case 37:
/* Select foreground color */
if (decscnm) {
i = (attribute & 0x8F);
l = sgrcols[pn[j] - 30];
attribute = (i | ((l << 4)));
} else {
i = (attribute & 0xF8);
attribute = (i | sgrcols[pn[j] - 30]);
}
break;
case 40:
case 41:
case 42:
case 43:
case 44:
case 45:
case 46:
case 47:
/* Select background color */
if (!decscnm) {
i = (attribute & 0x8F);
l = sgrcols[pn[j] - 40];
attribute = (i | ((l << 4)));
} else {
i = (attribute & 0xF8);
attribute = (i | sgrcols[pn[j] - 40]);
}
break;
default:
break;
}
break;
case 'r': /* Set margin (scrolling region) */
if ((k < 2) || (pn[2] == 0))
pn[2] = ysize;
if (pn[1] == 0)
pn[1] = 1;
if ((pn[1] > 0) &&
(pn[1] < pn[2]) &&
(pn[2] <= ysize)) {
setmargins(pn[1], pn[2]);
lgotoxy(1, relcursor ? margintop : 1);
}
break;
case 'J': /* Clear screen */
switch ((pn[1])) {
case 0: /* Clear to end of screen */
clreoscr_escape();
break;
case 1: /* Clear to beginning */
clrboscr_escape();
break;
case 2: /* Clear whole screen */
if (tt_type != TT_ANSI) { /* DEC ... */
int sx, sy;
sx = wherex; sy = wherey;
clrscreen(); /* Cursor does not move */
lgotoxy(sx,sy);
} else { /* ANSI homes the cursor */
clrscreen();
}
break;
default:
break;
}
break;
case 'K': /* Clear line */
switch ((pn[1])) {
case 0: /* Clear to end of line */
clrtoeoln();
break;
case 1: /* Clear to beginning */
clrbol_escape();
break;
case 2: /* Clear whole cursor line */
clrline_escape();
break;
default:
break;
}
break;
case 'L': /* Insert lines */
for (i = 1; i <= pn[1]; ++i)
scroll(DOWNWARD, wherey - 1, marginbot - 1, 1);
break;
case 'M': /* Delete lines */
for (i = 1; i <= pn[1]; ++i)
scroll(UPWARD, wherey - 1, marginbot - 1, 1);
break;
case '@': /* Insert characters */
blankcell[0] = ' ';
blankcell[1] = attribute;
pn[1] *= dwl[wherey - 1] ? 2 : 1;
if (pn[1] > xsize + 1 - wherex)
pn[1] = xsize + 1 - wherex;
#ifdef OS2MOUSE
os2_mousehide() ;
#endif /* OS2MOUSE */
VioScrollRt(wherey - 1,
wherex - 1,
wherey - 1,
xsize - 1,
pn[1],
blankcell,
0
);
#ifdef OS2MOUSE
os2_mouseshow() ;
#endif /* OS2MOUSE */
break;
case 'P': /* DeleteChar */
blankcell[0] = ' ';
blankcell[1] = attribute;
pn[1] *= dwl[wherey - 1] ? 2 : 1;
if (pn[1] > xsize + 1 - wherex)
pn[1] = xsize + 1 - wherex;
#ifdef OS2MOUSE
os2_mousehide() ;
#endif /* OS2MOUSE */
VioScrollLf(wherey - 1,
wherex - 1,
wherey - 1,
xsize - 1,
pn[1],
blankcell,
0
);
#ifdef OS2MOUSE
os2_mouseshow() ;
#endif /* OS2MOUSE */
break;
default:
break;
}
}
break;
}
} /* Left square bracket */
break;
case '7': /* Save cursor position and attributes */
savecurpos(1);
break;
case '8': /* Restore Cursor Position and attributes */
restorecurpos(1);
break;
case 'A':
if (tt_type == TT_VT52) /* VT52 control */
cursorup();
break;
case 'B':
if (tt_type == TT_VT52) /* VT52 control */
cursordown();
break;
case 'C':
if (tt_type == TT_VT52) /* VT52 control */
cursorright();
break;
case 'D':
if (tt_type == TT_VT52) /* VT52 control */
cursorleft();
else { /* Index */
if (wherey == marginbot) {
toplinetocyclicbuffer(); /* Save in rollback buffer */
scroll(UPWARD, margintop - 1, marginbot - 1, 1);
} else
cursordown();
}
break;
case 'E': /* Next Line */
wrtch(13);
wrtch(10);
break;
case 'F':
if (tt_type == TT_VT52) /* VT52 control */
vt52graphics = TRUE;
break;
case 'G':
if (tt_type == TT_VT52) /* VT52 control */
vt52graphics = FALSE;
break;
case 'H':
if (tt_type >= TT_VT100) {
/* Set Tab Stop */
htab[wherex] = 'T';
}
/* Set Tab Stop */
else
lgotoxy(1, 1);
/* VT52 control */
break;
case 'I': /* Reverse Linefeed, VT52 */
case 'M': /* Reverse Index, VT102 */
if ((tt_type == TT_VT52 && achar == 'I') ||
(tt_type >= TT_VT100 && achar == 'M')) {
if (margintop == wherey) /* "==", not ">="! - fdc */
scroll(DOWNWARD, margintop - 1, marginbot - 1, 1);
else
cursorup();
break;
}
break;
case 'J':
if (tt_type == TT_VT52)
/* VT52 control */
clreoscr_escape();
break;
case 'K':
if (tt_type == TT_VT52)
/* VT52 control */
clrtoeoln();
break;
#ifdef __32BIT__
/*
VT52 printer controls. For now, autoprint is treated like transparent
print. 32-bit version only, to avoid stack overflows in 16-bit version.
Edit 190, fdc.
*/
case 'V': /* Print cursor line */
if (tt_type == TT_VT52) /* VT52 control */
prtscreen(wherey,wherey);
break;
case ']': /* Print screen */
if (tt_type == TT_VT52) /* VT52 control */
prtscreen(1,ysize);
break;
case 'W': /* Transparent print on */
case '^': /* Autoprint on */
if (tt_type == TT_VT52) /* VT52 control */
turnonprinter = xprint = TRUE;
break;
case 'X': /* Transparent print off */
case '_': /* Autoprint off */
if (tt_type == TT_VT52) { /* VT52 control */
turnoffprinter = TRUE;
xprint = FALSE;
}
break;
#endif /* __32BIT__ */
case 'Y': /* Direct cursor address */
if (tt_type == TT_VT52) { /* VT52 control */
achar = (escnext<=esclast)?escbuffer[escnext++]:0;
row = achar - 31;
achar = (escnext<=esclast)?escbuffer[escnext++]:0;
column = achar - 31;
lgotoxy(column, row);
}
break;
case 'Z': /* DECID - Identify Terminal */
if (tt_type >= 0 && tt_type <= max_tt) {
if (!network) msleep(100);
sendescseq(tt_info[tt_type].x_id);
}
break;
case 'c':
/* Reset */
doreset(1);
break;
case '#':
/* Esc # sequence */
achar = (escnext<=esclast)?escbuffer[escnext++]:0;
switch (achar) {
case '3':
decdwl_escape(TRUE);
break;
case '4':
decdwl_escape(TRUE);
break;
case '5':
decdwl_escape(FALSE);
break;
case '6':
decdwl_escape(TRUE);
break;
case '8': /* Self Test */
{
char cell[2];
cell[0] = 'E';
cell[1] = 7;
/* Self Test */
#ifdef OS2MOUSE
os2_mousehide() ;
#endif /* OS2MOUSE */
VioWrtNCell(cell, 1920, 0, 0, 0);
#ifdef OS2MOUSE
os2_mouseshow() ;
#endif
setmargins(1, ysize);
lgotoxy(1, 1);
}
break;
default:
break;
} /* Esc # sequence */
break;
case '=': /* Application mode */
tt_keypad = TTK_APPL;
break;
case '>': /* Numeric mode */
tt_keypad = TTK_NORM;
break;
case '<': /* Enter ANSI mode */
/* VT52 control */
if (tt_type == TT_VT52)
tt_type = my_tt_type;
break;
case '(':
achar = (escnext<=esclast)?escbuffer[escnext++]:0;
g0 = achar;
break;
case ')':
achar = (escnext<=esclast)?escbuffer[escnext++]:0;
g1 = achar;
break;
case SP:
achar = (escnext<=esclast)?escbuffer[escnext++]:0;
if (tt_type >= TT_VT220) {
if (achar == 'F') /* S7C1T */
send_c1 = FALSE;
else if (achar == 'G') /* S8C1T */
if (c1controls && (cmask == 0xFF))
send_c1 = TRUE;
}
break;
default:
if (achar == 12) { /* ESC Ctrl-L */
lgotoxy(1, 1);
clrscreen();
}
break;
} /* First Level Case */
} /* Screen escape sequences */
/* Host said to turn off the printer. */
if (turnoffprinter) {
printeroff();
turnoffprinter = FALSE;
}
/* If printer is on, print this escape sequence. */
if (printon) {
fprintf(lst, "%c", 27);
if (esclast > 0) {
/* print esc sequence */
for (i = 1; i <= esclast; ++i)
fprintf(lst, "%c", escbuffer[i]);
}
}
/*
If we just got a "printer on" directive, turn on the printer now.
This way, the "printer on" directive itself is not printed.
*/
if (turnonprinter) { /* Last command was "printer on" */
printeron();
turnonprinter = FALSE;
}
}
/* ================================================================== */
/* VT100 - emulate a DEC VT terminal writing a character */
/* ================================================================== */
static void
vt100(unsigned char vtch) {
int i, j;
char *s, str[2];
if (tt_type == TT_NONE) {
wrtch(vtch);
return;
} else if (screenon) {
if (vtch < 32) { /* Control Character */
achar = vtch; /* Let the rest of this module see the value */
switch (achar) {
case FF: /* Formfeed */
if (tt_type == TT_ANSI) {
clrscreen();
break;
} /* else fall thru... */
case LF: /* Linefeed */
case 11: /* Vertical tab */
wrtch((char) LF);
break;
case CR: /* Carriage return */
wrtch((char) achar);
break;
#ifdef COMMENT
/* This is just plain wrong. */
case 27: /* ESC */
vtescape();
break;
#endif /* COMMENT */
case 14: /* SO */
if (tt_type != TT_ANSI) /* "ANSI music" protection... */
g0g1 = &g1;
break;
case 15: /* SI */
if (tt_type != TT_ANSI) /* Ditto, gag... */
g0g1 = &g0;
break;
case 8: /* BS */
wrtch((char) achar);
break;
case 7: /* BEL */
bleep();
break;
case 5: /* ENQ */
if (tt_answer) {
int x;
x = (tt_pacing > -1) ? tt_pacing : 50;
s = answerback;
while (*s) {
if (x > 0 && !network) msleep(x);
sendchar(*s++);
}
}
break;
case 9: /* Horizontal tab */
j = dwl[wherey - 1] ? 2 : 1;
i = wherex;
if (j == 2 && htab[(i - 1) / j + 1] == 'T') {
i++;
cursorright();
}
if (i < xsize)
do {
i++;
cursorright();
} while ((htab[(i - 1) / j + 1] != 'T') &&
(i <= xsize - j));
break;
default: /* ignore it */
break;
}
/* End of Control Character */
} else {
if (vtch != DEL) { /* Normal character. */
if (tt_type >= TT_VT100) {
if (*g0g1 == 'A' && tcsr == FC_USASCII && vtch == 35) {
/* UK ISO 646 character-set, # = Pound Sterling Sign */
vtch = 156;
} else if ((*g0g1 == '0') && /* VT graphics set */
(95 <= vtch) && (vtch <= 126)) {
literal = TRUE;
vtch = graphicset[vtch - 95];
}
} else {
if (vt52graphics && (95 <= vtch) && (vtch <= 126)) {
literal = TRUE;
vtch = graphicset[vtch - 95];
}
}
/* On the right margin? */
if (wherex != (dwl[wherey - 1] ? xsize - 1 : xsize)) {
wrtch(vtch); /* Not on right margin */
if (dwl[wherey-1]) /* Write the character */
wrtch(' '); /* Handle double-width characters */
wrapit = FALSE;
} else { /* On right margin. */
if (wrapit) { /* Time to wrap? */
if (marginbot <= wherey) { /* Scroll if bottom line */
toplinetocyclicbuffer(); /* Save in rollback buf */
scroll(UPWARD, margintop - 1, marginbot - 1, 1);
lgotoxy(1, wherey); /* Go to new bottom row */
} else /* Not bottom line, just wrap. */
lgotoxy(1, wherey + 1); /* Go to next row */
wrtch(vtch); /* Now write the character */
if (dwl[wherey - 1]) /* Take care of double-width */
wrtch(' ');
wrapit = FALSE; /* Remember wrapping is done */
} else { /* Not time to wrap */
i = dwl[wherey - 1] ? 2 : 1; /* Write the char */
str[0] = vtch;
str[1] = ' ';
#ifdef OS2MOUSE
os2_mousehide() ;
#endif /* OS2MOUSE */
VioWrtCharStrAtt(&vtch, i,
wherey - 1,
xsize - i,
&attribute,
0);
#ifdef OS2MOUSE
os2_mouseshow() ;
#endif
literal = FALSE;
if ((tt_wrap && !deccolm)) /* If TERM WRAP ON */
wrapit = TRUE; /* need to wrap next time */
}
}
} /* Normal char */
}
}
if (printon && (vtch != 27))
fprintf(lst, "%c", vtch);
}
/* Save current status of screen */
void
savescreen(ascreen *scrn, int wherex, int wherey) {
USHORT n = xsize * (ysize + 1) * 2;
debug(F101,"x_save scrn","",scrn);
debug(F101,"x_save wherex","",wherex);
debug(F101,"x_save wherey","",wherey);
scrn->ox = wherex;
scrn->oy = wherey;
scrn->att = attribute;
#ifdef OS2MOUSE
os2_mousehide() ;
#endif
VioReadCellStr((char *) (scrn->scrncpy), &n, 0, 0, 0);
#ifdef OS2MOUSE
os2_mouseshow() ;
#endif
}
/* Restore a saved screen */
restorescreen(ascreen *scrn) {
movetoscreen(scrn->scrncpy, 1, 1, xsize * (ysize + 1) * 2);
attribute = scrn->att;
wherey = scrn->oy;
wherex = scrn->ox;
debug(F101,"x_rest scrn","",scrn);
debug(F101,"x_rest wherex","",wherex);
debug(F101,"x_rest wherey","",wherey);
lgotoxy(wherex, wherey);
}
#ifdef M_I286
/* Avoid 16-bit stack overflows */
#define logchar(c) zchout(ZSFILE,c)
#else
static void
logchar(char c) {
if (zchout(ZSFILE,c) < 0) {
conoll("");
conoll("ERROR WRITING SESSION LOG, LOG CLOSED!");
seslog = 0;
}
}
#endif /* M_I286 */
static int
sendchar(CHAR c) {
#ifndef NOTTOCI
/*
NOTE: ttoci() uses an ioctl() that has been observed to hang, inexplicably,
on some systems (e.g. high-end PS/2s that haven't been rebooted in a month,
and have been going back and forth between SLIP and Kermit.) In fact,
this was reported only once, and rebooting the system made the problem go
away.
A NEWER NOTE: As of 8 May 94, ttoci() uses DosWrite, but first does an
ioctl() to make sure the connection is OK. Hopefully, this combines the
the benefits of both methods: failure detection, buffering, flow control.
*/
int x, i = 0;
long wait = 0;
/*
Send a character to the serial line in immediate mode, checking to avoid
overwriting a character already waiting to be sent. If we fail, e.g. because
FLOW is RTS/CTS and CTS is not on (like when modems are retraining), enter
a retry loop up to the timeout limit.
*/
x = ttoci(dopar(c)); /* Try to send the character */
if (x) { /* Transmission error */
KEY k;
int w, oldw;
debug(F101,"sendchar blocked char","",c);
oldw = 0; /* For updating status line once/sec */
save_status_line(); /* Save current status line */
do {
w = (waittime - wait) / 1000L;
if (w != oldw) { /* Countdown timer in status line */
oldw = w;
sprintf(usertext, " TRANSMISSION BLOCKED: %d",w);
helptext[0] = '\0';
line25();
}
if (conchk() > 0) { /* Is a keystroke waiting? */
k = congks(0); /* Read it */
k = keymap[k]; /* Get value from keymap */
debug(F101,"BLOCKED key","",k);
if (k == (F_KVERB | K_EXIT)) { /* Let them escape back... */
active = FALSE; /* this way */
return 0;
} else if (k == escape) { /* or this way */
k = congks(0);
k = keymap[k];
if ((k == 'c') || (k == 'C') || (k == 3)) {
active = FALSE;
return 0;
} else bleep();
} else bleep(); /* Anything else, just beep. */
}
DosSleep(INTERVAL); /* Sleep a bit */
wait += INTERVAL; /* Go round till limit exhausted */
x = ttoci(dopar(c)); /* Try to send again */
} while ((x != 0) && (wait < waittime));
restore_status_line();
}
if (wait >= waittime) { /* Go back to prompt if we failed */
while (conchk() > 0) congks(0); /* Flush any remaining typeahead */
active = FALSE;
if (network)
sprintf(termessage,
"Can't transmit to network, error status: %d\n", x);
else {
sprintf(termessage,"Serial port blocked%s%s%s%s%s%s%s%s\n",
( x & TX_WAITING_FOR_CTS )
? "\nTx waiting for CTS to be turned ON" : "",
( x & TX_WAITING_FOR_DSR )
? "\nTx waiting for DSR to be turned ON" : "",
( x & TX_WAITING_FOR_DCD )
? "\nTx waiting for DCD to be turned ON" : "",
( x & TX_WAITING_FOR_XON )
? "\nTx waiting because XOFF received" : "",
( x & TX_WAITING_TO_SEND_XON )
? "\nTx waiting because XOFF transmitted" : "",
( x & TX_WAITING_WHILE_BREAK_ON )
? "\nTx because BREAK is being transmitted" : "",
( x & TX_WAITING_TO_SEND_IMM )
? "\nCharacter waiting to transmit immediately" : "",
( x & RX_WAITING_FOR_DSR )
? "\nRx waiting for DSR to be turned ON" : "" ) ;
}
}
#else /* NOTTOCI is defined */
/*
On the other hand, using DosWrite() (via ttoc()) makes C-Kermit hang
if modem signals are not just right, plus we can't handle CTS blockage
this way, nor do we get the OS/2 error code.
*/
if (ttoc(dopar(c)) < 0) {
active = FALSE;
sprintf(termessage,"Can't transmit to %s\n",
network ? "network" : "serial port");
}
#endif /* NOTTOCI */
return 0;
}
static int
sendcharduplex(unsigned char key) {
unsigned char csave;
key &= cmdmsk; /* Do any requested masking */
csave = key;
if (outesc == ES_NORMAL) { /* If not inside escape seq.. */
/* Translate character sets */
if (sxo) key = (*sxo)(key); /* Local to intermediate. */
if (rxo) key = (*rxo)(key); /* Intermediate to remote. */
}
if (oskipesc) outesc = chkaes(outesc, key);
/* Check output (key) escape sequence status */
if (sosi) { /* Shift-In/Out selected? */
if (cmask == 0177) { /* In 7-bit environment? */
if (key & 0200) { /* 8-bit character? */
if (outshift == 0) { /* If not shifted, */
sendchar(SO); /* shift. */
outshift = 1;
}
} else {
if (outshift == 1) { /* 7-bit character */
sendchar(SI); /* If shifted, */
outshift = 0; /* unshift. */
}
}
}
if (key == SO) outshift = 1; /* User typed SO */
if (key == SI) outshift = 0; /* User typed SI */
}
key &= cmask; /* Apply Kermit-to-host mask now. */
if (key == '\015') { /* Handle TERMINAL NEWLINE */
int stuff = -1;
if (tnlm) { /* TERMINAL NEWLINE ON */
stuff = LF; /* Stuff LF */
#ifdef TNCODE
} else if (network && /* TELNET NEWLINE ON/OFF/RAW */
(ttnproto == NP_TELNET) &&
(tn_nlm != TNL_CR)) {
stuff = (tn_nlm == TNL_CRLF) ? LF : NUL;
#endif /* TNCODE */
}
if (stuff > -1) {
sendchar(dopar('\015')); /* Send the CR */
if (duplex) { /* If local echoing... */
cwrite('\015'); /* echo to screen */
if (seslog) /* and if logging */
logchar(csave); /* log it */
}
key = stuff;
csave = key;
} else if (tt_crd && duplex) { /* CR-DISPLAY CRLF & local echo */
cwrite(CR); /* so we have to echo CRLF locally */
if (seslog)
logchar(csave);
csave = LF;
key = CR; /* ... but only send a CR */
}
}
#ifdef TNCODE
/* If user types the 0xff character (TELNET IAC), it must be doubled. */
else
if (dopar(key) == IAC && network && ttnproto == NP_TELNET)
sendchar(IAC); /* and the other one just below. */
#endif /* TNCODE */
sendchar(dopar(key));
if (duplex) {
cwrite(csave);
if (seslog) logchar(csave);
}
}
/* S E N D E S C S E Q -- Send ESC followed by the given string */
/*
Used for sending host-requested reports, as well as for sending
F-keys, arrow keys, etc. Translation, shifting, etc, are not issues here.
*/
static int
sendescseq(CHAR *s) {
char c;
int pause;
pause = (tt_pacing > -1) ? tt_pacing : 50;
/* Handle 7-bit vs 8-bit escape sequences...*/
if (send_c1 && ((*s == '[' || *s == 'O'))) /* 8-bit C1 controls... */
c = (*s++ ^ (CHAR) 0x40) | (CHAR) 0x80;
else /* Or 7-bit escape sequences... */
c = ESC;
sendchar(c);
if (duplex) { /* Half duplex, echo it to the */
cwrite(c); /* console too ... */
if (seslog) logchar(c); /* and maybe log it in session log */
}
for ( ; *s; s++ ) { /* Same deal for the rest */
if (!network) msleep(pause); /* But sleep between each character */
sendchar(*s); /* Otherwise sendchars can overrun */
if (duplex) { /* unbuffered UARTs... */
cwrite(*s);
if (seslog) logchar(*s);
}
}
}
static void /* Push from CONNECT mode to OS/2 */
os2push() {
VIOMODEINFO mi;
savescreen(&savedscreen,wherex,wherey);
mi.cb = sizeof(mi);
VioGetMode(&mi, 0);
concooked();
clearscreen(1, colorcmd);
restorecursormode();
puts("Enter EXIT to return to C-Kermit.");
zshcmd("");
conraw();
connoi();
VioSetMode(&mi, 0);
setborder(); /* Put back CONNECT screen border */
setcursormode();
restorescreen(&savedscreen);
if (cursorena) /* If cursor is enabled */
newcursor(); /* turn it on explicitly, in case... */
}
void
os2debugoff() { /* Turn off debugging from outside */
debug(F100,"os2debugoff","",0);
attribute = defaultattribute;
}
void
os2bold() { /* Toggle boldness from the outside */
tn_bold = 1 - tn_bold;
}
static void /* Toggle session debugging */
flipdebug() {
if (debses) {
attribute = defaultattribute; /* Back to normal coloring */
debses = 0; /* Turn off session debug flag */
} else {
debses = 1; /* Turn on session debug flag */
}
if (!roll.flag && status_saved < 0)
ipadl25();
}
/* Initialize key map */
void
keymapinit() {
keymap[0x103] = 0x00; /* Ctrl-2 = NUL */
keymap[0x200 | DEL ] = DEL; /* Ctrl-Backspace = DEL */
keymap[0x200 | ' ' ] = 0x00; /* Ctrl-Space = NUL */
keymap[0x200 | '+' ] = '+'; /* Predefine ambiguous keypad keys */
keymap[0x200 | '-' ] = '-';
keymap[0x200 | '*' ] = '*';
keymap[0x200 | '/' ] = '/';
keymap[0x200 | '\r'] = '\r';
keymap[0x200 | '\n'] = '\n';
keymap[0x200 | '.' ] = '.';
keymap[0x200 | ',' ] = ',';
keymap[0x200 | '0' ] = '0';
keymap[0x200 | '1' ] = '1';
keymap[0x200 | '2' ] = '2';
keymap[0x200 | '3' ] = '3';
keymap[0x200 | '4' ] = '4';
keymap[0x200 | '5' ] = '5';
keymap[0x200 | '6' ] = '6';
keymap[0x200 | '7' ] = '7';
keymap[0x200 | '8' ] = '8';
keymap[0x200 | '9' ] = '9';
keymap[0x109] = 9; /* Tab-Key = Tab */
keymap[0x10f] = 8; /* Shift-Tab = Backtab = Backspace */
keymap[0x11B] = 27; /* Shift-Escape = Escape */
keymap[0x10f] = 8; /* Backtab = Backspace */
keymap[270] = 8; /* Alt-Backspace = Backspace */
keymap[0x153] = 127; /* Keypad Del sends DEL */
keymap[595] = 127; /* Gray Delete send DEL */
#ifndef NOKVERBS
keymap[511] = F_KVERB | K_HOLDSCRN; /* Hold Screen */
keymap[767] = F_KVERB | K_HOLDSCRN; /* Hold Screen */
/* Arrow keys */
keymap[584] = F_KVERB | K_UPARR; /* Up Arrow Gray */
keymap[328] = F_KVERB | K_UPARR; /* Up Arrow Numeric */
keymap[587] = F_KVERB | K_LFARR; /* Left Arrow Gray */
keymap[331] = F_KVERB | K_LFARR; /* Left Arrow Numeric*/
keymap[589] = F_KVERB | K_RTARR; /* Right Arrow Gray */
keymap[333] = F_KVERB | K_RTARR; /* Right Arrow Numeric */
keymap[592] = F_KVERB | K_DNARR; /* Down Arrow Gray */
keymap[336] = F_KVERB | K_DNARR; /* Down Arrow Numeric */
/* Screen scroll */
keymap[585] = F_KVERB | K_UPSCN; /* Page Up: Up one screen */
keymap[329] = F_KVERB | K_UPSCN; /* PgUp: Up one screen */
keymap[644] = F_KVERB | K_UPONE; /* Ctrl Page Up: Up one line */
keymap[388] = F_KVERB | K_UPONE; /* Ctrl PgUp: Up one line */
keymap[593] = F_KVERB | K_DNSCN; /* Page Down: Down one screen */
keymap[337] = F_KVERB | K_DNSCN; /* PgDn: Down one screen */
keymap[630] = F_KVERB | K_DNONE; /* Ctrl Page Down: Down one line */
keymap[374] = F_KVERB | K_DNONE; /* Ctrl PgDn: Down one line */
keymap[583] = F_KVERB | K_HOMSCN; /* Gray Home: Top of buffer */
keymap[327] = F_KVERB | K_HOMSCN; /* Numeric Home: Top of buffer */
keymap[591] = F_KVERB | K_ENDSCN; /* Gray End: Bottom of buffer */
keymap[335] = F_KVERB | K_ENDSCN; /* Numeric End: Bottom of buffer */
/* Numeric keypad */
keymap[315] = F_KVERB | K_PF1; /* F1 = DEC PF1 */
keymap[316] = F_KVERB | K_PF2; /* F2 = DEC PF2 */
keymap[317] = F_KVERB | K_PF3; /* F3 = DEC PF3 */
keymap[318] = F_KVERB | K_PF4; /* F4 = DEC PF4 */
keymap[385] = F_KVERB | K_KP0; /* Alt-0, Top Rank = DEC Keypad 0 */
keymap[376] = F_KVERB | K_KP1; /* Alt-1, Top Rank = DEC Keypad 1 */
keymap[377] = F_KVERB | K_KP2; /* Alt-2, Top Rank = DEC Keypad 2 */
keymap[378] = F_KVERB | K_KP3; /* Alt-3, Top Rank = DEC Keypad 3 */
keymap[379] = F_KVERB | K_KP4; /* Alt-4, Top Rank = DEC Keypad 4 */
keymap[380] = F_KVERB | K_KP5; /* Alt-5, Top Rank = DEC Keypad 5 */
keymap[381] = F_KVERB | K_KP6; /* Alt-6, Top Rank = DEC Keypad 6 */
keymap[382] = F_KVERB | K_KP7; /* Alt-7, Top Rank = DEC Keypad 7 */
keymap[383] = F_KVERB | K_KP8; /* Alt-8, Top Rank = DEC Keypad 8 */
keymap[384] = F_KVERB | K_KP9; /* Alt-9, Top Rank = DEC Keypad 9 */
keymap[386] = F_KVERB | K_KPMINUS; /* Alt -, Top Rank = DEC Keypad - */
keymap[307] = F_KVERB | K_KPCOMA; /* Alt-Comma = DEC Keypad comma */
keymap[308] = F_KVERB | K_KPDOT; /* Alt-Period = DEC Keypad period */
keymap[284] = F_KVERB | K_KPENTER; /* Alt-Enter = DEC Keypad Enter */
/* The compose key */
keymap[302] = F_KVERB | K_COMPOSE; /* Alt-c, Compose */
/* Kermit action verbs */
/* Default mappings designed so key names are valid on all systems */
keymap[275] = F_KVERB | K_RESET; /* Alt-R, Reset emulator */
keymap[387] = F_KVERB | K_RESET; /* Alt-=, Reset emulator */
keymap[301] = F_KVERB | K_EXIT; /* Alt-x, Exit emulator */
keymap[304] = F_KVERB | K_BREAK; /* Alt-b, Send BREAK */
keymap[294] = F_KVERB | K_LBREAK; /* Alt-l, Send Long BREAK */
keymap[278] = F_KVERB | K_HANGUP; /* Alt-u, Hangup connection */
keymap[281] = F_KVERB | K_DUMP; /* Alt-p, Print/Dump screen */
keymap[370] = F_KVERB | K_PRTSCN; /* Ctrl-PrintScreen, Toggle printing */
keymap[415] = F_KVERB | K_PRINTFF; /* Alt-End, Print FF */
keymap[417] = F_KVERB | K_DOS; /* Alt-Page Down, Push to OS/2 */
keymap[303] = F_KVERB | K_FLIPSCN; /* Alt-v, video toggle */
keymap[288] = F_KVERB | K_DEBUG; /* Alt-d, Toggle debugging */
keymap[291] = F_KVERB | K_HELP; /* Alt-h, Help */
keymap[510] = F_KVERB | K_IGNORE; /* Num Lock, don't beep */
keymap[766] = F_KVERB | K_IGNORE; /* Num Lock, don't beep */
#endif /* NOKVERBS */
}
#ifndef NOKVERBS
VOID
keynaminit() {
/* These names apply only to US keyboards. */
int i;
for (i = 0; i < 512; i++)
keynam[i] = NULL;
keynam[259 - 256] = "Ctrl-2";
keynam[265 - 256] = "Tab";
keynam[270 - 256] = "Alt-Backspace";
keynam[271 - 256] = "Shift-Tab";
keynam[272 - 256] = "Alt-q";
keynam[273 - 256] = "Alt-w";
keynam[274 - 256] = "Alt-e";
keynam[275 - 256] = "Alt-r";
keynam[276 - 256] = "Alt-t";
keynam[277 - 256] = "Alt-y";
keynam[278 - 256] = "Alt-u";
keynam[279 - 256] = "Alt-i";
keynam[280 - 256] = "Alt-o";
keynam[281 - 256] = "Alt-p";
keynam[282 - 256] = "Alt-[";
keynam[283 - 256] = "Shift-Esc"; /* Fullscreen sessions only! */
keynam[284 - 256] = "Alt-Enter";
keynam[286 - 256] = "Alt-a";
keynam[287 - 256] = "Alt-s";
keynam[288 - 256] = "Alt-d";
keynam[289 - 256] = "Alt-f";
keynam[290 - 256] = "Alt-g";
keynam[291 - 256] = "Alt-h";
keynam[292 - 256] = "Alt-j";
keynam[293 - 256] = "Alt-k";
keynam[294 - 256] = "Alt-l";
keynam[295 - 256] = "Alt-;";
keynam[296 - 256] = "Alt-'";
keynam[297 - 256] = "Alt-grave";
keynam[299 - 256] = "Alt-\\";
keynam[300 - 256] = "Alt-z";
keynam[301 - 256] = "Alt-x";
keynam[302 - 256] = "Alt-c";
keynam[303 - 256] = "Alt-v";
keynam[304 - 256] = "Alt-b";
keynam[305 - 256] = "Alt-n";
keynam[306 - 256] = "Alt-m";
keynam[307 - 256] = "Alt-,";
keynam[308 - 256] = "Alt-.";
keynam[309 - 256] = "Alt-?";
keynam[311 - 256] = "Alt-Kp *";
keynam[315 - 256] = "F1";
keynam[316 - 256] = "F2";
keynam[317 - 256] = "F3";
keynam[318 - 256] = "F4";
keynam[319 - 256] = "F5";
keynam[320 - 256] = "F6";
keynam[321 - 256] = "F7";
keynam[322 - 256] = "F8";
keynam[323 - 256] = "F9";
keynam[324 - 256] = "F10";
keynam[327 - 256] = "Kp Home";
keynam[329 - 256] = "PgUp";
keynam[330 - 256] = "Alt-Kp -";
keynam[334 - 256] = "Alt-Kp +";
keynam[335 - 256] = "Kp End";
keynam[337 - 256] = "PgDn";
keynam[339 - 256] = "Kp Del";
keynam[350 - 256] = "Ctrl-F1";
keynam[351 - 256] = "Ctrl-F2";
keynam[352 - 256] = "Ctrl-F3";
keynam[353 - 256] = "Ctrl-F4";
keynam[354 - 256] = "Ctrl-F5";
keynam[355 - 256] = "Ctrl-F6";
keynam[356 - 256] = "Ctrl-F7";
keynam[357 - 256] = "Ctrl-F8";
keynam[358 - 256] = "Ctrl-F9";
keynam[359 - 256] = "Ctrl-F10";
keynam[360 - 256] = "Alt-F1";
keynam[361 - 256] = "Alt-F2";
keynam[362 - 256] = "Alt-F3";
keynam[363 - 256] = "Alt-F4";
keynam[364 - 256] = "Alt-F5";
keynam[365 - 256] = "Alt-F6";
keynam[366 - 256] = "Alt-F7";
keynam[367 - 256] = "Alt-F8";
keynam[368 - 256] = "Alt-F9";
keynam[369 - 256] = "Alt-F10";
keynam[370 - 256] = "Ctrl-Print Screen";
keynam[371 - 256] = "Ctrl-Kp 4";
keynam[372 - 256] = "Ctrl-Kp 6";
keynam[373 - 256] = "Ctrl-Kp 1";
keynam[373 - 256] = "Ctrl-Kp End";
keynam[374 - 256] = "Ctrl-Kp 4";
keynam[374 - 256] = "Ctrl-PgDn";
keynam[375 - 256] = "Ctrl-Kp 7";
keynam[375 - 256] = "Ctrl-Kp Home";
keynam[376 - 256] = "Alt-1";
keynam[377 - 256] = "Alt-2";
keynam[378 - 256] = "Alt-3";
keynam[379 - 256] = "Alt-4";
keynam[380 - 256] = "Alt-5";
keynam[381 - 256] = "Alt-6";
keynam[382 - 256] = "Alt-7";
keynam[383 - 256] = "Alt-8";
keynam[384 - 256] = "Alt-9";
keynam[385 - 256] = "Alt-0";
keynam[386 - 256] = "Alt-minus";
keynam[387 - 256] = "Alt-=";
keynam[388 - 256] = "Ctrl-PgUp";
keynam[389 - 256] = "F11";
keynam[390 - 256] = "F12";
keynam[393 - 256] = "Ctrl-F11";
keynam[394 - 256] = "Ctrl-F12";
keynam[395 - 256] = "Alt-F11";
keynam[396 - 256] = "Alt-F12";
keynam[397 - 256] = "Ctrl-Kp 8";
keynam[398 - 256] = "Ctrl-Kp -";
keynam[399 - 256] = "Ctrl-Kp 5";
keynam[400 - 256] = "Ctrl-Kp +";
keynam[401 - 256] = "Ctrl-Kp 2";
keynam[402 - 256] = "Ctrl-Kp 0";
keynam[403 - 256] = "Ctrl-Kp Del";
keynam[403 - 256] = "Ctrl-Kp Del";
keynam[404 - 256] = "Ctrl-Tab";
keynam[405 - 256] = "Ctrl-Kp /";
keynam[406 - 256] = "Ctrl-Kp *";
keynam[408 - 256] = "Alt-Up Arrow";
keynam[409 - 256] = "Alt-Page Up";
keynam[411 - 256] = "Alt-Left Arrow";
keynam[413 - 256] = "Alt-Right Arrow";
keynam[415 - 256] = "Alt-End";
keynam[416 - 256] = "Alt-Down Arrow";
keynam[417 - 256] = "Alt-Page Down";
keynam[418 - 256] = "Alt-Insert";
keynam[419 - 256] = "Alt-Delete";
keynam[420 - 256] = "Alt-Kp /";
keynam[421 - 256] = "Alt-Tab";
keynam[422 - 256] = "Alt-Kp Enter";
keynam[510 - 256] = "Num Lock";
keynam[510 - 256] = "Pause";
keynam[511 - 256] = "Scroll Lock";
keynam[522 - 256] = "Ctrl-Kp Enter";
keynam[583 - 256] = "Home";
keynam[585 - 256] = "Page Up";
keynam[591 - 256] = "End";
keynam[593 - 256] = "Page Down";
keynam[627 - 256] = "Ctrl-Left Arrow";
keynam[628 - 256] = "Ctrl-Right Arrow";
keynam[629 - 256] = "Ctrl-End";
keynam[630 - 256] = "Ctrl-Page Down";
keynam[631 - 256] = "Ctrl-Home";
keynam[639 - 256] = "Ctrl-Backspace";
keynam[644 - 256] = "Ctrl-Page Up";
keynam[653 - 256] = "Ctrl-Up Arrow";
keynam[657 - 256] = "Ctrl-Down Arrow";
keynam[658 - 256] = "Ctrl-Insert";
keynam[659 - 256] = "Ctrl-Delete";
keynam[766 - 256] = "Num Lock";
keynam[766 - 256] = "Pause";
keynam[767 - 256] = "Scroll Lock";
}
/* DEC F-key strings */
static char * fkeys[] = {
"[17~","[18~","[19~","[20~","[21~", /* F6 - F10 */
"[23~","[24~","[25~","[26~","[28~", /* F11 - F15 */
"[29~","[31~","[32~","[33~","[34~" /* F16 - F20 */
};
/* DEC Editing key strings */
static char * ekeys[] = {
"[1~", /* Find */
"[2~", /* Insert */
"[3~", /* Remove */
"[4~", /* Select */
"[5~", /* Previous Screen */
"[6~" /* Next Screen */
};
#ifdef NETCONN
#ifdef TCPSOCKET
do_tn_cmd(CHAR x) {
CHAR temp[3];
if (network && ttnproto == NP_TELNET) { /* TELNET */
temp[0] = (CHAR) IAC;
temp[1] = x;
temp[2] = NUL;
ttol((CHAR *)temp,2);
} else
bleep();
}
#endif /* TCPSOCKET */
#endif /* NETCONN */
/* D O K V E R B -- Execute a keyboard verb */
static void
dokverb(int k) { /* 'k' is the kverbs[] table index. */
int x;
char escbuf[10]; /* For building key escape sequences */
/*
Items are grouped according to function, and checked approximately
in order of how frequently they are used.
*/
k &= ~(F_KVERB); /* Clear KVERB flag */
if (k >= K_ACT_MIN && k <= K_ACT_MAX) {
switch (k) { /* Common Kermit actions first ... */
case K_EXIT: /* \Kexit: */
active = FALSE; return; /* Exit from terminal emulator */
case K_BREAK: /* \Kbreak */
ttsndb(); return; /* Send a BREAK */
case K_DOS: /* \Kdos or \Kos2 */
os2push(); return; /* Push to system */
case K_RESET: /* \Kreset */
doreset(1); return; /* Reset terminal emulator */
case K_HELP: /* \Khelp */
popuphelp(0); return; /* Pop-up help message */
case K_PRTSCN: /* \Kprtscn */
if (printon) { /* Toggle printer on/off */
xprint = FALSE; /* It's on, turn it off */
printeroff();
} else { /* vice versa ... */
printeron();
}
return;
case K_DUMP: /* \Kdump */
x = xprintff; xprintff = 0; /* Print/Dump current screen */
prtscreen(1,ysize);
xprintff = x; return;
case K_PRINTFF: /* \KprintFF - Print Form Feed */
printeron();
fprintf(lst,"%c",FF); /* Send formfeed */
printeroff();
return;
case K_HANGUP: /* \Khangup */
hangnow = 1; /* Hang up connection */
active = 0; /* and return to prompt. */
strcpy(termessage, "Hangup.\n");
return;
case K_NULL: /* \Knull */
sendcharduplex('\0'); return; /* Send a NUL */
case K_LBREAK: /* \Klbreak: */
ttsndlb(); return; /* Send a Long BREAK */
case K_DEBUG: /* \Kdebug */
flipdebug(); return; /* Toggle debugging */
case K_FLIPSCN: /* \KflipScn */
flipscreen(); return; /* Toggle video */
case K_HOLDSCRN: /* \KholdScrn */
save_status_line(); /* Save current status line */
strcpy(usertext,
" Scroll-Lock Press (almost) any key to unlock"
);
helptext[0] = exittext[0] = hostname[0] = NUL;
line25(); /* Make special status line */
congks(0); /* Wait for any keystroke */
restore_status_line(); /* Restore status line */
return;
case K_IGNORE: /* \Kignore */
return;
#ifdef NETCONN
#ifdef TCPSOCKET
case K_TN_AYT: /* TELNET Are You There */
do_tn_cmd((CHAR) AYT);
return;
case K_TN_IP: /* TELNET Interrupt Process */
do_tn_cmd((CHAR) IP);
return;
#endif /* TCPSOCKET */
#endif /* NETCONN */
default: /* None of the above */
return; /* Ignore this key and return. */
}
}
if (k >= K_ROLLMIN && k <= K_ROLLMAX) { /* Screen rollback... */
scrollback(k);
return;
}
if (k >= K_ARR_MIN && k <= K_ARR_MAX) { /* DEC arrow (cursor) keys */
if (tt_type >= TT_VT100)
sprintf(escbuf,"%c%c",( (tt_arrow == TTK_APPL) ? 'O' : '[' ),
'A' + (k - K_UPARR));
else
sprintf(escbuf,"%c", 'A' + (k - K_UPARR));
sendescseq(escbuf);
return;
}
if (k >= K_PF1 && k <= K_PF4) { /* DEC PF keys */
char *p = escbuf;
if (tt_type >= TT_VT100) /* SS3 P..S for VT100 & above */
*p++ = 'O';
*p++ = 'P' + (k - K_PF1); /* or just ESC P..S for VT52 */
*p = NUL;
sendescseq(escbuf);
return;
}
if (k >= K_KP0 && k <= K_KP9) { /* DEC numeric keypad keys */
if (tt_keypad == TTK_NORM) /* Keypad in numeric mode */
sendcharduplex((CHAR) ('0' + (CHAR) (k - K_KP0)));
else { /* Application mode */
sprintf(escbuf,
"%c%c",
((tt_type >= TT_VT100) ? 'O' : '?'),
('p' + (k - K_KP0))
);
sendescseq(escbuf);
}
return;
}
if (k >= K_KPCOMA && k <= K_KPDOT) { /* DEC keypad punctuation keys */
if (tt_keypad == TTK_NORM) /* Keypad in numeric mode */
sendcharduplex((CHAR) (',' + (CHAR) (k - K_KPCOMA)));
else { /* Keypad in application mode */
sprintf(escbuf,
"%c%c",
((tt_type >= TT_VT100) ? 'O' : '?'),
('l' + (k - K_KPCOMA))
);
sendescseq(escbuf);
}
return;
}
if (k == K_KPENTER) { /* DEC keypad Enter key */
if (tt_keypad == TTK_NORM) { /* Keypad in numeric mode */
sendcharduplex('\015'); /* Send CR */
if (tnlm)
sendcharduplex('\012'); /* Newline mode, send LF too */
} else { /* Keypad in application mode */
sprintf(escbuf,
"%c%M",
((tt_type >= TT_VT100) ? 'O' : '?')
);
sendescseq(escbuf);
}
return;
}
if (k >= K_DECFIND && k <= K_DECNEXT) { /* DEC editing keypad keys */
if (tt_type >= TT_VT220) /* VT220 and above */
sendescseq(ekeys[k - K_DECFIND]);
else bleep();
return;
}
if (k >= K_DECF6 && k <= K_DECF20) { /* DEC top-rank function keys */
if (tt_type >= TT_VT220) { /* VT220 and above */
sendescseq(fkeys[k - K_DECF6]);
return;
} else { /* VT102 or lower */
switch (k) {
case K_DECF11:
sendcharduplex(ESC); return;
case K_DECF12:
sendcharduplex(BS); return;
case K_DECF13:
sendcharduplex(LF); return;
default:
bleep();
return;
}
}
}
if (k == K_COMPOSE) { /* Compose key */
int i;
CHAR x1, x2, c;
save_status_line();
strcpy(exittext,"Cancel: Space"); /* Make special one */
sprintf(usertext," COMPOSE: [ ]"); /* with mini-echo-buffer */
if (vik.help > 255 && keynam[vik.help - 256])
sprintf(helptext, "Help: %s", keynam[vik.help - 256]);
line25();
while ((x1 = keymap[congks(0)]) == K_HELP) /* Let them ask for help */
popuphelp(2);
if (macrotab[x1] || (x1 <= SP) || (x1 > 0x7E)) {
if (x1 != SP) bleep();
goto compose_exit;
}
sprintf(usertext," COMPOSE: [%c ]", x1); /* Echo first char */
line25();
while ((x2 = keymap[congks(0)]) == K_HELP)
popuphelp(2);
if (x2 <= SP || x2 > 0x7E) {
if (x2 != SP) bleep();
goto compose_exit;
}
sprintf(usertext," COMPOSE: [%c%c]", x1, x2); /* Echo second char */
line25();
for (i = 0; i < nl1ktab; i++) /* Look up the 2-char sequence */
if ((x1 == l1ktab[i].c1) && (x2 == l1ktab[i].c2))
break;
if (i >= nl1ktab) { /* Not found */
bleep();
goto compose_exit;
} else c = l1ktab[i].c3; /* Character we found */
if (sxi) c = (*sxi)((CHAR)c); /* Xlate from remote to intermediate */
if (rxi) c = (*rxi)((CHAR)c); /* and from intermediate to local */
sendcharduplex(c); /* Send it */
msleep(333); /* Some time to look at minibuffer */
compose_exit: /* Common exit point */
restore_status_line(); /* Restore status line */
return;
}
if (k == K_KB_HEB) { /* Hebrew keyboard support... */
sethebrewmode();
return;
}
if (k == K_KB_ENG) {
resethebrewmode();
return;
}
#ifdef COMMENT
if (k >= K_UDKF6 && k <= K_UDKF20) { /* User-Defined Keys */
return; /* Not implemented yet */
}
#endif /* COMMENT */
}
#endif /* NOKVERBS */
/* S E N D K E Y D E F -- Send key definition */
static void
sendkeydef(unsigned char *s) {
#ifndef NOKVERBS
int x, y, brace = 0;
int pause;
char * p, * b;
#define K_BUFLEN 30
char kbuf[K_BUFLEN + 1]; /* Key verb name buffer */
#endif /* NOKVERBS */
pause = (tt_pacing > -1) ? tt_pacing : 50;
for ( ; *s; s++ ) { /* Go through the string */
#ifdef NOKVERBS
if (!network) msleep(pause); /* To prevent UART overruns... */
sendcharduplex(*s); /* Send each character literally. */
#else /* \Kverb support ... */
if (*s != CMDQ) { /* Normal character */
if (!network) msleep(pause); /* Prevent UART overruns. */
sendcharduplex(*s); /* Send it */
continue; /* Get next, etc. */
}
b = s++; /* Get next character */
if (!*s) {
keydefptr = NULL;
return;
}
if (*s == '{') { /* Opening brace? */
brace = 1; /* Remember */
s++; /* Go to next character */
if (!*s) {
keydefptr = NULL;
return;
}
}
if (*s == 'K' || *s == 'k') { /* Have K verb? */
s++;
if (!*s) {
keydefptr = NULL;
return;
}
/*
We assume that the verb name is {braced}, or it extends to the end of the
string, s, or it ends with a space, control character, or backslash.
*/
p = kbuf; /* Copy verb name into local buffer */
x = 0;
while ((x++ < K_BUFLEN) && (*s > SP) && (*s != CMDQ)) {
if (brace && *s == '}') {
break;
}
*p++ = *s++;
}
if (*s && !brace) /* If we broke because of \, etc, */
s--; /* back up so we get another look. */
brace = 0;
*p = NUL; /* Terminate. */
p = kbuf; /* Point back to beginning */
debug(F110,"sendkeydef kverb",p,0);
y = xlookup(kverbs,p,nkverbs,&x); /* Look it up */
debug(F101,"sendkeydef lookup",0,y);
if (y > -1) {
#ifdef __32BIT__
{
DosRequestMutexSem( hmtxScreenSem, SEM_INDEFINITE_WAIT ) ;
dokverb(y) ;
DosReleaseMutexSem( hmtxScreenSem ) ;
}
#else
dokverb(y);
#endif /* __32BIT__ */
#ifndef NOSPL
} else { /* Is it a macro? */
y = mxlook(mactab,p,nmac);
if (y > -1) {
keymac = 1; /* Flag for key macro active */
keymacx = y; /* Key macro index */
keydefptr = s; /* Where to resume next time */
debug(F111,"sendkeydef mxlook",keydefptr,y);
active = 0; /* Leave CONNECT mode */
}
#endif /* NOSPL */
}
} else if (*s == 'V' || *s == 'v') { /* Have \v(xxx)? */
s++; /* Next char */
if (!*s)
return;
if (*s != '(') { /* Should be left paren */
if (!network) msleep(pause); /* Prevent UART overruns. */
sendcharduplex(CMDQ);
if (!network) msleep(pause); /* Prevent UART overruns. */
sendcharduplex(*s);
continue;
}
b = s - 1; /* Save my place */
s++; /* Point past paren */
p = kbuf; /* Point to word buffer */
x = 0; /* Copy verb into it */
while ((x++ < K_BUFLEN) && (*s > SP) && (*s != ')'))
*p++ = *s++;
*p = NUL;
if (*s != ')') { /* Have terminating paren? */
if (!network) msleep(pause); /* Prevent UART overruns. */
sendcharduplex(CMDQ); /* No, send this literally */
s = b;
continue;
} else {
p = kbuf; /* Point back to beginning */
debug(F110,"sendkeydef v(verb)",p,0);
p = nvlook(p); /* Look it up. */
if (!p) /* Not found, */
continue; /* continue silently. */
while (*p) { /* Send it. */
if (!network) msleep(pause); /* Prevent UART overruns. */
sendcharduplex(*p++);
}
if (!*s)
return;
}
} else { /* Not \K, \{K or \V */
if (!network) msleep(pause); /* Prevent UART overruns. */
sendcharduplex(CMDQ); /* Back up and send backslash, */
if (brace) { /* and maybe a left brace, */
if (!network) msleep(pause); /* Prevent UART overruns. */
sendcharduplex('{');
brace = 0;
}
if (!network) msleep(pause); /* Prevent UART overruns. */
if (*s) sendcharduplex(*s); /* and this char literally. */
}
if (!*s) {
keydefptr = NULL;
return;
}
#endif /* NOKVERBS */
}
keydefptr = NULL;
}
/* Scrollback handler */
/*
Totally rewritten for edit 190 to allow TERMINAL ROLL options and to
use new keymap - fdc.
*/
static void
scrollback(int key) { /* Keycode */
int nlines, /* How many lines to roll */
nolblines, /* Lines above top of screen */
i, il; /* Workers */
/* Initialization */
#ifdef DEBUG
if (deblog) {
debug(F101,"scrollback key","",key);
debug(F101,"scrollback botline","",roll.botline);
debug(F101,"scrollback numlines","",roll.numlines);
debug(F101,"scrollback linesleft","",roll.linesleft);
debug(F101,"scrollback nextline","",roll.nextline);
debug(F101,"scrollback flag","",roll.flag);
debug(F101,"scrollback tt_roll","",tt_roll);
}
#endif /* DEBUG */
if (!roll.flag) { /* Set if we are not at bottom */
roll.linesleft = roll.numlines;
roll.nextline = roll.botline;
}
if (cursorena) /* If cursor not already off */
killcursor(); /* turn it off. */
/*
If TERMINAL ROLL OFF, we just process the argument key and return control of
the keyboard to the user. This lets the user type characters to the host
while looking at rollback screens, as well as view new incoming characters
on an old screen. But it can result in some confusion by mixing new and old
material in the rollback buffer.
If TERMINAL ROLL ON, the user is held captive inside the rolled-back
screens, allowed to type only rollback keys until reaching the bottom again,
and no characters are read from the communication device while rolled back.
This prevents transmission of characters to the host, and it prevents
mixture of new and old material in the rollback buffer.
*/
do { /* If ROLL is ON, this is a loop */
while (roll.flag && tt_roll) { /* Get another keystroke */
key = keymap[congks(0)];
if (key & F_KVERB) /* It has to be a \Kverb */
break;
bleep(); /* if not, stay in little loop */
}
switch (key &= ~(F_KVERB)) { /* Handle the key... */
case K_HOMSCN: /* Scrolling UP (backwards) ... */
case K_UPSCN:
case K_UPONE:
if (roll.linesleft <= 0) { /* Can't go any further up */
bleep(); /* Beep */
if (!roll.flag)
return;
else if (tt_roll)
continue;
else {
if (cursorena) /* If cursor is enabled */
newcursor(); /* turn it back on. */
return;
}
}
if (!roll.flag) /* If not scrolled up already, */
savescreen(&savedscreen,wherex,wherey); /* save current screen */
nlines = key == K_UPSCN ? ysize /* How far depends on key */
: key == K_HOMSCN ? roll.linesleft :
1;
if (nlines > roll.linesleft) /* Don't go past top */
nlines = roll.linesleft;
debug(F101,"scrollback up nlines","",nlines);
if (nlines >= ysize) { /* More than screen size? */
if (nlines > ysize)
roll.nextline = roll.topline + ysize - 1;
debug(F101,"scrollback up whole screen","",roll.nextline);
for (il = ysize; il >= 1; il--) {
movetoscreen(
roll.buffer + xsize * 2 * roll.nextline,
1, il, xsize * 2);
if (roll.nextline == 0)
roll.nextline = LBUFSIZE - 1;
else
roll.nextline--;
} /* for-loop */
} else { /* nlines < ysize, so we can scroll some lines down */
debug(F101,"scrollback up partial screen","",nlines);
scroll(DOWNWARD, 0, ysize - 1, nlines);
for (il = 1; il <= nlines; il++) {
movetoscreen(roll.buffer + xsize * 2 * roll.nextline,
1, nlines - il + 1, xsize * 2);
if (roll.nextline <= 0)
roll.nextline = LBUFSIZE - 1;
else
roll.nextline--;
}
}
roll.linesleft -= nlines;
roll.flag = 1;
break;
case K_DNSCN: /* Go down */
case K_DNONE:
if (!roll.flag) { /* If we're not rolled back */
bleep(); /* nothing to do, so beep */
if (tt_roll)
continue;
else {
if (cursorena) /* If cursor is enabled */
newcursor(); /* turn it back on. */
return;
}
}
nlines = key == K_DNSCN ? ysize : 1; /* Screen Down or Line Down */
if (nlines > roll.numlines - roll.linesleft)
nlines = roll.numlines - roll.linesleft;
debug(F101,"scrollback down nlines","",nlines);
if (nlines < ysize)
scroll(UPWARD, 0, ysize - 1, nlines);
do {
if (++roll.nextline >= LBUFSIZE)
roll.nextline = 0;
roll.linesleft++;
/* Lines of extended display above top of the screen */
nolblines = roll.numlines - roll.linesleft;
/* Number of extended display buffer lines on screen */
if (nolblines >= ysize) {
i = roll.nextline + ysize;
if (i >= LBUFSIZE)
i -= LBUFSIZE;
/* Move from buffer to screen */
movetoscreen(roll.buffer + xsize * 2 * i, 1,
ysize - nlines + 1, xsize * 2);
} else { /* Move from saved current screen */
movetoscreen(
&(savedscreen.scrncpy[
(ysize - 1 - nolblines) * xsize * 2
]),
1,
ysize - nlines + 1,
xsize * 2
);
}
nlines--;
} while (nlines > 0);
break;
case K_ENDSCN: /* Scroll to bottom */
if (!roll.flag) { /* If we're not rolled back, */
bleep(); /* just beep, */
if (cursorena) /* restore cursor, */
newcursor(); /* and return. */
return;
} else { /* Otherwise, set exit condition. */
roll.linesleft = roll.numlines;
}
break;
case K_DUMP: { /* Print/Dump current screen */
int x;
x = xprintff; xprintff = 0;
prtscreen(1,ysize);
xprintff = x;
continue;
}
case K_HELP: /* Help */
popuphelp(0); /* Watch out, this turns cursor on */
killcursor(); /* Turn it back off */
continue;
default: /* Not a rollback key. */
bleep();
continue;
} /* switch (key) */
/* If we're still rolled back, make special status line */
if (roll.linesleft != roll.numlines) {
roll.flag = 1; /* (Just in case) */
sprintf(usertext, " Scroll: %d/%d", /* Do special status line. */
roll.numlines - roll.linesleft,
roll.numlines
);
if (vik.upscn > 255 && keynam[vik.upscn - 256]) {
strncpy(helptext, keynam[vik.upscn - 256], 20);
if (vik.dnscn > 255 && keynam[vik.dnscn - 256]) {
if (HLPTXTLEN
- (int)strlen(keynam[vik.upscn - 256])
- (int)strlen(keynam[vik.dnscn - 256]) > 0) {
strcat(helptext,"/");
strcat(helptext,keynam[vik.dnscn - 256]);
}
}
} else
strcpy(helptext, "\\KupScn,\\KdnScn");
if ((vik.help > 255) &&
(keynam[vik.help - 256]) &&
((HSTNAMLEN - 6 - (int)strlen(keynam[vik.help - 256])) > 0)) {
sprintf(hostname, "Help: %s", keynam[vik.help - 256]);
} else if (vik.homscn > 255 && keynam[vik.homscn - 256]) {
strcpy(hostname, keynam[vik.homscn - 256]);
if (vik.endscn > 255 && keynam[vik.endscn - 256]) {
if (HSTNAMLEN - 1
- (int)strlen(keynam[vik.homscn - 256])
- (int)strlen(keynam[vik.endscn - 256]) > 0) {
strcat(hostname,"/");
strcat(hostname,keynam[vik.endscn - 256]);
}
}
} else
strcpy(hostname, "\\KhomScn,\\KendScn");
exittext[0] = '\0';
/* filetext[0] = '\0'; */
line25(); /* Display the status line */
}
} while (tt_roll && (roll.linesleft != roll.numlines));
/*
Get here after processing one keystroke and TERMINAL ROLL is OFF,
or when TERMINAL ROLL is ON, only when we've reached the bottom.
*/
if (roll.linesleft == roll.numlines) { /* We're at the bottom */
if (roll.flag) {
roll.flag = 0; /* Reset scrolled-back flag */
restorescreen(&savedscreen); /* Put back current screen */
ipadl25(); /* Put back normal status line */
}
}
if (cursorena) /* If cursor is enabled */
newcursor(); /* turn it back on. */
return;
}
static void
vt100key(int key) {
#ifdef NOKVERBS
char str[3]; /* Not needed in simplified code */
int prt, st;
#endif /* NOKVERBS */
if ( keydefptr ) { /* First send any leftovers */
sendkeydef( keydefptr ); /* from previous session... */
keydefptr = NULL; /* and then forget about it */
return;
} else if ( macrotab[key] ) { /* Check for macro */
sendkeydef(macrotab[key]); /* This also handles \Kverbs */
return;
}
key = keymap[key]; /* If no macro, check keymap. */
if (key < 0x100) { /* If it's a regular key, */
sendcharduplex((char) key); /* just send it, */
if (tt_pacing > 0) /* taking care of pacing */
msleep(tt_pacing);
if (key == CR && tnlm) { /* and newline mode */
sendcharduplex(LF);
if (tt_pacing > 0) /* and pacing */
msleep(tt_pacing);
}
return;
}
#ifndef NOKVERBS
if (IS_KVERB(key)) /* Specially precoded keyboard verb */
#ifdef __32BIT__
{
DosRequestMutexSem( hmtxScreenSem, SEM_INDEFINITE_WAIT ) ;
dokverb(key) ; /* We already know its index */
DosReleaseMutexSem( hmtxScreenSem ) ;
}
#else
dokverb(key); /* We already know its index */
#endif /* __32BIT__ */
else
bleep(); /* Extended key with no definition. */
return; /* Just beep & return. */
#else /* Old way, pre-edit-190, hardwired scan codes... */
switch (key & 0xFF) {
case 72: /* Up Arrow */
if (tt_type >= TT_VT100) {
if (tt_arrow == TTK_APPL)
sendescseq("OA"); /* Application mode */
else
sendescseq("[A"); /* Normal (cursor) mode */
} else
sendescseq("A");
break;
case 75: /* 587 Left Arrow */
if (tt_type >= TT_VT100) {
if (tt_arrow == TTK_APPL)
sendescseq("OD");
else
sendescseq("[D");
} else
sendescseq("D");
break;
case 77: /* 589 Right Arrow */
if (tt_type >= TT_VT100) {
if (tt_arrow == TTK_APPL)
sendescseq("OC");
else
sendescseq("[C");
} else
sendescseq("C");
break;
case 80: /* 592 Down Arrow */
if (tt_type >= TT_VT100) {
if (tt_arrow == TTK_APPL)
sendescseq("OB");
else
sendescseq("[B");
} else
sendescseq("B");
break;
case 15: /* 271 Backtab */
sendcharduplex(8); /* Sends backspace */
break;
case 83: /* 127 DEL */
sendcharduplex(127); /* Sends delete */
break;
case 59: /* 315 F1 */
if (tt_type >= TT_VT100) /* Sends DEC PF1 */
sendescseq("OP");
else
sendescseq("P");
break;
case 60: /* 316 F2 */
if (tt_type >= TT_VT100) /* Sends DEC PF2 */
sendescseq("OQ");
else
sendescseq("Q");
break;
case 61: /* 317 F3 */
if (tt_type >= TT_VT100) /* Send DEC PF3 */
sendescseq("OR");
else
sendescseq("R");
break;
case 62: /* 318 F4 */
if (tt_type >= TT_VT100) /* Sends DEC PF4 */
sendescseq("OS");
else
sendescseq("S");
break;
case 120: /* Alt-1 ... Alt-9 */
case 121: /* 376, 377, ... 384 */
case 122:
case 123:
case 124:
case 125:
case 126:
case 127:
case 128:
case 129: /* 385 .. This one is Alt-0 */
/* numeric 1-9,0 */
if (tt_keypad == TTK_NORM) { /* Keypad digits in numeric mode */
if (key == 129) key = 48; /* Watch out for zero */
else key -= 71;
sendcharduplex((unsigned char)key); /* Send digit */
} else { /* Keypad in Application mode */
key = 'q' + (key & 0xFF) - 120;
if (key == 'z')
key = 'p';
/* alt 0 */
if (tt_type >= TT_VT100)
strcpy(str, "O ");
else
strcpy(str, "? ");
str[1] = key;
sendescseq(str);
}
break;
case 63: /* Keypad minus = F5 or ... */
case 64: /* F6 */
if (tt_keypad == TTK_NORM) /* Keypad in numeric mode */
sendcharduplex('-');
else if (tt_type >= TT_VT100) /* Application mode, VT102 */
sendescseq("Om");
else /* Application mode, VT52 */
sendescseq("?m");
break;
case 65: /* Keypad comma = F7 or ... */
case 66: /* F8 */
if (tt_keypad == TTK_NORM) /* Numeric mode... */
sendcharduplex(',');
else if (tt_type >= TT_VT100)
sendescseq("Ol");
else
sendescseq("?l");
break;
case 67: /* Keypad period = F9 */
if (tt_keypad == TTK_NORM)
sendcharduplex('.');
else if (tt_type >= TT_VT100)
sendescseq("On");
else
sendescseq("?n");
break;
case 68: /* Keypad Enter = F10 */
if (tt_keypad == TTK_NORM) {
sendcharduplex('\015'); /* Numeric mode, send CR */
if (tnlm)
sendcharduplex('\012'); /* Newline mode, send LF too */
} else if (tt_type >= TT_VT100)
sendescseq("OM");
else
sendescseq("?M");
break;
case 255: /* Scroll-Lock */
{
strcpy(usertext, " Scroll-Lock ");
*exittext = '\0';
*helptext = '\0';
line25();
while (keymap[congks(0)] != 0x1FF) ;
ipadl25();
}
break;
case 81: /* Page-Down */
case 118: /* Control-Page-Down */
bleep();
/* since not in extended display mode */
break;
case 71: /* Home, enter extended display mode */
case 73: /* Page-Up */
case 132: /* Control-Page-Up */
if (roll.numlines == 0)
bleep();
else
scrollback(key);
break;
case 16: /* Alt-Q = Quit */
doesc('Q'); break;
case 45: /* Alt-X = Return to prompt */
doesc('C'); break;
case 48: /* Alt-B = Send BREAK */
doesc('B'); break;
case 38: /* Alt-L = Send Long BREAK */
doesc('L'); break;
case 35: /* Alt-H = Hangup */
doesc('H'); break;
case 131: /* Alt-= is Reset */
doreset(1);
break;
case 53: /* Alt-? or Alt-/ = Help */
strcpy(usertext, " Press (almost) any key to restore the screen");
exittext[0] = '\0';
helptext[0] = '\0';
hostname[0] = '\0';
line25();
popuphelp(0);
ipadl25();
break;
case 19: /* Alt-R = Flip screen */
flipscreen();
break;
case 25: { /* Alt-P = print/dump screen */
int x;
x = xprintff; xprintff = 0;
prtscreen(1,ysize); /* Print/Dump screen */
xprintff = x;
break;
}
case 32: /* Alt-D = Toggle debugging */
flipdebug();
break;
default: /* Others, ignore */
break;
} /* of switch (key & 0xFF) */
#endif /* NOKVERBS */
}
/* ------------------------------------------------------------------ */
/* cwrite - check and process escape sequence */
/* ------------------------------------------------------------------ */
static char old_c = 0;
void /* Note, not static! */
cwrite(unsigned char ch) { /* Used by ckcnet.c for */
/* TELNET options debug display. */
/*
Edit 190.
New code, supporting APC, and integrating escape sequence state switching
that was formerly done, but not used to good advantage, in chkaes(). The
additional complexity comes from the fact that ESC is not used only to
commence escape sequences, but also, in the case of APC, OSC, PM, etc, to
terminate them. New code also supports session debugging.
*/
if (tt_type == TT_NONE) {
vt100(ch);
return;
}
if (debses && !f_pushed) { /* Session debugging */
unsigned char ch8;
ch8 = f_popped ? ((ch ^ 0x40) | 0x80) : ch;
if (ch8 < 32) { /* C0 Control character */
attribute = colorunderline; /* Use underline color */
if (decscnm) /* Handle flipped screen */
attribute = swapcolors(attribute);
wrtch((char)(ch8 | 64)); /* Write corresponding letter */
} else if (ch8 == 127) { /* DEL */
attribute = colorunderline; /* Underline color */
if (decscnm) /* Handle flipped screen */
attribute = swapcolors(attribute);
wrtch('?'); /* question mark */
} else if (ch8 > 127 && ch8 < 160) { /* C1 control */
attribute = colorunderline; /* Underline color */
if (decscnm) /* Handle flipped screen */
attribute = swapcolors(attribute);
wrtch(ch8); /* The character itself */
} else if (escstate != ES_NORMAL) { /* Part of Esc sequence */
attribute = swapcolors(defaultattribute); /* Reverse video */
wrtch(ch8);
} else { /* Regular character */
attribute = defaultattribute; /* Normal colors */
if (tn_bold) attribute ^= 8; /* (only for TELNET debugging...) */
wrtch(ch8);
}
if (ch8 == LF && old_c == CR) { /* Break lines for readability */
wrtch(CR);
wrtch(LF);
}
old_c = ch8; /* Remember this character */
} /* for CRLF matching. */
/*
Even if debugging, we still plow through the escape-sequence state table
switcher, but we don't call any of the action routines.
This lets us highlight text that appears inside an escape sequence.
*/
if (escstate == ES_NORMAL) { /* Not in an escape sequence */
if (ch == ESC) { /* This character is an Escape */
escstate = ES_GOTESC; /* Change state to GOTESC */
esclast = 0; /* Reset buffer pointer */
} else /* Not an ESC, stay in NORMAL state */
if (!debses) vt100(ch); /* and send to vt100() for display. */
return; /* Return in either case. */
}
/* We are in an escape sequence... */
if (escstate != ES_STRING && escstate != ES_TERMIN) { /* Not in string */
if (ch < SP) { /* Control character? */
if (ch == CAN || ch == SUB) { /* These cancel an escape sequence */
escstate = ES_NORMAL; /* Go back to normal. */
} else if (ch == BS && esclast > 0) { /* Erases previous */
esclast--; /* escape sequence char (really?) */
} else if (ch == ESC) {
escstate = ES_GOTESC; /* Escape sequence was restarted */
esclast = 0; /* Reset buffer pointer */
}
return;
}
/*
Put this character in the escape sequence buffer.
But we don't put "strings" in this buffer; either absorb them silently
(as with Operating System Command), or handle them specially (as with APC).
Note that indexing starts at 1, not 0.
*/
if (esclast < ESCBUFLEN)
escbuffer[++esclast] = ch;
}
/* Note: vtescape() sets escstate back to ES_NORMAL. */
if (tt_type == TT_VT52) { /* VT52 Emulation */
switch (esclast) {
case 1: /* First char after Esc */
if (ch != 'Y') /* If not Y, */
vtescape(); /* then it's a complete sequence */
break;
case 3: /* Can only happen with Y<row><col> */
vtescape(); /* Cursor position */
case 2: /* First part of cursor position */
break;
default: /* Something unexpected, ignore */
escstate = ES_NORMAL;
break;
}
return; /* Done with VT52 */
}
/* The rest of this routine handles ANSI/VT1xx/VT2xx emulation... */
switch (escstate) { /* Enter esc sequence state switcher */
case ES_GOTESC: /* GOTESC state, prev char was Esc */
if (ch == '[') /* Left bracket after ESC is CSI */
escstate = ES_GOTCSI; /* Change to GOTCSI state */
else if (ch == '_' || /* Application Program Command (APC) */
ch == 'P' || /* Device Control String Introducer */
ch == '^' || /* Privacy Message (PM) */
ch == ']') { /* Operating System Command (OSC) */
escstate = ES_STRING; /* Enter STRING-absorption state */
#ifdef CK_APC
if (ch == '_') { /* Application Program Command */
apcactive = 1; /* Set APC-Active flag */
apclength = 0; /* and reset APC buffer pointer */
}
#endif /* CK_APC */
} else if ((ch > 057) && (ch < 0177)) /* Or final char, '0' thru '~' */
vtescape(); /* Go act on it. */
else
escstate = ES_ESCSEQ;
break;
case ES_ESCSEQ: /* ESCSEQ -- in an escape sequence */
if (ch > 057 && ch < 0177) /* Final character is '0' thru '~' */
vtescape(); /* Go handle it */
break;
case ES_GOTCSI: /* GOTCSI -- In a control sequence */
if (ch > 077 && ch < 0177) /* Final character is '@' thru '~' */
vtescape(); /* Go act on it. */
break;
case ES_STRING: /* Inside a string */
if (ch == ESC) /* ESC may be 1st char of terminator */
escstate = ES_TERMIN; /* Change state to find out. */
#ifdef CK_APC
else if (apcactive && (apclength < apcbuflen)) /* If in APC string, */
apcbuf[apclength++] = ch; /* deposit this character */
#endif /* CK_APC */
break; /* Absorb all other characters. */
case ES_TERMIN: /* May have a string terminator */
if (ch == '\\') { /* which must be backslash */
escstate = ES_NORMAL; /* If so, back to NORMAL */
#ifdef CK_APC
if (apcactive) { /* If it was an APC string, */
apcbuf[apclength] = NUL; /* terminate it and then ... */
if (apcstatus != APC_OFF) {
active = FALSE; /* exit from the terminal emulator */
return; /* with the apcactive flag still set */
} else apcactive = 0;
#endif /* CK_APC */
}
} else { /* Just a stray Esc character. */
escstate = ES_STRING; /* Return to string absorption. */
#ifdef CK_APC
if (apcactive && (apclength+1 < apcbuflen)) { /* In APC string, */
apcbuf[apclength++] = ESC; /* deposit the Esc character */
apcbuf[apclength++] = ch; /* and this character too */
}
#endif /* CK_APC */
}
}
}
/*---------------------------------------------------------------------------*/
/* scrninit */
/*---------------------------------------------------------------------------*/
static void
scrninit() {
setborder();
if ( roll.bufsize != tt_scrsize ) {
if ( roll.buffer != NULL )
free(roll.buffer);
roll.buffer = NULL;
scrninitialised = 0;
}
if (!scrninitialised) {
scrninitialised = 1;
defaultattribute = colornormal;
attribute = defaultattribute;
/* Initialise paging info */
if ( roll.buffer == NULL ) {
roll.bufsize = tt_scrsize;
roll.buffer = malloc(tt_scrsize * xsize * 2);
}
assert(roll.buffer != NULL);
roll.numlines = 0;
roll.topline = 0;
roll.botline = LBUFSIZE - 1;
roll.flag = 0;
clearscreen(0, attribute);
savescreen(&vt100screen,wherex,wherey);
}
}
/*---------------------------------------------------------------------------*/
/* bleep */
/*---------------------------------------------------------------------------*/
static void
bleep() {
switch(tt_bell) { /* Follows TERMINAL BELL setting. */
case 1: /* AUDIBLE */
DosBeep(880, 50); /* 880 MHz for 50 msec */
return;
case 2: /* VISIBLE */
flipscreen(); /* Flash the screen */
msleep(250); /* for 250 msec */
flipscreen();
return;
default: /* NONE or other */
return;
}
}
/*---------------------------------------------------------------------------*/
/* wrtch */
/*---------------------------------------------------------------------------*/
static void
wrtch(char ch) {
char cell[2];
if (printon && xprint && !debses) /* If transparent print active, */
return; /* we don't touch the screen. */
if (ch >= ' ' || literal) { /* Normal character */
if (attrib.invisible)
ch = ' ';
if ((tt_type >= TT_VT102) && insertmode) {
cell[0] = ch;
cell[1] = attribute;
#ifdef OS2MOUSE
os2_mousehide() ;
#endif /* OS2MOUSE */
VioScrollRt(wherey - 1, wherex - 1, wherey - 1,
xsize - 1, 1, cell, 0);
#ifdef OS2MOUSE
os2_mouseshow() ;
#endif
} else
#ifdef OS2MOUSE
os2_mousehide() ;
#endif /* OS2MOUSE */
VioWrtCharStrAtt(&ch, 1, wherey - 1, wherex - 1, &attribute, 0);
#ifdef OS2MOUSE
os2_mouseshow() ;
#endif
literal = FALSE;
if (++wherex > xsize) {
wherex = 1;
wrtch(LF);
}
} else { /* Control character */
switch (ch) {
case LF:
if (wherey == marginbot) {
if (margintop == 1)
toplinetocyclicbuffer();
scroll(UPWARD, margintop - 1, marginbot - 1, 1);
} else {
wherey++;
if (wherey == ysize + 1)
wherey--;
}
break;
case CR:
wherex = 1;
break;
case BS:
if (wherex > 1)
wherex--;
break;
case 12:
if (wherex < xsize)
wherex++;
break;
case BEL:
DosBeep(440, 100);
break;
default:{ /* Ignore */
}
}
}
if (cursoron)
VioSetCurPos(wherey - 1, wherex - 1, 0);
}
/*---------------------------------------------------------------------------*/
/* clearscreen */
/*---------------------------------------------------------------------------*/
static void
clearscreen(int all, int attr) {
char cell[2];
cell[0] = ' ';
cell[1] = attr;
#ifdef OS2MOUSE
os2_mousehide() ;
#endif /* OS2MOUSE */
VioWrtNCell(cell, xsize * ysize + (all ? xsize : 0), 0, 0, 0);
#ifdef OS2MOUSE
os2_mouseshow() ;
#endif
lgotoxy(1, 1);
}
/*---------------------------------------------------------------------------*/
/* lgotoxy */
/*---------------------------------------------------------------------------*/
static void
lgotoxy(int x, int y) {
wherex = x;
wherey = y;
if (cursoron)
VioSetCurPos(wherey - 1, wherex - 1, 0);
}
/*---------------------------------------------------------------------------*/
/* scroll */
/*---------------------------------------------------------------------------*/
static void
scroll(int updown, int top, int bottom, int nlines) {
char blankcell[2];
int i;
blankcell[0] = ' ';
#ifdef COMMENT
blankcell[1] = attribute;
#else
/*
Fixed by fdc, Jan 94 -- If the new bottom line inherits the current
character attributes, then it will be padded out to the end with
attribute-bearing spaces. Create the new line with default attributes,
then let subsequent-character writing operations take care of the
per-character attributes.
*/
blankcell[1] = defaultattribute;
#endif /* COMMENT */
switch (updown) {
case UPWARD:
#ifdef OS2MOUSE
os2_mousehide() ;
#endif
VioScrollUp(top, 0, bottom, xsize - 1, nlines, blankcell, 0);
VioShowBuf(0, xsize * 2, 0);
/* There is a bug in early OS/2 2.0 8514/A PM drivers that causes
* wrong screen update after a scroll operation. We just force
* a correct screen update of the line in question here. */
#ifdef OS2MOUSE
os2_mouseshow() ;
#endif
if (dwls) {
for (i = top; i <= bottom - nlines; i++)
dwl[i] = dwl[i + nlines];
for (i = bottom - nlines + 1; i <= bottom; i++)
dwl[i] = FALSE;
}
break;
case DOWNWARD:
#ifdef OS2MOUSE
os2_mousehide() ;
#endif
VioScrollDn(top, 0, bottom, xsize - 1, nlines, blankcell, 0);
VioShowBuf(xsize * 2, xsize * 2, 0);
#ifdef OS2MOUSE
os2_mouseshow() ;
#endif
if (dwls) {
for (i = bottom; i >= top + nlines; i--)
dwl[i] = dwl[i - nlines];
for (i = top + nlines - 1; i >= top; i--)
dwl[i] = FALSE;
}
break;
default: /* ignore */ ;
}
if (dwls) {
dwls = FALSE;
for (i = 0; i < ysize; i++)
if (dwl[i]) {
dwls = TRUE;
break;
}
}
}
/*---------------------------------------------------------------------------*/
/* movetoscreen */
/*---------------------------------------------------------------------------*/
static void
movetoscreen(char *source, int x, int y, int len) {
#ifdef OS2MOUSE
os2_mousehide() ;
#endif /* OS2MOUSE */
VioWrtCellStr(source, len, y - 1, x - 1, 0);
#ifdef OS2MOUSE
os2_mouseshow() ;
#endif
}
/*---------------------------------------------------------------------------*/
/* toplinetocyclicbuffer */
/*---------------------------------------------------------------------------*/
static void
toplinetocyclicbuffer() {
USHORT n = xsize * 2;
if (roll.numlines == LBUFSIZE) {
if (++roll.topline == LBUFSIZE)
roll.topline = 0;
} else
roll.numlines++;
if (++roll.botline == LBUFSIZE)
roll.botline = 0;
#ifdef OS2MOUSE
os2_mousehide() ;
#endif
VioReadCellStr((roll.buffer + xsize * 2 * roll.botline),
&n, 0, 0, 0);
#ifdef OS2MOUSE
os2_mouseshow() ;
#endif
}
/*---------------------------------------------------------------------------*/
/* cleartoeol */
/*---------------------------------------------------------------------------*/
static void
clrtoeoln() {
char cell[2];
cell[0] = ' ';
#ifdef COMMENT
cell[1] = attribute;
#else
cell[1] = defaultattribute;
#endif /* COMMENT */
#ifdef OS2MOUSE
os2_mousehide() ;
#endif /* OS2MOUSE */
VioWrtNCell(cell, xsize + 1 - wherex, wherey - 1, wherex - 1, 0);
#ifdef OS2MOUSE
os2_mouseshow() ;
#endif
}
/*---------------------------------------------------------------------------*/
/* setmargins */
/*---------------------------------------------------------------------------*/
static void
setmargins(int top, int bot) {
margintop = top;
marginbot = bot;
}
/*---------------------------------------------------------------------------*/
/* killcursor */
/*---------------------------------------------------------------------------*/
static void
killcursor() {
VIOCURSORINFO nocursor;
if (!cursoron) /* It's already off */
return;
VioGetCurType(&crsr_info, 0); /* Store current cursor type */
nocursor = crsr_info; /* MS C allows structure copy */
nocursor.attr = -1;
VioSetCurType(&nocursor, 0); /* Hide cursor */
cursoron = FALSE;
}
/*---------------------------------------------------------------------------*/
/* newcursor */
/*---------------------------------------------------------------------------*/
static void
newcursor() {
if (cursoron) /* It's already on */
return;
VioSetCurType(&crsr_info, 0);
VioSetCurPos(wherey - 1, wherex - 1, 0);
cursoron = TRUE;
}
/*---------------------------------------------------------------------------*/
/* line25 */
/*---------------------------------------------------------------------------*/
#define STATUS_MAX 10
static char *save_status[STATUS_MAX];
static char *save_usertext[STATUS_MAX];
static char *save_exittext[STATUS_MAX];
static char *save_helptext[STATUS_MAX];
static char *save_filetext[STATUS_MAX];
static char *save_savefiletext[STATUS_MAX];
static char *save_hostname[STATUS_MAX];
static void
save_status_line() {
if ((++status_saved >= (STATUS_MAX - 1)) || (status_saved < 0))
return;
if (!(save_status[status_saved] = malloc(MAXCOL+1)))
return;
else
strncpy(save_status[status_saved],statusline,MAXCOL);
if (!(save_usertext[status_saved] = malloc(MAXCOL+1)))
return;
else
strncpy(save_usertext[status_saved],usertext,MAXCOL);
if (!(save_exittext[status_saved] = malloc(MAXCOL+1)))
return;
else
strncpy(save_exittext[status_saved],exittext,MAXCOL+1);
if (!(save_helptext[status_saved] = malloc(MAXCOL+1)))
return;
else
strncpy(save_helptext[status_saved],helptext,MAXCOL+1);
if (!(save_filetext[status_saved] = malloc(MAXCOL+1)))
return;
else
strncpy(save_filetext[status_saved],filetext,MAXCOL+1);
if (!(save_savefiletext[status_saved] = malloc(MAXCOL+1)))
return;
else
strncpy(save_savefiletext[status_saved],savefiletext,MAXCOL+1);
if (!(save_hostname[status_saved] = malloc(MAXCOL+1)))
return;
else
strncpy(save_hostname[status_saved],hostname,MAXCOL+1);
}
static void
restore_status_line() {
if ((status_saved >= (STATUS_MAX - 1)) || (status_saved < 0))
return;
if (save_status[status_saved]) {
strncpy(statusline,save_status[status_saved],MAXCOL);
free(save_status[status_saved]);
}
if (save_usertext[status_saved]) {
strncpy(usertext,save_usertext[status_saved],20);
free(save_usertext[status_saved]);
}
if (save_exittext[status_saved]) {
strncpy(exittext,save_exittext[status_saved],20);
free(save_exittext[status_saved]);
}
if (save_helptext[status_saved]) {
strncpy(helptext,save_helptext[status_saved],20);
free(save_helptext[status_saved]);
}
if (save_filetext[status_saved]) {
strncpy(filetext,save_filetext[status_saved],20);
free(save_filetext[status_saved]);
}
if (save_savefiletext[status_saved]) {
strncpy(savefiletext,save_savefiletext[status_saved],20);
free(save_savefiletext[status_saved]);
}
if (save_hostname[status_saved]) {
strncpy(hostname,save_hostname[status_saved],20);
free(save_hostname[status_saved]);
}
status_saved--;
line25();
}
static void
strinsert(char *d, char *s) {
while (*s)
*d++ = *s++;
}
static void
xline25(char *s) {
char attr;
attr = colorstatus;
#ifdef OS2MOUSE
os2_mousehide() ;
#endif /* OS2MOUSE */
VioWrtCharStrAtt(s, xsize, ysize, 0, &attr, 0);
#ifdef OS2MOUSE
os2_mouseshow() ;
#endif
}
static void
line25() {
char *s = statusline;
int i;
for (i = 0; i < xsize; i++)
s[i] = ' ';
if (usertext[0]) strinsert(&s[00], usertext); /* Leftmost item */
if (helptext[0]) strinsert(&s[18], helptext);
if (exittext[0]) strinsert(&s[32], exittext);
i = strlen(filetext); /* How much needed for last item */
if (i > 0) {
strinsert(&s[79 - i], filetext); /* Right-justify it */
if (hostname[0]) {
i = 31 - i; /* Space remaining for hostname */
if ((int) strlen(hostname) > (i - 1)) { /* Too long? */
int j;
for (j = i; j > 0 && hostname[j] != ':'; j--) ;
if (j > 0) { /* Cut off ":service" if any */
hostname[j] = '\0';
} else { /* Or else ... */
hostname[i - 3] = '.'; /* show ellipsis */
hostname[i - 2] = '.';
hostname[i - 1] = '\0';
}
}
}
}
if (hostname[0])
strinsert(&s[47], hostname);
xline25(s);
}
#ifdef COMMENT
static void
sendescseq(char * s) {
sendchar(27);
while (*s) {
if (!network) msleep(50);
sendchar(*s++);
}
}
#endif /* COMMENT */
/*
* RDCOMWRTSCR -- Read from the communication device and write to the screen.
* This function is executed by a separate thread.
*/
int
ckcgetc(int dummy) {
return ttinc(1);
}
#ifdef __32BIT__
void
rdcomwrtscr(void * pArgList)
#else
void FAR
rdcomwrtscr()
#endif /* __32BIT__ */
/* rdcomwrtscr */ {
int c, cx, tx;
DosSetPrty(PRTYS_THREAD, PRTYC_FOREGROUNDSERVER, 0, 0);
#ifdef __32BIT__
DosPostEventSem(threadsem);
#else
DosSemClear(&threadsem); /* Let 'em know we've started */
#endif
while (active) {
if (f_pushed) { /* Handle 8-bit controls */
c = c_pushed; /* by converting to ESC + 7-bit char */
f_pushed = 0;
f_popped = 1;
} else {
c = ttinc(-50); /* Get a character from the host */
cx = c & cmask; /* C1 check must be masked */
f_popped = 0;
if (tt_type >= TT_VT220) { /* VT220 and above... */
if (c1controls && /* Character set has C1 controls */
(cx > 127) && (cx < 160) /* It's a C1 character */
) {
f_pushed = 1;
c_pushed = (c & 0x7F) | 0x40;
c = ESC;
}
}
}
if (!active) /* Connection broken? */
break;
if (c >= 0) { /* Got character with no error? */
#ifdef TNCODE
/* Handle TELNET negotiations here */
if (c == IAC && network && ttnproto == NP_TELNET) {
if ((tx = tn_doop((CHAR)(c & 0xff),duplex,ckcgetc)) == 0) {
continue;
} else if (tx == -1) { /* I/O error */
strcpy(termessage, "Connection closed.\n");
active = FALSE; /* Quit */
break;
} else if (tx == 1) { /* ECHO change */
duplex = 1; /* Get next char */
continue;
} else if (tx == 2) { /* ECHO change */
duplex = 0; /* Get next char */
continue;
} else if (tx == 3) { /* Quoted IAC */
c = 255; /* proceeed with it. */
} else continue; /* Unknown, get next char */
}
#endif /* TNCODE */
#ifdef __32BIT__
DosRequestMutexSem( hmtxScreenSem, SEM_INDEFINITE_WAIT ) ;
#ifdef OS2MOUSE
if ( hMouse )
DosRequestMutexSem( hmtxMouseSem, SEM_INDEFINITE_WAIT ) ;
#endif /* OS2MOUSE */
#else
DosEnterCritSec();
#endif /* __32BIT__ */
if (tt_hide && cursoron && cursorena) /* Kill cursor if more */
if (ttchk() > 20) /* than 20 input chars are buffered */
killcursor();
c &= cmask; /* Maybe strip 8th bit */
if (sosi && !debses) { /* Handle Shift In / Shift Out */
if (c == SO) { /* Shift Out */
inshift = 1;
goto cont;
} else if (c == SI) { /* Shift In */
inshift = 0;
goto cont;
}
if (inshift) c |= 0200;
}
if (escstate == ES_NORMAL) { /* Translate character sets */
if (sxi) c = (*sxi)((CHAR)c);
if (rxi) c = (*rxi)((CHAR)c);
}
#ifdef COMMENT
/* No longer needed, done in cwrite() */
if (iskipesc) inesc = chkaes(inesc, (CHAR)c);
/* Adjust escape sequence status */
#endif /* COMMENT */
c &= cmdmsk; /* Apply command mask. */
if ((!debses) && (
(tnlm && (c == LF || c == FF || c == 11)) || /* NEWLINE-MODE? */
(c == CR && tt_crd) /* CR-DISPLAY CRLF ? */
)) {
cwrite((char) CR); /* Yes, output CR */
if (seslog) logchar((char) CR);
c = LF; /* and insert a linefeed */
}
cwrite((char) c);
if (seslog) logchar((char) c);
cont: ;
#ifdef __32BIT__
#ifdef OS2MOUSE
if ( hMouse )
DosReleaseMutexSem( hmtxMouseSem ) ;
#endif /* OS2MOUSE */
DosReleaseMutexSem( hmtxScreenSem ) ;
#else
DosExitCritSec();
#endif /* __32BIT__ */
} else if (c == -2) {
active = FALSE;
strcpy(termessage, "Connection closed.\n");
/* link broken */
} else if (tt_hide && !cursoron && cursorena) {
#ifdef __32BIT__
DosRequestMutexSem( hmtxScreenSem, SEM_INDEFINITE_WAIT ) ;
#ifdef OS2MOUSE
if ( hMouse )
DosRequestMutexSem( hmtxMouseSem, SEM_INDEFINITE_WAIT ) ;
#endif /* OS2MOUSE */
#else
DosEnterCritSec();
#endif /* __32BIT__ */
newcursor();
#ifdef __32BIT__
#ifdef OS2MOUSE
if ( hMouse )
DosReleaseMutexSem( hmtxMouseSem ) ;
#endif /* OS2MOUSE */
DosReleaseMutexSem( hmtxScreenSem ) ;
#else
DosExitCritSec();
#endif /* __32BIT__ */
}
}
#ifdef __32BIT__
_endthread() ;
#else
DosEnterCritSec(); /* Stop thread 1 discarding our stack before
* we've gone */
DosSemClear(&threadsem); /* Tell him we're going to die */
DosExit(EXIT_THREAD, 0);
#endif /* __32BIT__ */
}
/* POPUPHELP -- Give help message for connect. */
static int helpcol, helprow;
static int helpwidth;
static void
helpstart(int w, int h) { /* Start help window */
unsigned char cell[2];
cell[1] = colorhelp;
helpwidth = w;
helpcol = (xsize - w) / 2; /* Column */
helprow = (ysize - h) / 2 - 1; /* Row */
cell[0] = 201; /* IBM upper left box corner double */
#ifdef OS2MOUSE
os2_mousehide() ;
#endif /* OS2MOUSE */
VioWrtNCell(cell, 1, helprow, helpcol, 0);
cell[0] = 205; /* Center box bar horizontal double */
VioWrtNCell(cell, helpwidth, helprow, helpcol + 1, 0);
cell[0] = 187; /* Upper right box corner double */
VioWrtNCell(cell, 1, helprow, helpcol + helpwidth + 1, 0);
#ifdef OS2MOUSE
os2_mouseshow() ;
#endif
}
static void
helpline(char *s) { /* Add line to popup help */
unsigned char cell[2];
int i;
i = strlen(s); /* Length of this line */
helprow++;
cell[1] = colorhelp;
cell[0] = 186; /* IBM center bar vertical double */
#ifdef OS2MOUSE
os2_mousehide() ;
#endif /* OS2MOUSE */
VioWrtNCell(cell, 1, helprow, helpcol, 0);
VioWrtCharStrAtt(s, i, helprow, helpcol + 1, &cell[1], 0);
cell[0] = ' ';
VioWrtNCell(cell, helpwidth - i, helprow, helpcol + 1 + i, 0);
cell[0] = 186; /* IBM center bar vertical double */
VioWrtNCell(cell, 1, helprow, helpcol + helpwidth + 1, 0);
#ifdef OS2MOUSE
os2_mouseshow() ;
#endif
}
static void
helpend() { /* End of popup help box */
unsigned char cell[2];
#ifdef OS2MOUSE
os2_mousehide() ;
#endif /* OS2MOUSE */
helprow++;
cell[1] = colorhelp;
cell[0] = 200; /* IBM lower left box corner double */
VioWrtNCell(cell, 1, helprow, helpcol, 0);
cell[0] = 205; /* Center box bar horizontal double */
VioWrtNCell(cell, helpwidth, helprow, helpcol + 1, 0);
cell[0] = 188; /* Lower right box corner double */
VioWrtNCell(cell, 1, helprow, helpcol + helpwidth + 1, 0);
#ifdef OS2MOUSE
os2_mouseshow() ;
#endif
}
static int
popuphelp(int x) {
int c, n;
char line[81];
char kn[41];
char *s;
static char *hlpmsg[] = {
"",
" Command: (SPACE to cancel)",
"",
" C to return to the C-Kermit prompt",
" U to hangUp and return to the prompt",
" Q to hangup and Quit C-Kermit",
" ! to enter the OS/2 command processor",
" F to print or File the current screen",
"",
" 0 (zero) to send a null",
" ^%c to send the escape character",
" B to send a BREAK signal",
" L to send a Long BREAK",
"",
#ifdef TNCODE
" I to Interrupt process (TELNET)",
" A to send \"Are you there?\" (TELNET)",
"",
#endif /* TNCODE */
" \\ backslash escape (end with ENTER):",
" \\nnn decimal code, like \\199",
" \\Onnn octal code, like \\o307",
" \\Xhh hexadecimal code, like \\xC7",
""};
#define HELPSIZE (sizeof(hlpmsg)/sizeof(char *))
static char *cmposmsg[] = {
" COMPOSE SEQUENCES FOR MULTINATIONAL CHARACTERS",
"",
" Press two keys to compose the desired character:",
"",
" First Second Result",
" ' Vowel Vowel with acute accent",
" ` Vowel Vowel with grave accent",
" \" Vowel Vowel with diaeresis/trema/umlaut",
" ^ Vowel Vowel with circumflex",
" * A A ring",
" , C C cedilla",
" ~ N,A,O Letter with tilde",
" A E AE digraph",
" O / O with stroke",
" s s German sharp s",
"",
" And others; see the documentation.",
};
#define COMPOSESIZE (sizeof(cmposmsg)/sizeof(char *))
#ifdef COMMENT
unsigned char cell[MAXCOL * 2]; /* For saving status line */
USHORT w;
w = xsize * 2;
#ifdef OS2MOUSE
os2_mousehide() ;
#endif
VioReadCellStr(cell, &w, ysize - 1, 0, 0); /* Read status line */
#ifdef OS2MOUSE
os2_mouseshow() ;
#endif
#else /* !COMMENT */
#ifdef __32BIT__
DosRequestMutexSem( hmtxScreenSem, SEM_INDEFINITE_WAIT ) ;
#endif /* __32BIT__ */
save_status_line(); /* Save current status line */
#endif /* COMMENT */
savescreen(&helpscreen,wherex,wherey);
if (cursorena)
killcursor();
if (x > 0) { /* List escape-character commands */
n = (x == 1) ? HELPSIZE : COMPOSESIZE; /* or compose-key help */
helpstart(x == 1 ? 47 : 52, n);
for (c = 0; c < n; c++) {
s = (x == 1) ? hlpmsg[c] : cmposmsg[c];
if (strchr(s, '%')) {
sprintf(line, s, ctl(escape));
helpline(line);
} else
helpline(s);
}
} else { /* List "hot keys" */
strcpy(usertext, " Press (almost) any key to restore the screen");
exittext[0] = helptext[0] = hostname[0] = NUL;
line25();
if (roll.flag) {
s = " OS/2 C-KERMIT - SCREEN ROLLBACK KEYS"; /* Box title */
n = 13; /* How many lines for help box */
if (vik.upscn < 256) n--; /* Deduct for verbs not assigned */
if (vik.upone < 256) n--;
if (vik.dnscn < 256) n--;
if (vik.dnone < 256) n--;
if (vik.homscn < 256) n--;
if (vik.endscn < 256) n--;
if (vik.prtscn < 256) n--;
helpstart(50, n); /* Make popup window 50 x n */
helpline(s); /* 1 */
helpline(""); /* 2 */
if (vik.upscn > 255 && keynam[vik.upscn - 256]) {
strncpy(kn,keynam[vik.upscn - 256],40);
sprintf(line," %-15.14s%s",kn,"Roll backward one screen");
helpline(line); /* 3 */
}
if (vik.upone > 255 && keynam[vik.upone - 256]) {
strncpy(kn,keynam[vik.upone - 256],40);
sprintf(line," %-15.14s%s",kn,"Backward one line");
helpline(line); /* 4 */
}
if (vik.dnscn > 255 && keynam[vik.dnscn - 256]) {
strncpy(kn,keynam[vik.dnscn - 256],40);
sprintf(line," %-15.14s%s",kn,"Roll forward one screen");
helpline(line); /* 5 */
}
if (vik.dnone > 255 && keynam[vik.dnone - 256]) {
strncpy(kn,keynam[vik.dnone - 256],40);
sprintf(line," %-15.14s%s",kn,"Forward one line");
helpline(line); /* 6 */
}
if (vik.homscn > 255 && keynam[vik.homscn - 256]) {
strncpy(kn,keynam[vik.homscn - 256],40);
sprintf(line," %-15.14s%s",kn,"Back to beginning");
helpline(line); /* 7 */
}
if (vik.endscn > 255 && keynam[vik.endscn - 256]) {
strncpy(kn,keynam[vik.endscn - 256],40);
sprintf(line," %-15.14s%s",kn,"Forward to end");
helpline(line); /* 8 */
}
if (vik.dump > 255 && keynam[vik.dump - 256]) {
strncpy(kn,keynam[vik.dump - 256],40);
sprintf(line," %-15.14s%s",kn,"Print the current screen");
helpline(line); /* 9 */
}
helpline(""); /* 10 */
helpline(tt_roll ?
" TERMINAL ROLL is ON: No other keys are valid." :
" TERMINAL ROLL is OFF: All keys are valid."
); /* 11 */
sprintf(line, " Rollback buffer size: %d lines.",tt_scrsize);
helpline(line); /* 12 */
helpline(" Use SET TERMINAL SCROLLBACK to change it."); /* 13 */
} else { /* Regular help message */
n = 19; /* How many lines */
s = " OS/2 C-KERMIT - IMPORTANT KEYS";
if (vik.upscn < 256) n--; /* Deduct for verbs not assigned */
if (vik.dnscn < 256) n--;
if (vik.flipscn < 256) n--;
if (vik.debug < 256) n--;
if (vik.reset < 256) n--;
if (vik.prtscn < 256) n--;
if (vik.printff < 256) n--;
if (vik.compose < 256) n--;
helpstart(50, n); /* Make popup window 50 x n */
helpline(s); /* 1 */
helpline(""); /* 2 */
if (vik.exit > 255 && keynam[vik.exit - 256])
strncpy(kn,keynam[vik.exit - 256],40);
else
sprintf(kn, "Ctrl-%c?", ctl(escape));
sprintf(line," %-15.14s%s",kn,"Return to the C-Kermit prompt");
helpline(line); /* 3 */
if (vik.hangup > 255 && keynam[vik.hangup - 256])
strncpy(kn,keynam[vik.hangup - 256],40);
else
sprintf(kn, "Ctrl-%cH", ctl(escape));
sprintf(line," %-15.14s%s",kn,"Hang up and return to the prompt");
helpline(line); /* 4 */
if (vik.os2 > 255 && keynam[vik.os2 - 256])
strncpy(kn,keynam[vik.os2 - 256],40);
else
sprintf(kn, "Ctrl-%c!", ctl(escape));
sprintf(line," %-15.14s%s",kn,"Enter OS/2 command processor");
helpline(line); /* 5 */
if (vik.xbreak > 255 && keynam[vik.xbreak - 256])
strncpy(kn,keynam[vik.xbreak - 256],40);
else
sprintf(kn, "Ctrl-%cB", ctl(escape));
sprintf(line," %-15.14s%s",kn,
(network && ttnproto == NP_TELNET) ?
"Send TELNET BREAK" :
"Send a BREAK signal"
);
helpline(line); /* 6 */
if (!network) {
if ((vik.lbreak > 255) && (keynam[vik.lbreak - 256]))
strncpy(kn,keynam[vik.lbreak - 256],40);
else
sprintf(kn, "Ctrl-%cL", ctl(escape));
sprintf(line," %-15.14s%s",kn,"Send a Long BREAK signal");
helpline(line); /* 7 */
}
if (vik.dump > 255 && keynam[vik.dump - 256])
strncpy(kn,keynam[vik.dump - 256],40);
else
sprintf(kn, "Ctrl-%cF", ctl(escape));
sprintf(line," %-15.14s%s",kn,"Print the current screen");
helpline(line); /* 8 */
if (vik.prtscn > 255 && keynam[vik.prtscn - 256]) {
strncpy(kn,keynam[vik.prtscn - 256],40);
sprintf(line," %-15.14s%s%s",kn,"Turn printer ",
printon ? "OFF" : "ON");
helpline(line); /* 9, maybe */
}
if (vik.printff > 255 && keynam[vik.printff - 256]) {
strncpy(kn,keynam[vik.printff - 256],40);
sprintf(line," %-15.14s%s",kn,"Print formeed / page eject");
helpline(line); /* 10, maybe */
}
if (vik.upscn > 255 && keynam[vik.upscn - 256]) {
strncpy(kn,keynam[vik.upscn - 256],40);
sprintf(line," %-15.14s%s",kn,"Roll backward one screen");
helpline(line); /* 11, maybe */
}
if (vik.dnscn > 255 && keynam[vik.dnscn - 256]) {
strncpy(kn,keynam[vik.dnscn - 256],40);
sprintf(line," %-15.14s%s",kn,"Roll forward one screen");
helpline(line); /* 12, maybe */
}
if (vik.flipscn > 255 && keynam[vik.flipscn - 256]) {
strncpy(kn,keynam[vik.flipscn - 256],40);
sprintf(line," %-15.14s%s%s",kn,
(decscnm ? "Normal" : "Reverse"),
" screen video");
helpline(line); /* 13, maybe */
}
if (vik.debug > 255 && keynam[vik.debug - 256]) {
strncpy(kn,keynam[vik.debug - 256],40);
sprintf(line," %-15.14s%s%s",kn,"Turn terminal debugging ",
debses ? "OFF" : "ON");
helpline(line); /* 14, maybe */
}
if (vik.reset > 255 && keynam[vik.reset - 256]) {
strncpy(kn,keynam[vik.reset - 256],40);
sprintf(line," %-15.14s%s",kn,"Reset the terminal emulator");
helpline(line); /* 15, maybe */
}
if (vik.compose > 255 && keynam[vik.compose - 256]) {
strncpy(kn,keynam[vik.compose - 256],40);
sprintf(line," %-15.14s%s",kn,"Compose a special character");
helpline(line); /* 16, maybe */
}
helpline(""); /* 17 */
sprintf(line," or the CONNECT-mode escape character Ctrl-%c",
ctl(escape));
helpline(line); /* 18 */
helpline(" followed by ? for additional commands."); /* 19 */
}
}
helpend(); /* Write bottom of help panel */
c = keymap[congks(0)]; /* Wait till user hits a key */
if (cursorena) /* If cursor is enabled */
newcursor(); /* turn it back on */
restorescreen(&helpscreen); /* Restore terminal screen */
#ifdef COMMENT
#ifdef OS2MOUSE
os2_mousehide() ;
#endif /* OS2MOUSE */
VioWrtCellStr(cell, w, ysize -1, 0, 0); /* Restore the status line */
#ifdef OS2MOUSE
os2_mouseshow() ;
#endif
#else
restore_status_line();
#ifdef __32BIT__
DosReleaseMutexSem( hmtxScreenSem ) ;
#endif /* __32BIT__ */
#endif /* COMMENT */
return (c);
}
/* CHSTR -- Make a printable string out of a character */
static char*
chstr(int c) {
static char s[8];
char *cp = s;
if (c < SP || c == DEL)
sprintf(cp, "CTRL-%c", ctl(c));
else
sprintf(cp, "'%c'\n", c);
cp = s;
return (cp);
}
/* DOESC -- Process an escape character argument */
static void
esc25(int h) {
strcpy(usertext, " Command:");
strcpy(exittext, h ? "" : (esc_exit ? "Exit: c" : "Prompt: c"));
strcpy(helptext, h ? "" : "Help: h");
line25();
}
static void
doesc(int c) {
int x;
CHAR d, temp[8];
while (1) {
if (c == escape) { /* Send escape character */
sendchar((char)c);
return;
} else if (isupper(c)) /* Or else look it up below. */
c = tolower(c);
switch (c) {
case 'c': /* Return to prompt */
case '\03':
active = 0;
return;
case 'u': /* Hangup and return to command mode */
hangnow = 1;
active = 0;
strcpy(termessage, "Hangup.\n");
return;
case 'q': /* Hangup and quit */
active = 0;
hangnow = 1;
quitnow = 1;
strcpy(termessage, "Hangup and quit.\n");
return;
case '!': /* Push to OS/2 */
os2push();
return;
case 'b': /* Send a BREAK signal */
case '\02':
ttsndb();
return;
case 'l': /* Send a Long BREAK signal */
case '\014':
ttsndlb();
return;
case 'f': /* Print/dump screen */
x = xprintff; xprintff = 0;
prtscreen(1,ysize);
xprintff = x;
return;
case '0': /* Send a NUL character */
c = '\0';
sendchar((char)c);
return;
#ifdef NETCONN
#ifdef TCPSOCKET
case 'i': /* Send TELNET Interrupt Process */
do_tn_cmd((CHAR) IP);
return;
case 'a': /* "Are You There?" */
do_tn_cmd((CHAR) AYT);
return;
#endif /* TCPSOCKET */
#endif /* NETCONN */
case '\\':
{
char kbuf[32];
char *kbp = kbuf, *text = usertext + 2;
*kbp++ = c;
strcpy(usertext, " \\");
strcpy(exittext,"Exit: ENTER");
helptext[0] = 0;
line25();
while (((c = (coninc(0) & cmdmsk)) != '\r') && (c != '\n')) {
if ( c == '\b' ) {
if ( kbp > kbuf + 1 ) {
*--kbp = 0;
*--text = 0;
}
} else if ( kbp - kbuf < sizeof(kbuf) - 2 ) {
*kbp++ = c;
*text++ = c;
*text = 0;
}
line25();
}
*kbp = 0; kbp = kbuf;
c = xxesc(&kbp); /* Interpret it */
if (c >= 0) {
sendcharduplex((char)c);
return;
} else { /* Invalid backslash code. */
conoc(BEL);
return;
}
}
return;
case SP: /* Space, ignore */
return;
default: /* Other */
conoc(BEL);
return; /* Invalid esc arg, beep */
}
}
}
/* CHECKSCREENMODE -- Make sure we are in a usable mode */
int /* NOTE: not static, on purpose */
ttgwsiz() { /* Get Window Size */
if (xsize < 0 || ysize < 0)
checkscreenmode();
return((tt_rows < 1 || tt_cols < 1) ? 0 : 1);
}
static void
checkscreenmode() {
VIOMODEINFO m;
#ifdef COMMENT /* Moved to setcursormode() */
VIOINTENSITY vi;
vi.cb = sizeof(vi);
vi.type = 2;
vi.fs = 1;
VioSetState(&vi, 0);
#endif /* COMMENT */
m.cb = sizeof(m);
assert(VioGetMode(&m, 0) == 0);
/* Terminal screen not created yet, or user changed the screen size. */
if ( xsize != min(MAXCOL, m.col) || ysize != min(MAXROW, m.row) - 1 ) {
scrninitialised = 0;
if ( roll.buffer )
free(roll.buffer);
roll.buffer = NULL;
if ( vt100screen.scrncpy )
free(vt100screen.scrncpy);
vt100screen.scrncpy = NULL;
if ( commandscreen.scrncpy )
free(commandscreen.scrncpy);
commandscreen.scrncpy = NULL;
if ( savedscreen.scrncpy )
free(savedscreen.scrncpy);
savedscreen.scrncpy = NULL;
if ( helpscreen.scrncpy )
free(helpscreen.scrncpy);
helpscreen.scrncpy = NULL;
#ifdef OS2MOUSE
if ( mousescreen.scrncpy )
free(mousescreen.scrncpy);
mousescreen.scrncpy = NULL;
#endif /* OS2MOUSE */
tt_cols = xsize = min(MAXCOL, m.col);
tt_rows = ysize = min(MAXROW, m.row) - 1;
/*
If there is a scrolling window in effect, this will wipe it out. However,
this code is executed only upon the first CONNECT, or when the user changed
screen sizes while escaped back. Any nondefault scrolling region does not
make sense under these conditions anyway. The "if" clause is commented out
because leaving it in could do more harm than good, for example if the new
screen is smaller than the old scrolling region.
if (!relcursor)
*/
marginbot = ysize;
}
if ( !vt100screen.scrncpy ) {
vt100screen.scrncpy = malloc(xsize * (ysize + 1) * 2);
}
assert(vt100screen.scrncpy != NULL);
if ( !commandscreen.scrncpy )
commandscreen.scrncpy = malloc(xsize * (ysize + 1) * 2);
assert(commandscreen.scrncpy != NULL);
if ( !savedscreen.scrncpy )
savedscreen.scrncpy = malloc(xsize * (ysize + 1) * 2);
assert(savedscreen.scrncpy != NULL);
if ( !helpscreen.scrncpy )
helpscreen.scrncpy = malloc(xsize * (ysize + 1) * 2);
assert(helpscreen.scrncpy != NULL);
#ifdef OS2MOUSE
if ( !mousescreen.scrncpy )
mousescreen.scrncpy = malloc(xsize * (ysize + 1) * 2);
assert(mousescreen.scrncpy != NULL);
#endif /* OS2MOUSE */
}
static void
setcursormode() {
VIOMODEINFO vmi;
VIOCURSORINFO vci;
VIOINTENSITY vi;
int cell, bottom, top;
vmi.cb = sizeof(vmi);
VioGetMode(&vmi, 0);
cell = vmi.vres / vmi.row;
VioGetCurType(&vci, 0);
crsr_command = vci;
vci.cEnd = cell - 1;
vci.yStart = (tt_cursor == 0) ? cell - 2 :
cell - 1 - (cell - 2) * tt_cursor / 2;
VioSetCurType(&vci, 0);
/*
Note: For some reason, choosing vi.fs = 0 makes *everything* blink.
Receipt of "turn-on-blink" escape sequences turn off blinking. Thus,
everything is backwards. But when vi.fs = 1, the sense is not reversed.
A puzzle.
*/
vi.cb = sizeof(vi);
vi.type = 2; /* High-intensity vs blinking */
vi.fs = 1; /* 0 = blinking, 1 = hi intensity */
VioSetState(&vi, 0);
}
static void
restorecursormode() {
VioSetCurType(&crsr_command, 0);
}
#ifdef __32BIT__
/* C O N K B D H A N D L E R */
void
conkbdhandler(void *pArgList) {
int c, cm, cx, tx;
DosPostEventSem(threadsem2);
while (active) { /* Read the keyboard and write to comms line */
c = congks(1); /* Get keystroke */
if (!active) /* Exit if this happened */
break; /* (in any of various ways) */
if (c == -1) { /* like:... */
if (!active)
strcpy(termessage, "Carrier lost.\n");
continue;
}
cm = keymap[c]; /* Do key mapping */
if (cm == escape) { /* Is it the escape character? */
DosRequestMutexSem( hmtxScreenSem, SEM_INDEFINITE_WAIT ) ;
save_status_line(); /* Yes, save current status line. */
esc25(0); /* Make new one. */
c = keymap[congks(0)]; /* Get escape command. */
if (c == '?' || c == 'h' || c == 'H') { /* They want help menu. */
esc25(1); /* Show it */
c = popuphelp(1); /* Then get real escape command */
}
doesc(c); /* And process it */
restore_status_line(); /* Then restore status line */
DosReleaseMutexSem( hmtxScreenSem ) ;
} else { /* Ordinary character */
if (!keylock) /* If keyboard not locked, */
vt100key(c); /* go process it. */
}
} /* while (active) */
_endthread() ;
}
#endif /* __32BIT__ */
/* C O N E C T -- Perform CONNECT command */
int /* NOTE: Not static */
conect() {
USHORT len, x, y;
int i, c, cm; /* c is a character, but must be signed
* integer to pass thru -1, which is the
* modem disconnection signal, and is
* different from the character 0377 */
char errmsg[50], *erp, ac, bc;
#ifdef CK_APC
apcactive = FALSE;
#endif /* CK_APC */
if (!network && speed < 0) {
printf("Sorry, you must set speed first.\n");
return (0);
}
if ((escape < 0) || (escape > 0177)) {
printf("Escape character out of range: %d\n", escape);
return (0);
}
if (ttopen(ttname, &local, network ? -nettype : mdmtyp, 0) < 0) {
erp = errmsg;
sprintf(erp, "Sorry, can't open %s", ttname);
perror(errmsg);
return (0);
}
/* Condition console terminal and communication line */
if (ttvt(speed, flow) < 0) {
printf("Sorry, Can't condition communication line\n");
return (0);
}
if (!network && carrier != CAR_OFF && (ttgmdm() & BM_DCD) == 0) {
printf("No carrier detected on %s.\n",ttname);
printf("Hint: Use the DIAL command, or else SET CARRIER OFF.\n");
printf(
"If you want to make a network connection, use SET HOST or TELNET.\n");
return (0);
}
my_tt_type = tt_type; /* Remember prevailing type */
what = W_CONNECT; /* Keep track of what we're doing */
/* Will C-Kermit exit when user escapes back? */
esc_exit = (cflg || cnflg) && !stayflg;
esc_msg = esc_exit ? "Exit:" : "Prompt:";
/* Construct ENQ/Answerback message */
sprintf(answerback,"OS/2 C-Kermit %ld %s\n",
vernum,
tt_info[my_tt_type].x_name
);
/* Initialize Very Important Keys structure */
vik.help = 0;
vik.exit = 0;
vik.upscn = 0;
vik.dnscn = 0;
vik.upone = 0;
vik.dnone = 0;
vik.homscn = 0;
vik.endscn = 0;
vik.hangup = 0;
vik.xbreak = 0;
vik.lbreak = 0;
vik.dump = 0;
vik.prtscn = 0;
vik.os2 = 0;
vik.printff = 0;
vik.flipscn = 0;
vik.debug = 0;
vik.reset = 0;
vik.compose = 0;
for (i = 256; i < KMSIZE; i++) {
if (!vik.help && (keymap[i] == (F_KVERB | K_HELP)))
vik.help = i;
else if (!vik.exit && (keymap[i] == (F_KVERB | K_EXIT)))
vik.exit = i;
else if (keymap[i] == (F_KVERB | K_UPSCN))
vik.upscn = i;
else if (keymap[i] == (F_KVERB | K_DNSCN))
vik.dnscn = i;
else if (keymap[i] == (F_KVERB | K_UPONE))
vik.upone = i;
else if (keymap[i] == (F_KVERB | K_DNONE))
vik.dnone = i;
else if (keymap[i] == (F_KVERB | K_HOMSCN))
vik.homscn = i;
else if (keymap[i] == (F_KVERB | K_ENDSCN))
vik.endscn = i;
else if (!vik.hangup && (keymap[i] == (F_KVERB | K_HANGUP)))
vik.hangup = i;
else if (!vik.xbreak && (keymap[i] == (F_KVERB | K_BREAK)))
vik.xbreak = i;
else if (!vik.lbreak && (keymap[i] == (F_KVERB | K_LBREAK)))
vik.lbreak = i;
else if (!vik.dump && (keymap[i] == (F_KVERB | K_DUMP)))
vik.dump = i;
else if (!vik.flipscn && (keymap[i] == (F_KVERB | K_FLIPSCN)))
vik.flipscn = i;
else if (!vik.debug && (keymap[i] == (F_KVERB | K_DEBUG)))
vik.debug = i;
else if (!vik.reset && (keymap[i] == (F_KVERB | K_RESET)))
vik.reset = i;
else if (!vik.os2 && (keymap[i] == (F_KVERB | K_DOS)))
vik.os2 = i;
else if (!vik.prtscn && (keymap[i] == (F_KVERB | K_PRTSCN)))
vik.prtscn = i;
else if (!vik.printff && (keymap[i] == (F_KVERB | K_PRINTFF)))
vik.printff = i;
else if (!vik.compose && (keymap[i] == (F_KVERB | K_COMPOSE)))
vik.compose = i;
}
keymac = 0; /* Initialize \Kmacro flag */
keymacx = -1; /* and index */
outshift = inshift = 0; /* Initial SI/SO shift state. */
langsv = language; /* No language rules during CONNECT! */
language = L_USASCII;
if (debses) { /* Session debugging? */
tcs = TC_TRANSP; /* No character-set translation */
sxo = rxo = NULL; /* If so, no translation. */
sxi = rxi = NULL;
escstate = ES_NORMAL; /* No escape-sequence processing */
tt_wrap = TRUE; /* Always wrap */
} else { /* No session debugging */
tcs = gettcs(tcsr,tcsl); /* Get intermediate set. */
if (tcsr == tcsl) { /* Remote and local sets the same? */
sxo = rxo = NULL; /* If so, no translation. */
sxi = rxi = NULL;
} else { /* Otherwise, set up */
sxo = xls[tcs][tcsl]; /* translation function */
rxo = xlr[tcs][tcsr]; /* pointers for output functions */
sxi = xls[tcs][tcsr]; /* and for input functions. */
rxi = xlr[tcs][tcsl];
}
}
/*
C1 Control characters are possible only if the remote terminal
character set does not include graphic characters in the C1 area.
*/
c1controls = (tcsl != tcsr) && /* Transparent character-set */
(tcsr != FC_CP850) && /* or IBM code page */
(tcsr != FC_CP437) &&
(tcsr != FC_CP852) &&
(tcsr != FC_NEXT) && /* or NeXT character set */
(tcsr != FC_APPQD); /* or Apple Quickdraw */
#ifdef COMMENT
iskipesc =
#endif /* COMMENT */
oskipesc = (tcs != TC_TRANSP) && /* Not transparent */
(fcsinfo[tcsl].size == 128 || fcsinfo[tcsr].size == 128) && /* 7 bits */
(fcsinfo[tcsl].code != FC_USASCII);
#ifdef COMMENT
inesc =
#endif /* COMMENT */
outesc = ES_NORMAL; /* Initial state of recognizer */
#ifdef CK_BORDER
saveborder(); /* Save command-screen border */
#endif /* CK_BORDER */
checkscreenmode(); /* Initialize terminal emulator */
setcursormode();
VioGetCurPos(&y, &x, 0); /* Command screen cursor position */
wherex = x + 1;
wherey = y + 1;
savescreen(&commandscreen,wherex,wherey); /* Remember OS/2 screen */
colorcmd = commandscreen.scrncpy[(x + y * xsize) * 2 + 1];
scrninit();
restorescreen(&vt100screen); /* Put up previous terminal */
/* emulation screen, if any */
newcursor(); /* Install cursor */
conraw(); /* Put console in raw mode */
connoi(); /* No interrupts from console */
ipadl25(); /* Put up status line */
waittime = tt_ctstmo * 1000L; /* CTS timeout */
/* Create a thread to read the comms line and write to the screen */
active = 1; /* So thread 2 doesn't end at once */
quitnow = 0;
hangnow = 0;
termessage[0] = 0;
#ifdef __32BIT__
DosCreateEventSem(NULL, &threadsem, 0, 0);
DosResetEventSem(threadsem, &semcount);
threadid = _beginthread( &rdcomwrtscr, 0, THRDSTKSIZ, 0 ) ;
if ( threadid == -1 ) {
printf("Sorry, can't create thread\n");
return (0);
}
DosWaitEventSem(threadsem, -1L);
#else /* Not __32BIT__ */
DosSemSet(&threadsem); /* Thread 2 will clear this when it starts */
if (DosCreateThread(rdcomwrtscr, &threadid,
(PBYTE)(stack + THRDSTKSIZ))) {
printf("Sorry, can't create thread\n");
return (0);
}
DosSemWait(&threadsem, -1L);/* Wait for thread to start */
DosSemSet(&threadsem); /* Thread 2 will clear this on termination */
#endif /* __32BIT__ */
#ifdef __32BIT__
/* Use a separate thread for Keyboard handling */
DosCreateEventSem(NULL, &threadsem2, 0, 0);
DosResetEventSem(threadsem2, &semcount2);
threadid2 = _beginthread( &conkbdhandler, 0, THRDSTKSIZ, 0 ) ;
if ( threadid2 == -1) {
printf("Sorry, can't create thread\n");
return (0);
}
DosWaitEventSem(threadsem2, -1L);
#ifdef OS2MOUSE
if (tt_mouse)
os2_mouseon() ;
#endif /* OS2MOUSE */
while (active) {
active = network || /* I/O error on network connection */
(carrier == CAR_OFF) || /* Carrier dropped */
((ttgmdm() & BM_DCD) != 0);
DosSleep( 1000 ) ;
}
debug( F100,"Exiting connect mode","",0) ;
#ifdef COMMENT
/*
If APC commands come too quickly, this thread dies upon startup and its
threadid gets used by the mouse. So we can't wait for it to die. Why are
we waiting anyway? We no longer allow it to take direct control of the
keyboard, so even if it takes a couple of milliseconds to die off, there
shouldn't be any problems.
*/
DosWaitThread( &threadid2, DCWW_WAIT ) ;
debug( F100,"conkbdhandler() is dead","",0) ;
#endif /* COMMENT */
#ifdef OS2MOUSE
if (tt_mouse)
os2_mouseoff() ;
#endif /* OS2MOUSE */
#else /* Not __32BIT__ */
/* Perform keyboard handling in main thread */
while (active) { /* Read the keyboard and write to comms line */
c = congks(2); /* Get keystroke */
if (!active) /* Exit if this happened */
break; /* (in any of various ways) */
if (c == -1) { /* like:... */
active = network || /* I/O error on network connection */
(carrier == CAR_OFF) || /* Carrier dropped */
((ttgmdm() & BM_DCD) != 0);
if (!active)
strcpy(termessage, "Carrier lost.\n");
continue;
}
cm = keymap[c]; /* Do key mapping */
DosEnterCritSec(); /* Protect the runtime library */
if (cm == escape) { /* Is it the escape character? */
save_status_line(); /* Yes, save current status line. */
esc25(0); /* Make new one. */
c = keymap[congks(0)]; /* Get escape command. */
if (c == '?' || c == 'h' || c == 'H') { /* They want help menu. */
esc25(1); /* Show it */
c = popuphelp(1); /* Then get real escape command */
}
doesc(c); /* And process it */
restore_status_line(); /* Then restore status line */
} else { /* Ordinary character */
if (!keylock) /* If keyboard not locked, */
vt100key(c); /* go process it. */
}
DosExitCritSec(); /* Let others use runtime library */
} /* while (active) */
#endif /* __32BIT__ */
#ifdef __32BIT__
DosWaitThread(&threadid, 0);
debug(F100,"rdcomwrtscr() thread dead","",0) ;
DosCloseEventSem(threadsem);
#else
DosSemWait(&threadsem, -1L);/* Wait for other thread to terminate */
#endif
language = langsv; /* Restore language */
concooked(); /* Restore console to "cooked" mode */
savescreen(&vt100screen,wherex,wherey);
x = cursoron;
cursoron = TRUE; /* Needed for lgotoxy()... */
restoreborder(); /* Put back command-screen border */
restorescreen(&commandscreen); /* Put back command screen */
restorecursormode(); /* Put command-screen cursor back */
cursoron = x; /* Remember this for next time... */
if (termessage[0]!='\0') printf(termessage);
if (hangnow) {
#ifndef NODIAL
if (mdmhup() < 1)
#endif /* NODIAL */
tthang();
}
if (quitnow)
doexit(GOOD_EXIT,0);
what = W_NOTHING;
return (1);
}