/* * deal with the terminal definition file * * The file is named "terminal" * * It is modeled after the Pearl install.dat file * */ /* * here is the entry point */ # include "term.h" # define DRIVEA 0 # define DRIVEB 1 main (d) { ndrives = d; if (ndrives == 0) /* single drive system */ drive = DRIVEA; else drive = DRIVEB; readterm (); /* read the terminal data file */ getterm (); /* the terminal type */ patch (); /* patch it in the BIOS */ return 0; } char *one = "You have a Level I terminal. All programs supplied by Morrow\n\ Designs are pre-installed for your terminal. Any programs\n\ not supplied by Morrow Designs must be installed for an\n\ ADM-3A terminal.\n\ ", *two = "You have a Level II terminal. All programs supplied by\n\ Morrow Designs are pre-installed for your terminal. Any\n\ programs not supplied by Morrow Designs must be installed\n\ for a SOROC IQ-120 terminal.\n\ ", *three = "You have a Level III terminal. All programs supplied by\n\ Morrow Designs are pre-installed for your terminal. Any\n\ programs not supplied by Morrow Designs must be installed\n\ for an ADM-31 terminal.\n\ ", *sep1 = " The CP/M SYSTEM diskette will not be installed for your terminal.\n\ You must install some of the application programs (i.e. WordStar and\n\ LogiCalc) yourself.\n\ In addition, the Micro-Menus will not appear as they should on the\n", *sep2 = "screen.\n\ Before confirming this selection, check to see if your terminal can\n\ emulate any of those on the selection Menu. If it can, you will find it\n\ more convenient to use your system.\n\n"; unsigned nterm = 0; struct terminal terminal [MAXTERM] = NULL; /* * proto is the prototype terminal defintion */ struct terminal proto = { "adm", /* name */ one, 1, /* dca */ { "\33=", /* start */ "" /* mid */ "", /* end */ 0, /* esclevel */ 0, /* offset 1 */ 0, /* offset 2 */ NORMAL, /* order */ }, /* control */ { HOME, NULL, CLRSCREEN, NULL, CURLEFT, NULL, CURRIGHT, NULL, CURUP, NULL, CURDOWN, NULL, }, /* escape */ { INSLINE, NULL, INSCHAR, NULL, DELLINE, NULL, DELCHAR, NULL, HION, NULL, HIOFF, NULL, ALTCLEAR, NULL, CLREOS, NULL, CLREOL, NULL, }, }; /* * read in and internalize the Terminal definition file */ readterm () { char buf [BUFSIZE]; struct terminal *t; FILE *f; put ("\n\nLoading the terminal description file ...\n\n"); f = fopen ("terminal.dat", "read"); if (f == NULL) { put ("No terminal file\n"); return NO; } *buf = NULL; /* initialize the line buffer */ nterm = 0; t = terminal; for (;;) { /* * find next line beginning with non blank */ for (;;) { if (!iswhite (*buf) && *buf != '*') break; fgets (buf, BUFSIZE, f); if (feof (f)) break; } if (feof (f)) break; t = &terminal [nterm++]; if (nterm == MAXTERM) { put ("Too many terminals\n"); return NO; } cpybuf (t, &proto, sizeof *t); shorten (buf); t->name = save (buf); /* * now process each of the lines * of the terminals definition */ for (;;) { fgets (buf, BUFSIZE, f); if (feof (f)) break; if (empty (buf)) break; if (!iswhite (*buf)) break; process (buf, t); } } fclose (f); } struct token token [] = { "ESC", 033, "NUL", 0, "SP", ' ', "LEVEL", LEVEL, "CURSOR", CURSOR, "HOME", HOME, "CLR", CLEAR, "RIGHT", RIGHT, "LEFT" LEFT, "UP", UP, "DOWN", DOWN, "CEOL", CEOL, "CEOS", CEOS, "INSLINE", INSLINE, "INSCHAR", INSCHAR, "DELCHAR", DELCHAR, "DELLINE", DELLINE, "HI", HI, "LO", LOW, "", }; /* * look up a string and return a numeric value */ lookup (a) char *a; { struct token *t; for (t = token; *t->name; t++) if (cmpstr (t->name, a)) return t->value & BYTEMASK; return -1; /* couldn't find it */ } /* * dig a character string out of the definition file * * Here, a is the source string and b is the destination */ findstring (a, b) char *a, *b; { char buf [BUFSIZE]; /* out own personal buffer */ for (;;) { a = getword (a, buf); /* pick a word */ if (!*buf || cmpstr (buf, "/*")) /* no more words */ break; *b++ = findchar (buf); /* extract one char */ } *b = NULL; } char findchar (a) char *a; { int l, c, value; l = lenstr (a); c = lookup (a); if (l == 2 && *a == '^') { a++; *a = toupper (*a); value = *a + 1 - 'A'; } else if (*a == '\\' && ishex (a + 1)) { value = htoi (a + 1); } else if (numeric (a)) { value = atoi (a); } else if (l == 3 && a[0] == '\'' && a[2] == '\'') { value = a[1]; /* quoted character */ } else if (c >= 0) { value = c; } else if (l == 1) /* single character */ { value = *a; } else { value = -1; /* unknown */ } if (value == 0) value = 0377; /* a null is reprented as a 0377 in string */ return value; } /* * add the information in the line at a to the * terminal structure at t */ process (a, t) char *a; struct terminal *t; { char *b; char buf [BUFSIZE]; int c; /* * snag the first word of the line into buf */ a = getword (a, buf); if (!*buf) return; /* no first word */ c = lookup (buf); /* is it a keyword ? */ if (c < 0) { put (buf); /* not a keyword */ put (": Unrecognized word\n"); return; } /* * if the next word is an equals sign, skip it */ b = getword (a, buf); if (cmpstr (buf, "=")) a = b; if (c == CURSOR) docursor (a, t); else if (c == LEVEL) dolevel (a, t); else { docode (a, t, c); if (c == CLEAR) /* special case for clear */ docode (a, t, ALTCLEAR); } } dolevel (a, t) char *a; struct terminal *t; { char buf [BUFSIZE]; a = getword (a, buf); if (!isdigit (*buf)) { put ("Non-numeric level number\n"); return NO; } t->level = atoi (buf); switch (t->level) { case 0: { t->message = NULL; break; } case 1: { t->message = &one; break; } case 2: { t->message = &two; break; } case 3: { t->message = &three; break; } default: { put ("Level number must be 0, 1, 2, or 3\n"); return NO; } } } docode (a, t, c) char *a; struct terminal *t; char c; { char buf [BUFSIZE]; int n; findstring (a, buf); for (n = 0; n < NCONTROL; n++) if (c == t->control[n].from) t->control[n].to = save (buf); for (n = 0; n < NESCAPE; n++) if (c == t->escape[n].from) t->escape[n].to = save (buf); } docursor (a, t) char *a; struct terminal *t; { static char *p, nchar; char buf [BUFSIZE]; int phase; phase = 0; *t->dca.start = NULL; *t->dca.mid = NULL; *t->dca.end = NULL; p = t->dca.start; nchar = 0; for (;;) { a = getword (a, buf); if (!*buf) break; /* no more words */ /* * R+32 for example */ if (buf[0] == 'R' && buf[1] == '+') { *p = NULL; if (phase == 0) { t->dca.order |= NORMAL; t->dca.offset1 = atoi (buf + 2) - 32; p = t->dca.mid; } else { t->dca.offset2 = atoi (buf + 2) - 32; p = t->dca.end; nchar = 0; } phase++; } /* * C+32 for example */ else if (buf[0] == 'C' && buf[1] == '+') { *p = NULL; if (phase == 0) { t->dca.order |= FLIPPED; t->dca.offset1 = atoi (buf + 2) - 32; p = t->dca.mid; } else { t->dca.offset2 = atoi (buf + 2) - 32; p = t->dca.end; nchar = 0; } phase++; } else if (cmpstr ("ASCII", buf)) { t->dca.order |= ASCII; } else { if (++nchar >= MAXCUR) { put ("Cursor addressing string too long\n"); return NO; } *p++ = findchar (buf); } } *p = NULL; }