|
|
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.