|
|
1.1 ! root 1: /* ! 2: * The functions in this file negotiate with the operating system ! 3: * for characters, and write characters in a barely buffered fashion ! 4: * on the display. ! 5: * All operating systems. ! 6: */ ! 7: #include <stdio.h> ! 8: #include "ed.h" ! 9: ! 10: #if IBM ! 11: #define lo(r) ((r)&0xFF) /* low-order byte of word register */ ! 12: #define hi(r) ((r)>>8) /* high-order byte of word register */ ! 13: #endif ! 14: ! 15: #if VMS ! 16: #include <stsdef.h> ! 17: #include <ssdef.h> ! 18: #include <descrip.h> ! 19: #include <iodef.h> ! 20: #include <ttdef.h> ! 21: ! 22: #define NIBUF 128 /* Input buffer size */ ! 23: #define NOBUF 1024 /* MM says bug buffers win! */ ! 24: #define EFN 0 /* Event flag */ ! 25: ! 26: uchar obuf[NOBUF]; /* Output buffer */ ! 27: int nobuf; /* # of bytes in above */ ! 28: uchar ibuf[NIBUF]; /* Input buffer */ ! 29: int nibuf; /* # of bytes in above */ ! 30: int ibufi; /* Read index */ ! 31: int oldmode[2]; /* Old TTY mode bits */ ! 32: int newmode[2]; /* New TTY mode bits */ ! 33: short iochan; /* TTY I/O channel */ ! 34: #endif ! 35: ! 36: #if CPM ! 37: #include <bdos.h> ! 38: #endif ! 39: ! 40: #if MSDOS ! 41: #include <dos.h> ! 42: #endif ! 43: ! 44: #if GEM ! 45: #include <osbind.h> ! 46: #endif ! 47: ! 48: #if V7 ! 49: #include <sgtty.h> /* for stty/gtty functions */ ! 50: struct sgttyb ostate; /* saved tty state */ ! 51: struct sgttyb nstate; /* values for editor mode */ ! 52: #endif ! 53: ! 54: /* ! 55: * This function is called once ! 56: * to set up the terminal device streams. ! 57: * On VMS, it translates SYS$INPUT until it ! 58: * finds the terminal, then assigns a channel to it ! 59: * and sets it raw. On CPM it is a no-op. ! 60: */ ! 61: ttopen() ! 62: { ! 63: #if VMS ! 64: struct dsc$descriptor idsc; ! 65: struct dsc$descriptor odsc; ! 66: uchar oname[40]; ! 67: int iosb[2]; ! 68: int status; ! 69: ! 70: odsc.dsc$a_pointer = "SYS$INPUT"; ! 71: odsc.dsc$w_length = strlen(odsc.dsc$a_pointer); ! 72: odsc.dsc$b_dtype = DSC$K_DTYPE_T; ! 73: odsc.dsc$b_class = DSC$K_CLASS_S; ! 74: idsc.dsc$b_dtype = DSC$K_DTYPE_T; ! 75: idsc.dsc$b_class = DSC$K_CLASS_S; ! 76: do { ! 77: idsc.dsc$a_pointer = odsc.dsc$a_pointer; ! 78: idsc.dsc$w_length = odsc.dsc$w_length; ! 79: odsc.dsc$a_pointer = &oname[0]; ! 80: odsc.dsc$w_length = sizeof(oname); ! 81: status = LIB$SYS_TRNLOG(&idsc, &odsc.dsc$w_length, &odsc); ! 82: if (status!=SS$_NORMAL && status!=SS$_NOTRAN) ! 83: exit(status); ! 84: if (oname[0] == 0x1B) { ! 85: odsc.dsc$a_pointer += 4; ! 86: odsc.dsc$w_length -= 4; ! 87: } ! 88: } while (status == SS$_NORMAL); ! 89: status = SYS$ASSIGN(&odsc, &iochan, 0, 0); ! 90: if (status != SS$_NORMAL) ! 91: exit(status); ! 92: status = SYS$QIOW(EFN, iochan, IO$_SENSEMODE, iosb, 0, 0, ! 93: oldmode, sizeof(oldmode), 0, 0, 0, 0); ! 94: if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL) ! 95: exit(status); ! 96: newmode[0] = oldmode[0]; ! 97: newmode[1] = oldmode[1] | TT$M_PASSALL | TT$M_NOECHO; ! 98: status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0, ! 99: newmode, sizeof(newmode), 0, 0, 0, 0); ! 100: if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL) ! 101: exit(status); ! 102: #endif ! 103: #if CPM ! 104: #endif ! 105: #if MSDOS ! 106: #if !IBM ! 107: /* ! 108: * Redefine cursor keys (as described in DOS Technical Reference Manual ! 109: * p. 2-11, DOS BASIC Manual p. G-6) to mean what the user might expect. ! 110: */ ! 111: static char *control[] = { ! 112: "\033[0;72;16p", /* up = <ctrl-p> */ ! 113: "\033[0;77;6p", /* right = <ctrl-f> */ ! 114: "\033[0;75;2p", /* left = <ctrl-b> */ ! 115: "\033[0;80;14p", /* down = <ctrl-n> */ ! 116: "\033[0;81;22p", /* pg dn = <ctrl-v> */ ! 117: "\033[0;73;27;86p", /* pg up = <esc>V */ ! 118: "\033[0;71;27;60p", /* home = <esc>< */ ! 119: "\033[0;79;27;62p", /* end = <esc>> */ ! 120: "\033[0;83;127p", /* del = del */ ! 121: "\033[0;3;27;46p" /* <ctrl-@> = <esc>. */ ! 122: }; ! 123: register uchar *cp; ! 124: register int i; ! 125: ! 126: for (i = 0; i < sizeof(control)/sizeof(uchar *); i++) { ! 127: for (cp = control[i]; *cp; ) ! 128: ttputc(*cp++); ! 129: } ! 130: ! 131: #endif ! 132: #endif ! 133: #if V7 ! 134: gtty(1, &ostate); /* save old state */ ! 135: nstate = ostate; /* get base of new state */ ! 136: nstate.sg_flags |= RAW; ! 137: nstate.sg_flags &= ~(ECHO|CRMOD); /* no echo for now... */ ! 138: stty(1, &nstate); /* set mode */ ! 139: #endif ! 140: } ! 141: ! 142: /* ! 143: * This function gets called just ! 144: * before we go back home to the command interpreter. ! 145: * On VMS it puts the terminal back in a reasonable state. ! 146: * Another no-operation on CPM. ! 147: */ ! 148: ttclose() ! 149: { ! 150: #if VMS ! 151: int status; ! 152: int iosb[1]; ! 153: ! 154: ttflush(); ! 155: status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0, ! 156: oldmode, sizeof(oldmode), 0, 0, 0, 0); ! 157: if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL) ! 158: exit(status); ! 159: status = SYS$DASSGN(iochan); ! 160: if (status != SS$_NORMAL) ! 161: exit(status); ! 162: #endif ! 163: #if CPM ! 164: #endif ! 165: #if MSDOS ! 166: #if !IBM ! 167: /* Redefine cursor keys to default values. */ ! 168: static char *control[] = { ! 169: "\033[0;72;0;72p", ! 170: "\033[0;77;0;77p", ! 171: "\033[0;75;0;75p", ! 172: "\033[0;80;0;80p", ! 173: "\033[0;81;0;81p", ! 174: "\033[0;73;0;73p", ! 175: "\033[0;71;0;71p", ! 176: "\033[0;79;0;79p", ! 177: "\033[0;83;0;83p", ! 178: "\033[0;3;0;3p" ! 179: }; ! 180: register uchar *cp; ! 181: register int i; ! 182: ! 183: for (i = 0; i < sizeof(control)/sizeof(uchar *); i++) { ! 184: for (cp = control[i]; *cp; ) ! 185: ttputc(*cp++); ! 186: } ! 187: #endif ! 188: #endif ! 189: #if V7 ! 190: stty(1, &ostate); ! 191: #endif ! 192: } ! 193: ! 194: #ifndef IBM ! 195: /* ! 196: * Write a character to the display. ! 197: * On VMS, terminal output is buffered, and ! 198: * we just put the characters in the big array, ! 199: * after cheching for overflow. On CPM terminal I/O ! 200: * unbuffered, so we just write the byte out. ! 201: * Ditto on MS-DOS (use the very very raw console ! 202: * output routine). ! 203: */ ! 204: ttputc(c) ! 205: { ! 206: #if VMS ! 207: if (nobuf >= NOBUF) ! 208: ttflush(); ! 209: obuf[nobuf++] = c; ! 210: #endif ! 211: #if CPM ! 212: bios(BCONOUT, c, 0); ! 213: #endif ! 214: #if GEM ! 215: #if NATIVE ! 216: Bconout(2, c); ! 217: #else ! 218: Crawio(c); ! 219: #endif ! 220: #endif ! 221: #if MSDOS ! 222: dosb(CONDIO, c, 0); ! 223: #endif ! 224: #if V7 ! 225: fputc(c, stdout); ! 226: #endif ! 227: } ! 228: #endif ! 229: /* ! 230: * Flush terminal buffer. Does real work ! 231: * where the terminal output is buffered up. A ! 232: * no-operation on systems where byte at a time ! 233: * terminal I/O is done. ! 234: */ ! 235: ttflush() ! 236: { ! 237: #if VMS ! 238: int status; ! 239: int iosb[2]; ! 240: ! 241: status = SS$_NORMAL; ! 242: if (nobuf != 0) { ! 243: status = SYS$QIOW(EFN, iochan, IO$_WRITELBLK|IO$M_NOFORMAT, ! 244: iosb, 0, 0, obuf, nobuf, 0, 0, 0, 0); ! 245: if (status == SS$_NORMAL) ! 246: status = iosb[0] & 0xFFFF; ! 247: nobuf = 0; ! 248: } ! 249: return (status); ! 250: #endif ! 251: #if CPM ! 252: #endif ! 253: #if MSDOS ! 254: #endif ! 255: #if V7 ! 256: fflush(stdout); ! 257: #endif ! 258: } ! 259: ! 260: /* ! 261: * Read a character from the terminal, ! 262: * performing no editing and doing no echo at all. ! 263: * More complex in VMS that almost anyplace else, which ! 264: * figures. Very simple on CPM, because the system can ! 265: * do exactly what you want. ! 266: */ ! 267: ttgetc() ! 268: { ! 269: #if VMS ! 270: int status; ! 271: int iosb[2]; ! 272: int term[2]; ! 273: ! 274: while (ibufi >= nibuf) { ! 275: ibufi = 0; ! 276: term[0] = 0; ! 277: term[1] = 0; ! 278: status = SYS$QIOW(EFN, iochan, IO$_READLBLK|IO$M_TIMED, ! 279: iosb, 0, 0, ibuf, NIBUF, 0, term, 0, 0); ! 280: if (status != SS$_NORMAL) ! 281: exit(status); ! 282: status = iosb[0] & 0xFFFF; ! 283: if (status!=SS$_NORMAL && status!=SS$_TIMEOUT) ! 284: exit(status); ! 285: nibuf = (iosb[0]>>16) + (iosb[1]>>16); ! 286: if (nibuf == 0) { ! 287: status = sys$qiow(EFN, iochan, IO$_READLBLK, ! 288: iosb, 0, 0, ibuf, 1, 0, term, 0, 0); ! 289: if (status != SS$_NORMAL ! 290: || (status = (iosb[0]&0xFFFF)) != SS$_NORMAL) ! 291: exit(status); ! 292: nibuf = (iosb[0]>>16) + (iosb[1]>>16); ! 293: } ! 294: } ! 295: return (ibuf[ibufi++] & 0xFF); /* Allow multinational */ ! 296: #endif ! 297: #if CPM ! 298: return (biosb(BCONIN, 0, 0)); ! 299: #endif ! 300: #if GEM ! 301: register long c; ! 302: ! 303: #if NATIVE ! 304: c = Bconin(2); ! 305: #else ! 306: c = Crawcin(); ! 307: #endif ! 308: /* ! 309: * Convert arrow keys to ctrl-p,n,f,b, and function keys to ! 310: * various things. (No longer return 0 for function keys.) ! 311: */ ! 312: switch ((int)(c >> 16)) { ! 313: case 0x48: /* Up arrow to ^P */ ! 314: return (OBND|0x10); ! 315: case 0x50: /* Down arrow to ^N */ ! 316: return (OBND|0x0E); ! 317: case 0x4D: /* Right arrow to ^F */ ! 318: return (OBND|0x06); ! 319: case 0x4B: /* Left arrow to ^B */ ! 320: return (OBND|0x02); ! 321: #if EXKEYS ! 322: case 0x3B: /* F1 */ ! 323: return (FN1); ! 324: case 0x3C: /* F2 */ ! 325: return (FN2); ! 326: case 0x3D: /* F3 */ ! 327: return (FN3); ! 328: case 0x3E: /* F4 */ ! 329: return (FN4); ! 330: case 0x3F: /* F5 */ ! 331: return (FN5); ! 332: case 0x40: /* F6 */ ! 333: return (FN6); ! 334: case 0x41: /* F7 */ ! 335: return (FN7); ! 336: case 0x42: /* F8 */ ! 337: return (FN8); ! 338: case 0x43: /* F9 */ ! 339: return (FN9); ! 340: case 0x44: /* F10 */ ! 341: return (FN10); ! 342: case 0x47: /* Clr/Home */ ! 343: return (FN1D); /* Delete this window */ ! 344: case 0x52: /* Insert */ ! 345: return (FN1C); /* perform macro */ ! 346: case 0x61: /* Undo */ ! 347: return (FN1B); /* Remove help window */ ! 348: case 0x62: /* Help */ ! 349: return (FN1A); /* Prompt for help */ ! 350: #else ! 351: case 0x3B: /* F1 */ ! 352: case 0x3C: /* F2 */ ! 353: case 0x3D: /* F3 */ ! 354: case 0x3E: /* F4 */ ! 355: case 0x3F: /* F5 */ ! 356: case 0x40: /* F6 */ ! 357: case 0x41: /* F7 */ ! 358: case 0x42: /* F8 */ ! 359: case 0x43: /* F9 */ ! 360: case 0x44: /* F10 */ ! 361: return (0x07|OBND); /* Ctrl-G */ ! 362: case 0x47: /* Clr/Home */ ! 363: return (OBND|META|'1'); /* Delete this window */ ! 364: case 0x52: /* Insert */ ! 365: return (OBND|PFX1|'E'); /* perform macro */ ! 366: case 0x61: /* Undo */ ! 367: return (OBND|META|'2'); /* Remove help window */ ! 368: case 0x62: /* Help */ ! 369: return (OBND|META|'?'); /* Prompt for help */ ! 370: #endif ! 371: default: /* Return the keyboard character */ ! 372: return ((int)c); ! 373: } ! 374: #endif ! 375: #if MSDOS ! 376: #if IBM ! 377: unsigned i; ! 378: ! 379: for (;;) { /* try again on bad stuff */ ! 380: /* Read a character through IBM PC ROM BIOS keyboard interrupt. */ ! 381: i = ibmrbkey(0); /* read character fn */ ! 382: if (lo(i)) ! 383: return (lo(i)); /* got a char */ ! 384: ! 385: switch (hi(i)) { /* else translate scan code */ ! 386: case 03: /* <ctl-@> = <esc>. */ ! 387: return OBND| '.' | META; ! 388: case 71: /* home = <esc>< */ ! 389: return OBND| '<' | META; ! 390: case 72: /* up = <ctl>p */ ! 391: return OBND| 'P' | CTRL; ! 392: case 73: /* pg up = <esc>v */ ! 393: return OBND| 'V' | META; ! 394: case 75: /* left = <ctl>b */ ! 395: return OBND| 'B' | CTRL; ! 396: case 77: /* right = <ctl>f */ ! 397: return OBND| 'F' | CTRL; ! 398: case 79: /* end = <esc>> */ ! 399: return OBND| '>' | META; ! 400: case 80: /* down = <ctl>n */ ! 401: return OBND| 'N' | CTRL; ! 402: case 81: /* pg dn = <ctl>v */ ! 403: return OBND| 'V' | CTRL; ! 404: case 83: /* del = del */ ! 405: return OBND| 127; ! 406: #if EXKEYS ! 407: case 0x3B: /* F1 */ ! 408: return (FN1); ! 409: case 0x3C: /* F2 */ ! 410: return (FN2); ! 411: case 0x3D: /* F3 */ ! 412: return (FN3); ! 413: case 0x3E: /* F4 */ ! 414: return (FN4); ! 415: case 0x3F: /* F5 */ ! 416: return (FN5); ! 417: case 0x40: /* F6 */ ! 418: return (FN6); ! 419: case 0x41: /* F7 */ ! 420: return (FN7); ! 421: case 0x42: /* F8 */ ! 422: return (FN8); ! 423: case 0x43: /* F9 */ ! 424: return (FN9); ! 425: case 0x44: /* F10 */ ! 426: return (FN10); ! 427: case 0x52: /* Insert */ ! 428: return (FN1C); /* perform macro */ ! 429: case 0x61: /* Undo */ ! 430: return (FN1B); /* Remove help window */ ! 431: case 0x62: /* Help */ ! 432: return (FN1A); /* Prompt for help */ ! 433: #endif ! 434: } ! 435: } ! 436: #else ! 437: return (dosb(CONRAW, 0, 0)); ! 438: #endif ! 439: #endif ! 440: #if V7 ! 441: return (fgetc(stdin)); ! 442: #endif ! 443: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.