char *connv = "OS/2 connect command, 13 Feb 89"; /* C K O C O N -- Kermit connect command for OS/2 systems */ /* * Author: Chris Adie (C.Adie@uk.ac.edinburgh) Copyright (C) 1988 Edinburgh * University Computing Service Permission is granted to any individual or * institution to use, copy, or redistribute this software so long as it is * not sold for profit, provided this copyright notice is retained. * * * Incorporates a VT102 emulator, together with its screen access routines. If * the code looks a bit funny sometimes, its because it was machine * translated to 'C'. */ /* * * =============================#includes===================================== */ #include "ckcker.h" /* Kermit definitions */ #include "ckcdeb.h" /* Typedefs, debug formats, etc */ #include /* Character types */ #include /* File io function declarations */ #include /* Process-control function declarations */ #include /* Standard library declarations */ #include #include #include /* Directory function declarations */ #include #include #define INCL_BASE #include /* * * =============================#defines====================================== */ #ifndef TRUE #define TRUE 1 #endif #ifndef FALSE #define FALSE 0 #endif #define SENDSTR2 sendstr #define SENDCHAR sendchar #define UPWARD 6 #define DOWNWARD 7 #define LBUFSIZE 144 /* No of lines in extended buffer */ #define DEFTABS \ "00000000T0000000T0000000T0000000T0000000T0000000T0000000T0000000T0000000T0000000"; /* * * =============================typedefs====================================== */ typedef char fulstring[256]; typedef int bool; typedef unsigned char screenmap[4000]; typedef struct ascreen_rec { /* Structure for saving screen info */ unsigned char ox; unsigned char oy; unsigned char att; screenmap scrncpy; } ascreen; /* * * =============================externals===================================== */ extern int local, speed, escape, duplex, parity, flow, seslog, cmask; extern char ttname[], sesfil[]; extern CHAR dopar(); /* * * =============================static=variables============================== */ static long twochartimes; static char termessage[80]; static FILE *lst; static bool lstclosed = TRUE; static char coloroftext = 7, colorofback = 0; static colorofunderline = 4; static ascreen vt100screen, commandscreen; static enum { mono, colour } adapter; unsigned char attribute, savedattribute, line25attribute, defaultattribute; static struct { unsigned reversed:1; unsigned blinking:1; unsigned underlined:1; unsigned bold:1; unsigned invisible:1; } attrib, savedattrib; static struct paging_record { unsigned char numlines; /* no. of lines in extended display buffer */ unsigned char topline; unsigned char botline; char *buffer; } paginginfo; static unsigned char wherex; static unsigned char wherey; static unsigned char margintop = 1; static unsigned char marginbot = 24; static int active; static long int threadsem; /* Semaphore to show thread is running */ static char usertext[(80) + 1]; static char exittext[(14) + 1]; static char helptext[(14) + 1]; static char filetext[(14) + 1]; static char hostname[(20) + 1]; static unsigned char graphicset[32] = { 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 }; static char htab[81] = DEFTABS /* Default tab settings */ static char answerback[81] = "OS/2 Kermit\n"; static int row; #ifdef US_CHAR static unsigned char g0 = 'B'; /* Character 35 is number sign */ static unsigned char g1 = 'B'; #else static unsigned char g0 = 'A'; /* Char 35 is pound (sterling) sign */ static unsigned char g1 = 'A'; #endif /* US_CHAR */ static unsigned char *g0g1 = &g0; static bool literal = FALSE; static bool wrapit; static bool printon = FALSE; static bool screenon = TRUE; static bool cursoron = TRUE;/* For speed, turn off when busy */ static bool relcursor = FALSE; static bool keypadnum = FALSE; static bool autowrap = FALSE; static bool ansi = TRUE; static bool keylock = FALSE; static bool vt52graphics = FALSE; static unsigned char achar; static int column; static unsigned char saveg0, saveg1, *saveg0g1; static bool saverelcursor, saved=FALSE; static bool dwl[24] = { FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE}; static bool dwls = FALSE; /* For optimisation */ static bool deccolm = FALSE; static bool decscnm = FALSE; static bool linemode = FALSE; static bool insertmode = FALSE; static bool cursorkey = TRUE; /* escape sequence processing buffer */ static bool escaping = FALSE; static int escnext = 1; static int esclast = 0; static unsigned char escbuffer[129]; static unsigned char sgrcols[8] = {0, 4, 2, 6, 1, 5, 3, 7}; /* * Send a character to the serial line in immediate mode, checking to avoid * overwriting a character already waiting to be sent. */ sendchar(unsigned char c) { int i=0; while (ttoci(c)<0 && i++<10) DosSleep(twochartimes); if (i>=10) { active = FALSE; strcpy(termessage,"Cannot transmit to serial port!\n"); } } /* ------------------------------------------------------------------ */ /* ipadl25 - */ /* ------------------------------------------------------------------ */ static void ipadl25() { strcpy(usertext, " C-Kermit VT102"); sprintf(filetext, "%1d baud", speed); strcpy(helptext, "Help: ^ ?"); helptext[7] = ctl(escape); strcpy(exittext, "Exit: ^ c"); exittext[7] = ctl(escape); strcpy(hostname, ttname); line25(); } /* ------------------------------------------------------------------ */ /* CursorUp - */ /* ------------------------------------------------------------------ */ static void cursorup() { if ((relcursor ? margintop : 1) != wherey) lgotoxy(wherex, wherey - 1); } /* ------------------------------------------------------------------ */ /* CursorDown - */ /* ------------------------------------------------------------------ */ static void cursordown() { if ((relcursor ? marginbot : 24) != wherey) lgotoxy(wherex, wherey + 1); } /* ------------------------------------------------------------------ */ /* CursorRight - */ /* ------------------------------------------------------------------ */ static void cursorright() { if (wherex < (dwl[wherey - 1] ? 79 : 80)) lgotoxy(wherex + 1, wherey); } /* ------------------------------------------------------------------ */ /* CursorLeft - */ /* ------------------------------------------------------------------ */ static void cursorleft() { if (wherex > 1) lgotoxy(wherex - 1, wherey); } /* ------------------------------------------------------------------ */ /* ReverseScreen */ /* ------------------------------------------------------------------ */ static void reversescreen() { unsigned char back; unsigned char fore; int i, r, c; USHORT n; unsigned char cell[160]; n = sizeof(cell); for (r = 0; r < 24; r++) { /* flip row */ VioReadCellStr(cell, &n, r, 0, 0); for (c = 1; c < n; c += 2) { /* do each cell in row */ back = (cell[c] & 0x70) >> 4; fore = (cell[c] & 0x07); if (fore == colorofunderline) cell[c] ^= 0x70; else cell[c] = (cell[c] & 0x88) | fore << 4 | back; } VioWrtCellStr(cell, n, r, 0, 0); } } /* ------------------------------------------------------------------ */ static void doprinton(bool on) { if (on) { if (lstclosed) { lst = fopen("prn", "w"); lstclosed = FALSE; } } else { if (!(lstclosed)) { fclose(lst); lstclosed = TRUE; } } printon = on; } /* ----------------------------------------------------------------- */ /* ClrScreen - */ /* ----------------------------------------------------------------- */ static void clrscreen() { int i, j; int nlines; USHORT n; char cells[80][2]; /* copy lines on screen to extended display buffer */ n = sizeof(cells); for (i = 23; i >= 0; i--) { VioReadCellStr((char *) cells, &n, i, 0, 0); for (j = 0; j < 80; j++) { if (cells[j][0] != 32) break; } if (j < 80) break; } nlines = i; /* no. of nonblank lines-1 */ for (i = 0; i <= nlines; ++i) { paginginfo.botline = (paginginfo.botline + 1) % LBUFSIZE; if (paginginfo.numlines < LBUFSIZE) paginginfo.numlines = paginginfo.numlines + 1; else paginginfo.topline = (paginginfo.topline + 1) % LBUFSIZE; VioReadCellStr((paginginfo.buffer + 160 * paginginfo.botline), &n, i, 0, 0); } for (i = 0; i < 24; i++) dwl[i] = FALSE; dwls = FALSE; clearscreen(); } static void readmchar_escape() { /* Stores character in achar directly */ if (escnext <= esclast) { achar = escbuffer[escnext]; escnext = escnext + 1; } else achar = 0; } static int pnumber(achar) unsigned char *achar; { int num = 0; while (isdigit(*achar)) { /* get number */ num = (num * 10) + (*achar) - 48; readmchar_escape(); } return (num); } static void clreoscr_escape() { char cell[2]; int i; if (wherex == 1 && wherey == 1) { clrscreen(); return; } cell[0] = ' '; cell[1] = defaultattribute; i = 1920 - (((wherey - 1) * 80) + (wherex - 1)); VioWrtNCell(cell, i, wherey - 1, wherex - 1, 0); for (i = wherey - 1; i < 24; i++) dwl[i] = FALSE; dwls = FALSE; for (i = 0; i < 24; i++) if (dwl[i]) { dwls = TRUE; break; } } static void clrboscr_escape() { char cell[2]; int i; cell[0] = ' '; cell[1] = defaultattribute; i = ((wherey - 1) * 80) + wherex; VioWrtNCell(cell, i, 0, 0, 0); for (i = 0; i < wherey; i++) dwl[i] = FALSE; dwls = FALSE; for (i = 0; i < 24; i++) if (dwl[i]) { dwls = TRUE; break; } } static void clrbol_escape() { char cell[2]; cell[0] = ' '; cell[1] = defaultattribute; VioWrtNCell(cell, wherex, wherey - 1, 0, 0); } static void clrline_escape() { char cell[2]; cell[0] = ' '; cell[1] = defaultattribute; VioWrtNCell(cell, 80, wherey - 1, 0, 0); } static void decdwl_escape(bool dwlflag) { unsigned char linenumber; unsigned char newx; char cells[80][2]; int i; USHORT n; /* Decdwl */ linenumber = wherey - 1; if (dwlflag != dwl[linenumber]) { /* change size */ n = sizeof(cells); VioReadCellStr((char *) cells, &n, linenumber, 0, 0); if (dwlflag) { /* make this line double size */ for (i = 39; i >= 0; --i) { /* expand */ cells[2 * i][0] = cells[i][0]; cells[2 * i + 1][0] = ' '; } newx = (wherex - 1) * 2 + 1; dwls = TRUE; } else { /* make this line single size */ for (i = 0; i <= 39; ++i) cells[i][0] = cells[2 * i][0]; for (i = 40; i <= 79; ++i) cells[i][0] = ' '; newx = (wherex - 1) / 2 + 1; dwls = FALSE; for (i = 0; i < 24; i++) if (dwl[i]) { dwls = TRUE; break; } } VioWrtCellStr((char *) cells, n, linenumber, 0, 0); dwl[linenumber] = dwlflag; if (newx >= 80) newx = 79; lgotoxy(newx, wherey); } } 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; escaping = FALSE; escnext = 1; readmchar_escape(); if (screenon || (achar == '[')) { /* screen escape sequences */ switch (achar) { /* First Level */ case '[': { /* Left square bracket */ readmchar_escape(); switch (achar) {/* Second level */ case 'A': cursorup(); wrapit = FALSE; break; case 'B': cursordown(); wrapit = FALSE; break; case 'C': cursorright(); if (dwl[wherey - 1]) cursorright(); break; case 'D': cursorleft(); if (dwl[wherey - 1]) cursorleft(); break; case 'J': /* Erase End of Display */ clreoscr_escape(); break; case 'K': clrtoeol(); break; case '?': private = TRUE; readmchar_escape(); goto LB2001; case 'f': case 'H': /* Cursor Home */ lgotoxy(1, relcursor ? margintop : 1); break; case 'g': 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, 24); lgotoxy(1, 1); break; case 'c': case 'h': case 'l': case 'n': case 'x': pn[1] = 0; private = FALSE; k = 1; goto LB2003; case ';': 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] */ readmchar_escape(); k++; if (achar == '?') { readmchar_escape(); } pn[k] = pnumber(&achar); } pn[k + 1] = 1; LB2003: switch (achar) { /* third level */ case 'A': do { cursorup(); wrapit = FALSE; pn[1] = pn[1] - 1; } while (!(pn[1] <= 0)); break; case 'B': do { cursordown(); wrapit = FALSE; pn[1] = pn[1] - 1; } while (!(pn[1] <= 0)); break; case 'C': do { cursorright(); if (dwl[wherey - 1]) cursorright(); pn[1] = pn[1] - 1; } while (pn[1] > 0); break; case 'D': do { cursorleft(); if (dwl[wherey - 1]) cursorleft(); pn[1] = pn[1] - 1; } while (pn[1] > 0); break; case 'f': case 'H': /* Direct cursor address */ if (pn[1] == 0) pn[1] = 1; if (relcursor) pn[1] += margintop - 1; if (pn[2] == 0) pn[2] = 1; if (dwl[pn[1] - 1]) { pn[2] = 2 * pn[2] - 1; if (pn[2] > 80) pn[2] = 79; } else if (pn[2] > 80) pn[2] = 80; wrapit = FALSE; lgotoxy(pn[2], pn[1]); break; case 'c': /* Device Attributes */ if (pn[1] == 0) sendstr("[?6;2c"); break; case 'g': if (pn[1] == 3) { /* clear all tabs */ for (j = 1; j <= 80; ++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 */ cursorkey = TRUE; break; case 2: /* DECANM : ANSI/VT52 */ ansi = TRUE; vt52graphics = FALSE; break; case 3: /* DECCOLM : Col = 132 */ deccolm = TRUE; clrscreen(); break; case 4: /* DECSCLM */ break; case 5: /* DECSCNM */ if (decscnm) break; /* Already set */ decscnm = TRUE;; reversescreen(); defaultattribute = (coloroftext << 4) | colorofback; attribute = defaultattribute; if (attrib.reversed) { back = attribute & 0x07; fore = (attribute & 0x70) >> 4; if (adapter == colour && attrib.underlined) { fore = colorofunderline; } attribute = (back << 4) | fore; } if (attrib.underlined) { if (adapter == mono && !attrib.reversed) attribute = (attribute & 0xF8) | colorofunderline; } if (attrib.blinking) attribute |= 0x80; if (attrib.bold) attribute |= 8; if (attrib.invisible) { i = (attribute & 0xF8); attribute = i | ((i >> 4) & 7); } break; case 6: /* DECOM : Relative origin */ relcursor = TRUE; lgotoxy(1, margintop); break; case 7: /* DECAWM */ autowrap = TRUE; break; case 8: /* DECARM */ break; case 9: /* DECINLM */ break; default: break; } else switch (pn[j]) { case 2: /* Keyboard locked */ keylock = TRUE; break; case 4: /* Ansi insert mode */ insertmode = TRUE; break; case 20: /* Ansi linefeed mode */ linemode = TRUE; break; default: break; } break; case 'l': /* Reset Mode */ for (j = 1; j <= k; ++j) if (private) switch ((pn[j])) { /* Field specs */ case 1: /* DECCKM */ cursorkey = FALSE; break; case 2: /* DECANM : ANSI/VT52 */ ansi = FALSE; vt52graphics = FALSE; break; case 3: /* DECCOLM : 80 col */ deccolm = FALSE; clrscreen(); break; case 4: /* DECSCLM */ break; case 5: /* DECSCNM */ if (!decscnm) break; decscnm = !decscnm; reversescreen(); defaultattribute = (colorofback << 4) | coloroftext; attribute = defaultattribute; if (attrib.reversed) { back = attribute & 0x07; fore = (attribute & 0x70) >> 4; if (adapter == colour && attrib.underlined) { fore = colorofunderline; } attribute = (back << 4) | fore; } if (attrib.underlined) { if (adapter == mono && !attrib.reversed) attribute = (attribute & 0xF8) | colorofunderline; } if (attrib.blinking) attribute |= 0x80; if (attrib.bold) attribute |= 8; if (attrib.invisible) { i = (attribute & 0xF8); attribute = i | ((i >> 4) & 7); } break; case 6: /* DECOM : Relative origin */ relcursor = FALSE; lgotoxy(1, 1); break; case 7: /* DECAWM */ autowrap = FALSE; break; case 8: /* DECARM */ break; case 9: /* DECINLM */ break; default: break; } else switch (pn[j]) { case 2: /* Keyboard unlocked */ keylock = FALSE; break; case 4: /* Ansi insert mode */ insertmode = FALSE; break; case 20: /* Ansi linefeed mode */ linemode = FALSE; break; default: break; } break; case 'i': /* Printer Screen on / off */ for (j = 1; j <= k; ++j) switch ((pn[j])) { /* Field specs */ case 4: doprinton(FALSE); break; case 5: doprinton(TRUE); break; case 6: screenon = FALSE; break; case 7: screenon = TRUE; break; default: break; } break; case 'q': break; case 'n': if (pn[1] == 5) { /* Device Status Report */ sendstr("[0n"); } else if (pn[1] == 6) { /* Cursor Position * Report */ sendstr("["); sprintf(tempstr, "%1d", (int) wherey); /* row */ SENDCHAR(tempstr[0]); if (tempstr[1]) SENDCHAR(tempstr[1]); SENDCHAR(';'); sprintf(tempstr, "%1d", (int) wherex); /* col */ SENDCHAR(tempstr[0]); if (tempstr[1]) SENDCHAR(tempstr[1]); SENDCHAR('R'); } break; case 'x': /* Request terminal Parameters */ if (pn[1] > 1) break; tempstr[0] = '['; tempstr[1] = (pn[1] == 0) ? '2' : '3'; tempstr[2] = ';'; switch (parity) { case 'e': tempstr[3] = '5'; tempstr[5] = '2'; break; case 'o': tempstr[3] = '4'; tempstr[5] = '2'; break; case 0: tempstr[3] = '1'; tempstr[5] = '1'; break; default: tempstr[3] = '1'; tempstr[5] = '2'; 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 = 120; break; } sprintf(&tempstr[6], ";%d;%d;1;0x", i, i); sendstr(tempstr); break; case 'm': case '}': for (j = 1; j <= k; ++j) switch ((pn[j])) { /* Field specs */ case 0: /* normal */ attribute = defaultattribute; attrib.blinking = FALSE; attrib.bold = FALSE; attrib.invisible = FALSE; attrib.underlined = FALSE; attrib.reversed = FALSE; break; case 1: /* bold */ attrib.bold = TRUE; attribute |= 8; break; case 4: /* underline */ if (attrib.underlined) break; attrib.underlined = TRUE; if (adapter == mono && attrib.reversed) break; attribute = (attribute & 0xF8) | colorofunderline; break; case 5: /* blink */ attrib.blinking = TRUE; attribute |= 0x80; break; case 7: /* reverse video */ if (attrib.reversed) break; attrib.reversed = TRUE; fore = defaultattribute >> 4; back = defaultattribute & 0x07; if (adapter == colour && attrib.underlined) { fore = colorofunderline; } if (attrib.invisible) fore = back; attribute = (attribute & 0x88) | back << 4 | fore; break; case 8: /* invisible */ if (attrib.invisible) break; attrib.invisible = TRUE; i = (attribute & 0xF8); attribute = i | ((i >> 4) & 7); break; case 30: case 31: case 32: case 33: case 34: case 35: case 36: case 37: /* select foreground */ i = (attribute & 248); attribute = (i | sgrcols[pn[j] - 30]); break; case 40: case 41: case 42: case 43: case 44: case 45: case 46: case 47: /* select back ground */ i = (attribute & 143); l = sgrcols[pn[j] - 40]; attribute = (i | ((l << 4))); break; default: break; } break; case 'r': /* set margin */ if ((k < 2) || (pn[2] == 0)) pn[2] = 24; if (pn[1] == 0) pn[1] = 1; if ((pn[1] > 0) && (pn[1] < pn[2]) && (pn[2] < 25)) { setmargins(pn[1], pn[2]); lgotoxy(1, relcursor ? margintop : 1); } break; case 'J': switch ((pn[1])) { case 0: /* clear to end of screen */ clreoscr_escape(); break; case 1: /* clear to beginning */ clrboscr_escape(); break; case 2: /* clear all of screen */ clrscreen(); break; default: break; } break; case 'K': switch ((pn[1])) { case 0: /* clear to end of line */ clrtoeol(); break; case 1: /* clear to beginning */ clrbol_escape(); break; case 2: /* clear line */ clrline_escape(); break; default: break; } break; case 'L': /* Insert lines */ for (i = 1; i <= pn[1]; ++i) scroll(DOWNWARD, wherey - 1, marginbot - 1); break; case 'M': /* Delete lines */ for (i = 1; i <= pn[1]; ++i) scroll(UPWARD, wherey - 1, marginbot - 1); break; case '@': /* Insert characters */ blankcell[0] = ' '; blankcell[1] = defaultattribute; pn[1] *= dwl[wherey - 1] ? 2 : 1; if (pn[1] > 81 - wherex) pn[1] = 81 - wherex; VioScrollRt(wherey - 1, wherex - 1, wherey - 1, 79, pn[1], blankcell, 0); break; case 'P': /* DeleteChar */ blankcell[0] = ' '; blankcell[1] = defaultattribute; pn[1] *= dwl[wherey - 1] ? 2 : 1; if (pn[1] > 81 - wherex) pn[1] = 81 - wherex; VioScrollLf(wherey - 1, wherex - 1, wherey - 1, 79, pn[1], blankcell, 0); break; default: break; } } break; } } /* Left square bracket */ break; case '7': /* Save cursor position */ saved = TRUE; row = wherey; column = wherex; savedattribute = attribute; savedattrib = attrib; saverelcursor = relcursor; saveg0 = g0; saveg1 = g1; saveg0g1 = g0g1; break; case '8': /* Restore Cursor Position */ if (!saved) { /* Home cursor */ lgotoxy(1, relcursor ? margintop : 1); break; } saved = FALSE; lgotoxy(column, row); attribute = savedattribute; attrib = savedattrib; relcursor = saverelcursor; g0 = saveg0; g1 = saveg1; g0g1 = saveg0g1; break; case 'A': if (!ansi) /* VT52 control */ cursorup(); break; case 'B': if (!(ansi)) /* VT52 control */ cursordown(); break; case 'C': if (!(ansi)) /* VT52 control */ cursorright(); break; case 'D': if (!(ansi)) /* VT52 control */ cursorleft(); else { /* Index */ if ((wherey >= marginbot)) scroll(UPWARD, margintop - 1, marginbot - 1); else cursordown(); } break; case 'E': /* Next Line */ wrtch(13); wrtch(10); break; case 'F': if (!ansi) vt52graphics = TRUE; break; case 'G': if (!ansi) vt52graphics = FALSE; break; case 'H': if (ansi) { /* Set Tab Stop */ htab[wherex] = 'T'; } /* Set Tab Stop */ else lgotoxy(1, 1); /* VT52 control */ break; case 'I': if (!(ansi)) { /* VT52 control */ if ((margintop < wherey)) cursorup(); else scroll(DOWNWARD, margintop - 1, marginbot - 1); } break; case 'J': if (!(ansi)) /* VT52 control */ clreoscr_escape(); break; case 'K': if (!(ansi)) /* VT52 control */ clrtoeol(); break; case 'M': /* Reverse Index */ if (margintop >= wherey) scroll(DOWNWARD, margintop - 1, marginbot - 1); else cursorup(); break; case 'Y': if (!(ansi)) { /* VT52 control */ /* direct cursor address */ readmchar_escape(); row = achar - 31; readmchar_escape(); column = achar - 31; lgotoxy(column, row); } /* direct cursor address */ break; case 'Z': if (ansi) { /* Device Attributes */ /* Send Esc[?6;2c */ sendstr("[?6;2c"); } /* Device Attributes */ else /* VT52 control */ SENDSTR2("/Z"); break; case 'c': /* Reset */ defaultattribute = coloroftext + (colorofback << 4); attribute = defaultattribute; attrib.blinking = FALSE; attrib.bold = FALSE; attrib.invisible = FALSE; attrib.underlined = FALSE; attrib.reversed = FALSE; g0 = g1 = 'A'; g0g1 = &g0; printon = FALSE; screenon = TRUE; vt52graphics = FALSE; saved = FALSE; linemode = FALSE; insertmode = FALSE; cursorkey = TRUE; keypadnum = FALSE; autowrap = FALSE; ansi = TRUE; keylock = FALSE; deccolm = decscnm = FALSE; for (i = 0; i < 24; i++) dwl[i] = FALSE; dwls = FALSE; for (i = 1; i < 80; i++) htab[i] = (i % 8) == 0 ? 'T' : '0'; relcursor = FALSE; setmargins(1, 24); clrscreen(); break; case '#': /* Esc # sequence */ readmchar_escape(); 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': { char cell[2]; cell[0] = 'E'; cell[1] = 7; /* Self Test */ VioWrtNCell(cell, 1920, 0, 0, 0); setmargins(1, 24); lgotoxy(1, 1); } break; /* Self Test */ default: break; } break; /* Esc # sequence */ case '=': keypadnum = FALSE; break; case '>': keypadnum = TRUE; break; case '<': /* VT52 control */ ansi = TRUE; break; case '(': readmchar_escape(); g0 = achar; break; case ')': readmchar_escape(); g1 = achar; break; default: if (achar == 12) { lgotoxy(1, 1); clrscreen(); } break; } /* First Level Case */ } /* screen escape sequences */ if (printon) { fprintf(lst, "%c", 27); if (esclast > 0) { /* print esc sequence */ for (i = 1; i <= esclast; ++i) fprintf(lst, "%c", escbuffer[i]); } } } /* ================================================================== */ /* */ /* VT100 emulate a dec vt100 terminal writing a character */ /* */ /* ================================================================== */ static void vt100(vtch) unsigned char vtch; { int i, j; char *s, str[2]; /* ----------------------------------------------------------------- */ /* ------------------------------------------------------------------ */ /* vt100 */ if (screenon) { if (vtch < 32) { /* Control Character */ achar = vtch; /* Let the rest of this module see the value */ switch (achar) { case LF: if (linemode) wherex=1; wrtch(achar); break; case CR: wrtch(achar); break; /* ESC */ case 27: vtescape(); break; case 14: /* SO */ g0g1 = &g1; break; /* SI */ case 15: g0g1 = &g0; break; /* BS */ case 8: wrtch(achar); break; case 12: /* FF */ case 11: /* VT */ /* take as lf */ achar = 10; wrtch(10); break; case 7: /* BEL */ bleep(); break; case 5: /* ENQ */ s = answerback; while (*s) SENDCHAR(*s++); break; case 9: /* tab character */ j = dwl[wherey - 1] ? 2 : 1; i = wherex; if (j == 2 && htab[(i - 1) / j + 1] == 'T') { i++; cursorright(); } if (i < 80) do { i++; cursorright(); } while ((htab[(i - 1) / j + 1] != 'T') && (i < 81 - j)); break; default: /* ignore it */ break; } /* end of Control Character */ } else { if (vtch != DEL) { /* Normal char */ if (ansi) { if (*g0g1 == 'A') { /* UK ascii set */ if (vtch == 35) vtch = 156; } else if ((*g0g1 == '0') && (95 <= vtch) && (vtch <= 126)) { literal = TRUE; vtch = graphicset[vtch - 95]; } } else { if (vt52graphics && (95 <= vtch) && (vtch <= 126)) { literal = TRUE; vtch = graphicset[vtch - 95]; } } if (wherex != (dwl[wherey - 1] ? 79 : 80)) { wrtch(vtch); if (dwl[wherey - 1]) wrtch(' '); wrapit = FALSE; } else { if (wrapit) { /* Next line */ if (marginbot <= wherey) { /* Scroll up */ scroll(UPWARD, margintop - 1, marginbot - 1); lgotoxy(1, wherey); } else lgotoxy(1, wherey + 1); wrtch(vtch); if (dwl[wherey - 1]) wrtch(' '); wrapit = FALSE; } else { /* put char on col 80 */ i = dwl[wherey - 1] ? 2 : 1; str[0] = vtch; str[1] = ' '; VioWrtCharStrAtt(&vtch, i, wherey - 1, 80 - i, &attribute, 0); literal = FALSE; if ((autowrap && !deccolm)) wrapit = TRUE; } } } /* Normal char */ } } if (printon && (vtch != 27)) fprintf(lst, "%c", vtch); } /* ------------------------------------------------------------------ */ /* Vt100read - */ /* ------------------------------------------------------------------ */ /* save current status of screen */ static void savescreen(scrn) ascreen *scrn; { USHORT n = sizeof(screenmap); scrn->ox = wherex; scrn->oy = wherey; scrn->att = attribute; VioReadCellStr((char *) (scrn->scrncpy), &n, 0, 0, 0); } /* restore state of screen */ static void restorescreen(scrn) ascreen *scrn; { movetoscreen(scrn->scrncpy, 1, 1, 4000); attribute = scrn->att; wherey = scrn->oy; wherex = scrn->ox; lgotoxy(wherex, wherey); } static void sendcharduplex(unsigned char c) { SENDCHAR(c); if (duplex) { cwrite(c); if (seslog) if (zchout(ZSFILE, c) < 0) seslog = 0; } } static void sendstrduplex(unsigned char *s) { SENDCHAR(27); if (duplex) { cwrite(27); if (seslog) if (zchout(ZSFILE, 27) < 0) seslog = 0; } while (*s) { SENDCHAR(*s); if (duplex) { cwrite(*s); if (seslog) if (zchout(ZSFILE, *s) < 0) seslog = 0; } s++; } } static void vt100read(a, b) unsigned char a, b; { unsigned char achar; unsigned char bchar; int i; int il; char str[3]; int prt; int st; unsigned char nolblines; unsigned char linesleft; unsigned char nextline; unsigned char nlines; ascreen savedscreen;/* screen save info */ achar = a; bchar = b; LB1: if (((achar == 8) && (bchar == 14))) { /* backspace is mapped to del */ achar = 127; bchar = 0; } if (achar != 0) { sendcharduplex(achar); if (achar == CR && linemode) sendcharduplex(LF); } else { switch ((int) (bchar)) { case 72: /* up */ if (ansi) { if (cursorkey) sendstrduplex("OA"); else sendstrduplex("[A"); } else sendstrduplex("A"); break; case 75: /* left */ if (ansi) { if (cursorkey) sendstrduplex("OD"); else sendstrduplex("[D"); } else sendstrduplex("D"); break; case 77: /* right */ if (ansi) { if (cursorkey) sendstrduplex("OC"); else sendstrduplex("[C"); } else sendstrduplex("C"); break; case 80: /* down */ if (ansi) { if (cursorkey) sendstrduplex("OB"); else sendstrduplex("[B"); } else sendstrduplex("B"); break; case 15: /* Backtab */ /* backspace */ sendcharduplex(8); break; case 83: /* delete */ sendcharduplex(127); break; case 59: /* PF1 */ if (ansi) sendstrduplex("OP"); else sendstrduplex("P"); break; case 60: /* PF2 */ if (ansi) sendstrduplex("OQ"); else sendstrduplex("Q"); break; case 61: /* PF3 */ if (ansi) sendstrduplex("OR"); else sendstrduplex("R"); break; case 62: /* PF4 */ if (ansi) sendstrduplex("OS"); else sendstrduplex("S"); break; case 120: case 121: case 122: case 123: case 124: case 125: case 126: case 127: case 128: case 129: /* numeric 1-9,0 */ { bchar = 'q' + bchar - 120; if (bchar == 'z') bchar = 'p'; /* alt 0 */ if (ansi) strcpy(str, "O "); else strcpy(str, "? "); str[1] = bchar; sendstrduplex(str); } break; case 63: case 64: /* numeric - */ if (ansi) sendstrduplex("Om"); else sendstrduplex("?m"); break; case 65: case 66: /* numeric , */ if (ansi) sendstrduplex("Ol"); else sendstrduplex("?l"); break; case 67: /* numeric + */ if (ansi) sendstrduplex("On"); else sendstrduplex("?n"); break; case 68: /* numeric enter */ if (ansi) sendstrduplex("OM"); else sendstrduplex("?M"); break; case 71: /* Home */ { strcpy(usertext, " Scroll lock on"); strcpy(exittext, "Exit: Home"); *helptext = '\0'; line25(); do scankey(&(achar), &(bchar)); while (!((achar == 0) && (bchar == 71))); ipadl25(); } break; case 81: /* Page down */ bleep(); /* since not in extened display mode */ break; case 73: /* Page up enter extended display mode */ if (paginginfo.numlines == 0) bleep(); else { savescreen(&savedscreen); killcursor(); linesleft = paginginfo.numlines; nextline = paginginfo.botline; do { if (bchar == 73) { if (linesleft == 0) bleep(); else { /* scroll up a page */ nlines = linesleft; if (nlines > 24) nlines = 24; { for (il = 1; il <= nlines; ++il) { scroll(DOWNWARD, 0, 23); movetoscreen(paginginfo.buffer + 160 * nextline, 1, 1, 160); if (nextline == 0) nextline = LBUFSIZE - 1; else nextline = nextline - 1; } il--; } linesleft = linesleft - nlines; } } else if (bchar == 81) { nlines = 24; do { nextline = nextline + 1; if (nextline >= LBUFSIZE) nextline = 0; linesleft = linesleft + 1; /* lines of ext display above top of the screen */ nolblines = paginginfo.numlines - linesleft; /* no. of ext disp buffer lines on screen */ scroll(UPWARD, 0, 23); if (nolblines >= 24) { /* move from buffer */ i = nextline; i = (i + 24); if (i >= LBUFSIZE) i = i - LBUFSIZE; movetoscreen(paginginfo.buffer + 160 * i, 1, 24, 160); } else { /* move from the screen copy */ movetoscreen(&(savedscreen.scrncpy[(23 - nolblines) * 160]), 1, 24, 160); } nlines = nlines - 1; } while (!(((nlines == 0) || (linesleft == paginginfo.numlines)))); } else linesleft = paginginfo.numlines; if (linesleft != paginginfo.numlines) { strcpy(helptext, "PgUp : up"); strcpy(exittext, "PgDn : down"); *usertext = '\0'; *filetext = '\0'; *hostname = '\0'; line25(); scankey(&(achar), &(bchar)); } } while (linesleft != paginginfo.numlines); restorescreen(&savedscreen); newcursor(); ipadl25(); if (((achar != 0) || (bchar != 45))) goto LB1; /* to process key */ } break; default: break; } /* of case bchar */ } } /* ------------------------------------------------------------------ */ /* cwrite */ /* ------------------------------------------------------------------ */ cwrite(ch) unsigned char ch; { { /* check and process escape sequence */ /* escape */ if (ch == 27) { escaping = TRUE; esclast = 0; } else { if (!(escaping)) { /* can send it to vt100 to be processed */ vt100(ch); } else { /* in the middle of an escape sequence */ if (((ch == 24) || (ch == 26))) /* cancelled */ escaping = FALSE; else { if (ch < 32) { if (ch == 8) { /* Backspace */ if (esclast >= 1) esclast--; } } else { /* add to control string */ if (esclast < 128) { /* add to buffer */ esclast = esclast + 1; escbuffer[esclast] = ch; } /* now check to see if sequence complete */ { if (ansi) { if (escbuffer[1] != '[') { char c = escbuffer[1]; if ((c != '#' && c != '(' && c != ')' && c != 'O' && c != '?') || esclast >= 2) { if ((escbuffer[1] != 'Y')) vtescape(); else { if ((esclast == 3)) vtescape(); } } } else { /* check for terminating character */ if ((((64 <= ch) && (ch <= 126)) && (esclast > 1))) vtescape(); } } else { /* vt52 mode */ if ((escbuffer[1] != 'Y')) vtescape(); else { if (esclast == 3) vtescape(); } } } } } } } } } /*---------------------------------------------------------------------------*/ /* scankey */ /*---------------------------------------------------------------------------*/ scankey(ach, bch) unsigned char * ach, *bch; { /* * Wait for a keypress, return the ASCII code in *ach and the scan in * *bch */ KBDKEYINFO k; KbdCharIn(&k, 0, 0); *ach = k.chChar; *bch = k.chScan; if (*ach == 0xE0) /* Extended scan code */ if (*bch >= 0x47 && *bch <= 0x53) *ach = 0; } /*---------------------------------------------------------------------------*/ /* scrninit */ /*---------------------------------------------------------------------------*/ static int scrninitialised = 0; scrninit() { SEL selector; if (!scrninitialised) { scrninitialised = 1; defaultattribute = (colorofback << 4) + coloroftext; attribute = defaultattribute; line25attribute = (coloroftext << 4) + colorofback; /* Initialise paging info */ if (DosAllocSeg(LBUFSIZE * 160, &selector, 0)) { printf("\nDosAllocSeg fails in scrninit\n"); exit(1); } paginginfo.buffer = MAKEP(selector, 0); paginginfo.numlines = 0; paginginfo.topline = 0; paginginfo.botline = LBUFSIZE - 1; clearscreen(); savescreen(&vt100screen); } } /*---------------------------------------------------------------------------*/ /* bleep */ /*---------------------------------------------------------------------------*/ bleep() { DosBeep(440, 200); } /*---------------------------------------------------------------------------*/ /* wrtch */ /*---------------------------------------------------------------------------*/ wrtch(unsigned char ch) { unsigned char cell[2]; if (ch >= ' ' || literal) { /* Normal character */ if (ansi && insertmode) { cell[0] = ch; cell[1] = attribute; VioScrollRt(wherey - 1, wherex - 1, wherey - 1, 79, 1, cell, 0); } else VioWrtCharStrAtt(&ch, 1, wherey - 1, wherex - 1, &attribute, 0); literal = FALSE; if (++wherex > 80) { wherex = 1; wrtch(LF); } } else { /* Control character */ switch (ch) { case LF: if (wherey == marginbot) { if (margintop == 1) toplinetocyclicbuffer(); scroll(UPWARD, margintop - 1, marginbot - 1); } else { wherey++; if (wherey == 25) wherey--; } break; case CR: wherex = 1; break; case BS: if (wherex > 1) wherex--; break; case 12: if (wherex < 80) wherex++; break; case BEL: DosBeep(400, 350); break; default:{ /* Ignore */ } } } if (cursoron) VioSetCurPos(wherey - 1, wherex - 1, 0); } /*---------------------------------------------------------------------------*/ /* clearscreen */ /*---------------------------------------------------------------------------*/ clearscreen() { char cell[2]; cell[0] = ' '; cell[1] = defaultattribute; VioWrtNCell(cell, 1920, 0, 0, 0); lgotoxy(1, 1); } /*---------------------------------------------------------------------------*/ /* lgotoxy */ /*---------------------------------------------------------------------------*/ lgotoxy(x, y) char x, y; { wherex = x; wherey = y; if (cursoron) VioSetCurPos(wherey - 1, wherex - 1, 0); } /*---------------------------------------------------------------------------*/ /* scroll */ /*---------------------------------------------------------------------------*/ scroll(updown, top, bottom) int updown; unsigned char top, bottom; { char blankcell[2]; int i; blankcell[0] = ' '; blankcell[1] = defaultattribute; switch (updown) { case UPWARD: VioScrollUp(top, 0, bottom, 79, 1, blankcell, 0); if (dwls) { for (i = top; i < bottom; i++) dwl[i] = dwl[i + 1]; dwl[bottom] = FALSE; } break; case DOWNWARD: VioScrollDn(top, 0, bottom, 79, 1, blankcell, 0); if (dwls) { for (i = bottom; i > top; i--) dwl[i] = dwl[i - 1]; dwl[top] = FALSE; } break; default: /* ignore */ ; } if (dwls) { dwls = FALSE; for (i = 0; i < 24; i++) if (dwl[i]) { dwls = TRUE; break; } } } /*---------------------------------------------------------------------------*/ /* movetoscreen */ /*---------------------------------------------------------------------------*/ movetoscreen(source, x, y, len) char * source, x, y; int len; { VioWrtCellStr(source, len, y - 1, x - 1, 0); } /*---------------------------------------------------------------------------*/ /* toplinetocyclicbuffer */ /*---------------------------------------------------------------------------*/ toplinetocyclicbuffer() { USHORT n = 160; if (paginginfo.numlines == LBUFSIZE) { if (++paginginfo.topline == LBUFSIZE) paginginfo.topline = 0; } else paginginfo.numlines++; if (++paginginfo.botline == LBUFSIZE) paginginfo.botline = 0; VioReadCellStr((paginginfo.buffer + 160 * paginginfo.botline), &n, 0, 0, 0); } /*---------------------------------------------------------------------------*/ /* cleartoeol */ /*---------------------------------------------------------------------------*/ clrtoeol() { char cell[2]; cell[0] = ' '; cell[1] = defaultattribute; VioWrtNCell(cell, 81 - wherex, wherey - 1, wherex - 1, 0); } /*---------------------------------------------------------------------------*/ /* setmargins */ /*---------------------------------------------------------------------------*/ setmargins(top, bot) char top, bot; { margintop = top; marginbot = bot; } /*---------------------------------------------------------------------------*/ /* killcursor */ /*---------------------------------------------------------------------------*/ static VIOCURSORINFO crsr_info; killcursor() { VIOCURSORINFO nocursor; if (!cursoron) return; VioGetCurType(&crsr_info, 0); /* Store current cursor type */ nocursor = crsr_info; /* MS C allows this */ nocursor.attr = -1; VioSetCurType(&nocursor, 0);/* Hide cursor */ return; } /*---------------------------------------------------------------------------*/ /* newcursor */ /*---------------------------------------------------------------------------*/ newcursor() { VioSetCurType(&crsr_info, 0); VioSetCurPos(wherey - 1, wherex - 1, 0); cursoron = TRUE; } /*---------------------------------------------------------------------------*/ /* line25 */ /*---------------------------------------------------------------------------*/ line25() { char s[80]; int i; char attr; for (i = 0; i < 80; i++) s[i] = ' '; strinsert(&s[00], usertext); strinsert(&s[36], exittext); strinsert(&s[20], helptext); strinsert(&s[65], filetext); strinsert(&s[50], hostname); attr = line25attribute; VioWrtCharStrAtt(s, 80, 24, 0, &attr, 0); } strinsert(d, s) char * d, *s; { while (*s) *d++ = *s++; } sendstr(s) char * s; { SENDCHAR(27); while (*s) SENDCHAR(*s++); } /* * RDSERWRTSCR -- Read the comms line and write to the screen. This * function is executed by a separate thread. */ VOID FAR rdserwrtscr(VOID) { int i; DosSemClear(&threadsem); /* Let him know we've started */ while (active) { if ((i = ttinc(50)) >= 0) { DosEnterCritSec(); if (cursoron) if (ttchk() > 40) { killcursor(); cursoron = FALSE; } cwrite(i & cmask); if (seslog) { if (zchout(ZSFILE, i & cmask) < 0) seslog = 0; } DosExitCritSec(); } else if (!cursoron) { DosEnterCritSec(); newcursor(); DosExitCritSec(); } } DosEnterCritSec(); /* Stop thread 1 discarding our stack before * we've gone */ DosSemClear(&threadsem); /* Tell him we're going to die */ } /* CONECT -- Perform terminal connection */ conect() { #define THRDSTKSIZ 2048 char stack[THRDSTKSIZ]; /* Stack for second thread */ USHORT len, x, y; TID threadid; int c; /* 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, ss[80]; if (speed < 0) { printf("Sorry, you must set speed first.\n"); return (-2); } twochartimes = 22000L / speed; if ((escape < 0) || (escape > 0177)) { printf("Your escape character is not ASCII - %d\n", escape); return (-2); } if (ttopen(ttname, &local, 0) < 0) { erp = errmsg; sprintf(erp, "Sorry, can't open %s", ttname); perror(errmsg); return (-2); } /* Condition console terminal and communication line */ if (ttvt(speed, flow) < 0) { printf("Sorry, Can't condition communication line\n"); return (-2); } checkscreenmode(); VioGetCurPos(&y, &x, 0); wherex = x + 1; wherey = y + 1; savescreen(&commandscreen); scrninit(); restorescreen(&vt100screen); ipadl25(); /* Create a thread to read the comms line and write to the screen */ DosSemSet(&threadsem); /* Thread 2 will clear this when it starts */ active = 1; /* So thread 2 doesn't end at once */ termessage[0] = 0; if (DosCreateThread(rdserwrtscr, &threadid, (PBYTE) (stack + THRDSTKSIZ))) { printf("Sorry, can't create thread\n"); return (-2); } DosSemWait(&threadsem, -1L);/* Wait for thread to start */ DosSemSet(&threadsem); /* Thread 2 will clear this on termination */ while (active) { /* Read the keyboard and write to comms line */ scankey(&ac, &bc); c = ac & cmask; /* Get character from keyboard */ DosEnterCritSec(); /* Protect the run time library */ if ((c & 0177) == escape) { /* Look for escape char */ c = coninc(0) & 0177; /* Got esc, get its arg */ if (c == '?') c = helpconnect(); doesc(c); /* And process it */ } else { /* Ordinary character */ if (!keylock) vt100read(ac, bc); } DosExitCritSec(); /* Let other guy use run time library */ } /* while (active) */ DosSemWait(&threadsem, -1L);/* Wait for other thread to terminate */ savescreen(&vt100screen); restorescreen(&commandscreen); if (termessage[0]!='\0') printf(termessage); } /* HELPCONNECT -- Give help message for connect. */ helpconnect() { int c; unsigned char ac, bc; char cell[2]; ascreen tempscreen; static char *hlpmsg[10] = { "", " Type :", "", " C to close the connection", " 0 (zero) to send a null", " B to send a BREAK", " H to hangup and close connection", " ^] to send the escape character", " space to cancel", ""}; *(hlpmsg[7] + 4) = ctl(escape); savescreen(&tempscreen); killcursor(); helpstart(41, 10); for (c = 0; c < 10; c++) helpline(hlpmsg[c]); helpend(); cell[0] = ' '; cell[1] = line25attribute; VioWrtNCell(cell, 80, 24, 0, 0); /* Erase line 25 */ scankey(&ac, &bc); c = ac & cmask; /* Get character from keyboard */ newcursor(); restorescreen(&tempscreen); return ((int) c); } static int helpcol, helprow; static int helpwidth; helpstart(int w, int h) { unsigned char cell[2]; cell[1] = attribute | 0x08; helpwidth = w; helpcol = (80 - w) / 2; helprow = (24 - h) / 2; cell[0] = 201; /* Top left corner */ VioWrtNCell(cell, 1, helprow, helpcol, 0); cell[0] = 205; /* Horizontal */ VioWrtNCell(cell, helpwidth, helprow, helpcol + 1, 0); cell[0] = 187; /* Top right corner */ VioWrtNCell(cell, 1, helprow, helpcol + helpwidth + 1, 0); } helpline(s) char *s; { unsigned char cell[2]; int i; i = strlen(s); helprow++; cell[1] = attribute | 0x08; cell[0] = 186; /* Vertical */ 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; /* Vertical */ VioWrtNCell(cell, 1, helprow, helpcol + helpwidth + 1, 0); } helpend() { unsigned char cell[2]; helprow++; cell[1] = attribute | 0x08; cell[0] = 200; /* Bottom left corner */ VioWrtNCell(cell, 1, helprow, helpcol, 0); cell[0] = 205; /* Horizontal */ VioWrtNCell(cell, helpwidth, helprow, helpcol + 1, 0); cell[0] = 188; /* Bottom right corner */ VioWrtNCell(cell, 1, helprow, helpcol + helpwidth + 1, 0); } /* CHSTR -- Make a printable string out of a character */ char * chstr(c) int c; { static char s[8]; char *cp = s; if (c < SP) { sprintf(cp, "CTRL-%c", ctl(c)); } else sprintf(cp, "'%c'\n", c); cp = s; return (cp); } /* DOESC -- Process an escape character argument */ doesc(c) char c; { CHAR d; char temp[50]; while (1) { if (c == escape) { /* Send escape character */ d = dopar(c); SENDCHAR(d); return; } else /* Or else look it up below. */ if (isupper(c)) c = tolower(c); switch (c) { case 'c': /* Close connection */ case '\03': active = 0; return; case 'b': /* Send a BREAK signal */ case '\02': ttsndb(); return; case 'h': /* Hangup */ case '\010': tthang(); active = 0; return; case '0': /* Send a null */ c = '\0'; d = dopar(c); SENDCHAR(d); return; case SP: /* Space, ignore */ return; default: /* Other */ conoc(BEL); return; /* Invalid esc arg, beep */ } } } /* CHECKSCREENMODE -- Make sure we are in a 25 x 80 mode */ checkscreenmode() { VIOMODEINFO m; VIOCONFIGINFO cfg; char cell[2]; int i; m.cb = 12; if (VioGetMode(&m, 0)) return; cfg.cb = 10; if (VioGetConfig(0, &cfg, 0)) return; switch (cfg.adapter) { case 0: /* Monochrome */ m.fbType = 0; m.color = 0; m.hres = 720; m.vres = 350; adapter = mono; colorofunderline = 1; break; case 1: /* CGA */ m.fbType = 1; m.color = 4; m.hres = 640; m.vres = 200; adapter = colour; break; default: /* Assume EGA/VGA */ m.fbType = 1; m.color = 4; m.hres = 640; m.vres = 350; adapter = colour; } if (m.row == 25 && m.col == 80) return; /* We're happy with this */ m.row = 25; m.col = 80; if (i = VioSetMode(&m, 0)) { printf("Error %d returned by VioSetMode\n", i); return; } cell[0] = ' '; cell[1] = 0x07; VioScrollUp(0, 0, -1, -1, -1, cell, 0); /* Clear the screen */ VioSetCurPos(0, 0, 0); /* Home the cursor */ }