1 /* UNIX: Unix specific terminal driver
2 for MicroEMACS 4.0
3 (C)Copyright 1995 D. Lawrence, C. Smith
4 */
5
6 /**
7 New features: (as of version 3.10)
8
9 1. Timeouts waiting on a function key have been changed from
10 35000 to 500000 microseconds.
11
12 2. Additional keymapping entries can be made from the command
13 language by issuing a 'set $palette xxx'. The format of
14 xxx is a string as follows:
15 "KEYMAP keybinding escape-sequence".
16 To add "<ESC><[><A>" as a keybinding of FNN, issue:
17 "KEYMAP FNN ~e[A".
18 Note that the "~e" sequence represents the escape character in
19 the MicroEMACS command language.
20
21 3. Colors are supported. Under AIX the colors will be pulled
22 in automaticly. For other environments, you can either add
23 the termcap entries, C0 to D7. Or the colors may be defined
24 using the command language by issuing a 'set $palette xxx'
25 command. The format of xxx is a string as follows:
26 "CLRMAP # escape-sequence".
27 The number is a number from 0 to 15, where 0 to 7 is the
28 foreground colors, and 8 to 15 as background colors.
29 To add foreground color 0 for ansi terminals, issue:
30 "CLRMAP 0 ~e[30m".
31
32 'Porting notes:
33
34 I have tried to create this file so that it should work
35 as well as possible without changes on your part.
36
37 However, if something does go wrong, read the following
38 helpful hints:
39
40 1. On SUN-OS4, there is a problem trying to include both
41 the termio.h and ioctl.h files. I wish Sun would get their
42 act together. Even though you get lots of redefined messages,
43 it shouldn't cause any problems with the final object.
44
45 2. In the type-ahead detection code, the individual UNIX
46 system either has a FIONREAD or a FIORDCHK ioctl call.
47 Hopefully, your system uses one of them and this be detected
48 correctly without any intervention.
49
50 3. Also lookout for directory handling. The SCO Xenix system
51 is the weirdest I've seen, requiring a special load file
52 (see below). Some machine call the result of a readdir() call
53 a "struct direct" or "struct dirent". Includes files are
54 named differently depending of the O/S. If your system doesn't
55 have an opendir()/closedir()/readdir() library call, then
56 you should use the public domain utility "ndir".
57
58 To compile:
59 Compile all files normally.
60 To link:
61 Select one of the following operating systems:
62 SCO Xenix:
63 use "-ltermcap" and "-lx";
64 SUN 3 and 4:
65 use "-ltermcap";
66 IBM-RT, IBM-AIX, ATT UNIX, Altos UNIX, Interactive:
67 use "-lcurses".
68
69 - 20 feb 95 New version 4.00 features
70 We added new code to implient a TERMIOS driver
71 **/
72
73 /** Include files **/
74 #include <stdio.h> /* Standard I/O definitions */
75 #include "estruct.h" /* Emacs definitions */
76
77 /** Do nothing routine **/
scnothing()78 int scnothing()
79 {
80 return(0);
81 }
82
83 /** Only compile for UNIX machines **/
84 #if BSD || FREEBSD || USG || AIX || AUX || SMOS || HPUX8 || HPUX9 || SUN || XENIX || (AVVION || TERMIOS)
85
86 /** Include files **/
87 #include "eproto.h" /* Function definitions */
88 #include "edef.h" /* Global variable definitions */
89 #include "elang.h" /* Language definitions */
90
91 /** Kill predefined **/
92 #undef CTRL /* Problems with CTRL */
93
94
95 /** Overall include files **/
96 #include <sys/types.h> /* System type definitions */
97 #include <sys/stat.h> /* File status definitions */
98 #include <sys/ioctl.h> /* I/O control definitions */
99
100 /** Additional include files **/
101 #if FREEBSD
102 #define TERMIOS 1
103 #include <sys/time.h>
104 #undef BSD
105 #include <sys/param.h>
106 #undef BSD
107 #define BSD 0
108 #endif
109 #if (BSD && !TERMIOS)
110 #include <sys/time.h> /* Timer definitions */
111 #endif /* (BSD && !TERMIOS) */
112 #if BSD || FREEBSD || SUN || HPUX8 || HPUX9 || (AVVION || TERMIOS) || AIX
113 #include <signal.h> /* Signal definitions */
114 #endif /* BSD || FREEBSD || SUN || HPUX8 || HPUX9 || (AVVION || TERMIOS) */
115 #if USG || AIX || AUX || SMOS || HPUX8 || HPUX9 || SUN || XENIX
116 #include <termio.h> /* Terminal I/O definitions */
117 #endif /* USG || AIX || AUX || SMOS || HPUX8 || HPUX9 || SUN || XENIX */
118 #if (AVVION || TERMIOS)
119 #include <termios.h> /* Terminal I/O definitions */
120 #include <unistd.h>
121 #endif /* (AVVION || TERMIOS) */
122 #if CURSES
123 #include <curses.h> /* Curses screen output */
124 #undef WINDOW /* Oh no! */
125 #endif /* CURSES */
126
127 /** Completion include files **/
128 /** Directory accessing: Try and figure this out... if you can! **/
129 #if ((BSD || FREEBSD) && !TERMIOS)
130 #include <sys/dir.h> /* Directory entry definitions */
131 #define DIRENTRY direct
132 #endif /* (BSD && !TERMIOS) */
133 #if XENIX || VAT
134 #include <sys/ndir.h> /* Directory entry definitions */
135 #define DIRENTRY direct
136 #endif /* XENIX */
137 #if ((USG || AIX || AUX) && !VAT) || SMOS || HPUX8 || HPUX9 || SUN || (AVVION || TERMIOS)
138 #include <dirent.h> /* Directory entry definitions */
139 #define DIRENTRY dirent
140 #endif /* ((USG || AIX || AUX) && !VAT) || SMOS || HPUX8 || HPUX9 || SUN || (AVVION || TERMIOS) */
141
142 /** Restore predefined definitions **/
143 #undef CTRL /* Restore CTRL */
144 #define CTRL 0x0100
145
146 /** Parameters **/
147 #define NINCHAR 64 /* Input buffer size */
148 #define NOUTCHAR 256 /* Output buffer size */
149 #if TERMCAP || TERMIOS
150 #define NCAPBUF 1024 /* Termcap storage size */
151 #endif /* TERMCAP */
152 #define MARGIN 8 /* Margin size */
153 #define SCRSIZ 64 /* Scroll for margin */
154 #define NPAUSE 10 /* # times thru update to pause */
155
156 /** CONSTANTS **/
157 #define TIMEOUT 255 /* No character available */
158
159 #if TERMCAP || TERMIOS
160 struct capbind { /* Capability binding entry */
161 char * name; /* Termcap name */
162 char * store; /* Storage variable */
163 };
164 struct keybind { /* Keybinding entry */
165 char * name; /* Termcap name */
166 int value; /* Binding value */
167 };
168 char *reset = (char*) NULL; /* reset string kjc */
169 #endif /* TERMCAP */
170
171 /** Local variables **/
172 #if (BSD && !TERMIOS)
173 static struct sgttyb cursgtty; /* Current modes */
174 static struct sgttyb oldsgtty; /* Original modes */
175 static struct tchars oldtchars; /* Current tchars */
176 static struct ltchars oldlchars; /* Current ltchars */
177 static char blank[6] = /* Blank out character set */
178 { -1, -1, -1, -1, -1, -1 };
179 #endif /* (BSD && !TERMIOS) */
180 #if USG || AIX || AUX || SMOS || HPUX8 || HPUX9 || (SUN && !TERMIOS) || XENIX
181 static struct termio curterm; /* Current modes */
182 static struct termio oldterm; /* Original modes */
183 #endif /* USG || AIX || AUX || SMOS || HPUX8 || HPUX9 || (SUN && !TERMIOS) || XENIX */
184 #if (AVVION || TERMIOS)
185 static struct termios curterm; /* Current modes */
186 static struct termios oldterm; /* Original modes */
187 #endif /* (AVVION || TERMIOS) */
188 #if TERMCAP || TERMIOS
189 static char tcapbuf[NCAPBUF]; /* Termcap character storage */
190 #define CAP_CL 0 /* Clear to end of page */
191 #define CAP_CM 1 /* Cursor motion */
192 #define CAP_CE 2 /* Clear to end of line */
193 #define CAP_SE 3 /* Standout ends */
194 #define CAP_SO 4 /* Standout (reverse video) */
195 #define CAP_IS 5 /* Initialize screen */
196 #define CAP_KS 6 /* Keypad mode starts */
197 #define CAP_KE 7 /* Keypad mode ends */
198 #define CAP_VB 8 /* Visible bell */
199 #if COLOR
200 #define CAP_C0 9 /* Foreground color #0 */
201 #define CAP_C1 10 /* Foreground color #1 */
202 #define CAP_C2 11 /* Foreground color #2 */
203 #define CAP_C3 12 /* Foreground color #3 */
204 #define CAP_C4 13 /* Foreground color #4 */
205 #define CAP_C5 14 /* Foreground color #5 */
206 #define CAP_C6 15 /* Foreground color #6 */
207 #define CAP_C7 16 /* Foreground color #7 */
208 #define CAP_D0 17 /* Background color #0 */
209 #define CAP_D1 18 /* Background color #1 */
210 #define CAP_D2 19 /* Background color #2 */
211 #define CAP_D3 20 /* Background color #3 */
212 #define CAP_D4 21 /* Background color #4 */
213 #define CAP_D5 22 /* Background color #5 */
214 #define CAP_D6 23 /* Background color #6 */
215 #define CAP_D7 24 /* Background color #7 */
216 #if USG || AIX || AUX
217 #define CAP_SF 25 /* Set foreground color */
218 #define CAP_SB 26 /* Set background color */
219 #endif /* USG || AIX || AUX */
220 #endif /* COLOR */
221 static struct capbind capbind[] = { /* Capability binding list */
222 { "cl" }, /* Clear to end of page */
223 { "cm" }, /* Cursor motion */
224 { "ce" }, /* Clear to end of line */
225 { "se" }, /* Standout ends */
226 { "so" }, /* Standout (reverse video) */
227 { "is" }, /* Initialize screen */
228 { "ks" }, /* Keypad mode starts */
229 { "ke" }, /* Keypad mode ends */
230 { "vb" }, /* Visible bell */
231 #if COLOR
232 { "c0" }, /* Foreground color #0 */
233 { "c1" }, /* Foreground color #1 */
234 { "c2" }, /* Foreground color #2 */
235 { "c3" }, /* Foreground color #3 */
236 { "c4" }, /* Foreground color #4 */
237 { "c5" }, /* Foreground color #5 */
238 { "c6" }, /* Foreground color #6 */
239 { "c7" }, /* Foreground color #7 */
240 { "d0" }, /* Background color #0 */
241 { "d1" }, /* Background color #1 */
242 { "d2" }, /* Background color #2 */
243 { "d3" }, /* Background color #3 */
244 { "d4" }, /* Background color #4 */
245 { "d5" }, /* Background color #5 */
246 { "d6" }, /* Background color #6 */
247 { "d7" }, /* Background color #7 */
248 #if USG || AIX || AUX
249 { "Sf" }, /* Set foreground color */
250 { "Sb" }, /* Set background color */
251 #endif /* USG || AIX || AUX */
252 #endif /* COLOR */
253 };
254 #if COLOR
255 static int cfcolor = -1; /* Current forground color */
256 static int cbcolor = -1; /* Current background color */
257 #endif /* COLOR */
258 static struct keybind keybind[] = { /* Keybinding list */
259 { "bt", SHFT|CTRL|'i' }, /* Back-tab key */
260 { "k1", SPEC|'1' }, /* F1 key */
261 { "k2", SPEC|'2' }, /* F2 key */
262 { "k3", SPEC|'3' }, /* F3 key */
263 { "k4", SPEC|'4' }, /* F4 key */
264 { "k5", SPEC|'5' }, /* F5 key */
265 { "k6", SPEC|'6' }, /* F6 key */
266 { "k7", SPEC|'7' }, /* F7 key */
267 { "k8", SPEC|'8' }, /* F8 key */
268 { "k9", SPEC|'9' }, /* F9 key */
269 { "k0", SPEC|'0' }, /* F0 or F10 key */
270 { "k;", SPEC|'0' }, /* F0 or F10 key (kjc) */
271 { "F1", SHFT|SPEC|'1' }, /* Shift-F1 or F11 key */
272 { "F2", SHFT|SPEC|'2' }, /* Shift-F2 or F12 key */
273 { "F3", SHFT|SPEC|'3' }, /* Shift-F3 or F13 key */
274 { "F4", SHFT|SPEC|'4' }, /* Shift-F4 or F14 key */
275 { "F5", SHFT|SPEC|'5' }, /* Shift-F5 or F15 key */
276 { "F6", SHFT|SPEC|'6' }, /* Shift-F6 or F16 key */
277 { "F7", SHFT|SPEC|'7' }, /* Shift-F7 or F17 key */
278 { "F8", SHFT|SPEC|'8' }, /* Shift-F8 or F18 key */
279 { "F9", SHFT|SPEC|'9' }, /* Shift-F9 or F19 key */
280 { "FA", SHFT|SPEC|'0' }, /* Shift-F0 or F20 key */
281 { "kA", CTRL|'O' }, /* Insert line key */
282 { "kb", CTRL|'H' }, /* Backspace key */
283 { "kC", CTRL|'L' }, /* Clear screen key */
284 { "kD", SPEC|'D' }, /* Delete character key */
285 { "kd", SPEC|'N' }, /* Down arrow key */
286 { "kE", CTRL|'K' }, /* Clear to end of line key */
287 { "kF", CTRL|'V' }, /* Scroll forward key */
288 { "kH", SPEC|'>' }, /* Home down key */
289 { "@7", SPEC|'>' }, /* Home down key (kjc) */
290 { "kh", SPEC|'<' }, /* Home key */
291 { "kI", SPEC|'C' }, /* Insert character key */
292 { "kL", CTRL|'K' }, /* Delete line key */
293 { "kl", SPEC|'B' }, /* Left arrow key */
294 { "kN", SPEC|'V' }, /* Next page key */
295 { "kP", SPEC|'Z' }, /* Previous page key */
296 { "kR", CTRL|'Z' }, /* Scroll backward key */
297 { "kr", SPEC|'F' }, /* Right arrow key */
298 { "ku", SPEC|'P' }, /* Up arrow key */
299 { "K1", SPEC|'<' }, /* Keypad 7 -> Home */
300 { "K2", SPEC|'V' }, /* Keypad 9 -> Page Up */
301 { "K3", ' ' }, /* Keypad 5 */
302 { "K4", SPEC|'>' }, /* Keypad 1 -> End */
303 { "K5", CTRL|'V' }, /* Keypad 3 -> Page Down */
304 { "kw", CTRL|'E' } /* End of line */
305 };
306 #endif /* TERMCAP */
307 static int inbuf[NINCHAR]; /* Input buffer */
308 static int * inbufh = /* Head of input buffer */
309 inbuf;
310 static int * inbuft = /* Tail of input buffer */
311 inbuf;
312 #if TERMCAP
313 static unsigned char outbuf[NOUTCHAR]; /* Output buffer */
314 static unsigned char * outbuft = /* Output buffer tail */
315 outbuf;
316 #endif /* TERMCAP */
317
318 static DIR *dirptr = NULL; /* Current directory stream */
319 static char path[NFILEN]; /* Path of file to find */
320 static char rbuf[NFILEN]; /* Return file buffer */
321 static char *nameptr; /* Ptr past end of path in rbuf */
322
323 /** Terminal definition block **/
324 int scopen(), scclose(), ttgetc(), ttputc(), ttflush();
325 int scmove(), sceeol(), sceeop(), scbeep(), screv();
326 int sckopen(), sckclose();
327 #if COLOR
328 int scfcol(), scbcol();
329 #endif /* COLOR */
330
331 #if TERMCAP && FLABEL
332 static void dis_sfk(), dis_ufk();
333 #endif
334
335 TERM term = {
336 120, /* Maximum number of rows */
337 0, /* Current number of rows */
338 132, /* Maximum number of columns */
339 0, /* Current number of columns */
340 0, 0, /* upper left corner default screen */
341 MARGIN, /* Margin for extending lines */
342 SCRSIZ, /* Scroll size for extending */
343 NPAUSE, /* # times thru update to pause */
344 scopen, /* Open terminal routine */
345 scclose, /* Close terminal routine */
346 sckopen, /* Open keyboard routine */
347 sckclose, /* Close keyboard routine */
348 ttgetc, /* Get character routine */
349 ttputc, /* Put character routine */
350 ttflush, /* Flush output routine */
351 scmove, /* Move cursor routine */
352 sceeol, /* Erase to end of line routine */
353 sceeop, /* Erase to end of page routine */
354 sceeop, /* Clear the desktop */
355 scbeep, /* Beep! routine */
356 screv, /* Set reverse video routine */
357 scnothing, /* Set resolution routine */
358 #if COLOR
359 scfcol, /* Set forground color routine */
360 scbcol, /* Set background color routine */
361 #endif /* COLOR */
362 #if INSDEL
363 scinsline, /* insert a screen line */
364 scdelline, /* delete a screen line */
365 #endif /* INSDEL */
366 };
367
368 int hpterm; /* global flag braindead HP-terminal */
369
370 /** Open terminal device **/
ttopen()371 int ttopen()
372 {
373 strcpy(os, "UNIX");
374 #if (BSD && !TERMIOS)
375 /* Get tty modes */
376 if (ioctl(0, TIOCGETP, &oldsgtty) ||
377 ioctl(0, TIOCGETC, &oldtchars) ||
378 ioctl(0, TIOCGLTC, &oldlchars))
379 return(-1);
380
381 /* Save to original mode variables */
382 cursgtty = oldsgtty;
383
384 /* Set new modes */
385 cursgtty.sg_flags |= CBREAK;
386 cursgtty.sg_flags &= ~(ECHO|CRMOD);
387
388 /* Set tty modes */
389 if (ioctl(0, TIOCSETP, &cursgtty) ||
390 ioctl(0, TIOCSETC, blank) ||
391 ioctl(0, TIOCSLTC, blank))
392 return(-1);
393 #endif /* (BSD && !TERMIOS) */
394 #if USG || AIX || AUX || SMOS || HPUX8 || HPUX9 || (SUN && !TERMIOS) || XENIX
395
396 #if SMOS
397 /* Extended settings; 890619mhs A3 */
398 set_parm(0,-1,-1);
399 #endif /* SMOS */
400
401 /* Get modes */
402 if (ioctl(0, TCGETA, &oldterm)) {
403 perror("Cannot TCGETA");
404 return(-1);
405 }
406
407 /* Save to original mode variable */
408 curterm = oldterm;
409
410 /* Set new modes */
411 /* I do not believe the flow control settings of the OS should
412 be diddled by an application program. But if you do, change this
413 1 to a 0, but be warned, all sorts of terminals will get grief
414 with this */
415 #if 1
416 curterm.c_iflag &= ~(INLCR|ICRNL|IGNCR);
417 #else
418 curterm.c_iflag &= ~(INLCR|ICRNL|IGNCR|IXON|IXANY|IXOFF);
419 #endif
420
421 curterm.c_lflag &= ~(ICANON|ISIG|ECHO|IEXTEN);
422 curterm.c_cc[VMIN] = 1;
423 curterm.c_cc[VTIME] = 0;
424
425 #if SMOS
426 /****THIS IS A BIG GUESS ON MY PART... the code changed
427 too much between versions for me to be sure this will work - DML */
428
429 /* Allow multiple (dual) sessions if already enabled */
430 curterm.c_lflag = oldterm.c_lflag & ISIG;
431
432 /* Use old SWTCH char if necessary */
433 if (curterm.c_lflag != 0)
434 curterm.c_cc[VSWTCH] = oldterm.c_cc[VSWTCH];
435
436 /* Copy VTI settings */
437 curterm.c_cc[VTBIT] = oldterm.c_cc[VTBIT];
438
439 /* Extended settings; 890619mhs A3 */
440 set_parm(0,-1,-1);
441 #endif /* SMOS */
442
443 /* Set tty mode */
444 if (ioctl(0, TCSETA, &curterm)) {
445 perror("Cannot TCSETA");
446 return(-1);
447 }
448 #endif /* USG || AIX || AUX || SMOS || HPUX8 || HPUX9 || (SUN && !TERMIOS) || XENIX */
449 #if (AVVION || TERMIOS)
450 /* Get modes */
451 if (tcgetattr(0, &oldterm)) {
452 perror("Cannot tcgetattr");
453 return(-1);
454 }
455
456 /* Save to original mode variable */
457 curterm = oldterm;
458
459 /* Set new modes */
460 /* disable XON/XOFF. We want to use ^S/^Q */
461 curterm.c_iflag &= ~(INLCR|ICRNL|IGNCR|IXON|IXANY|IXOFF);
462 curterm.c_lflag &= ~(ICANON|ISIG|ECHO|IEXTEN);
463 curterm.c_cc[VMIN] = 1;
464 curterm.c_cc[VTIME] = 0;
465 #ifdef VLNEXT
466 curterm.c_cc[VLNEXT] = -1;
467 #endif
468
469 #if AVVION
470 /* Set line discipline for Data General */
471 curterm.c_line = 0;
472 #endif
473
474 /* Set tty mode */
475 if (tcsetattr(0, TCSANOW, &curterm)) {
476 perror("Cannot tcsetattr");
477 return(-1);
478 }
479 #endif /* (AVVION || TERMIOS) */
480
481 /* Success */
482 return(0);
483 }
484
485 /** Close terminal device **/
ttclose()486 int ttclose()
487 {
488 #if ((AIX == 0) && (TERMIOS == 0)) || (FREEBSD == 1)
489 /* Restore original terminal modes */
490 if (reset != (char*)NULL)
491 write(1, reset, strlen(reset));
492 #endif
493
494 #if (BSD && !TERMIOS)
495 if (ioctl(0, TIOCSETP, &oldsgtty) ||
496 ioctl(0, TIOCSETC, &oldtchars) ||
497 ioctl(0, TIOCSLTC, &oldlchars))
498 return(-1);
499 #endif /* (BSD && !TERMIOS) */
500
501 #if USG || AIX || AUX || SMOS || HPUX8 || HPUX9 || (SUN && !TERMIOS) || XENIX
502 #if SMOS
503 /* Extended settings; 890619mhs A3 */
504 set_parm(0,-1,-1);
505 #endif /* SMOS */
506 if (ioctl(0, TCSETA, &oldterm))
507 return(-1);
508 #endif /* USG || AIX || AUX || SMOS || HPUX8 || HPUX9 || (SUN && !TERMIOS) || XENIX */
509
510 #if (AVVION || TERMIOS)
511 /* Set tty mode */
512 if (tcsetattr(0, TCSANOW, &oldterm)) {
513 perror("Cannot tcsetattr");
514 return(-1);
515 }
516 #endif /* (AVVION || TERMIOS) */
517
518 /* Success */
519 return(0);
520 }
521
522 /** Flush output buffer to display **/
ttflush()523 int ttflush()
524 {
525 #if TERMCAP
526 int len;
527
528 /* Compute length of write */
529 len = outbuft - outbuf;
530 if (len == 0)
531 return(0);
532
533 /* Reset buffer position */
534 outbuft = outbuf;
535
536 /* Perform write to screen */
537 return(write(1, outbuf, len) != len);
538 #else /* TERMCAP */
539 #if CURSES
540 refresh();
541 #endif /* CURSES */
542 return(0);
543 #endif /* TERMCAP */
544 }
545
546 /** Put character onto display **/
ttputc(ch)547 int ttputc(ch)
548 char ch; /* Character to display */
549 {
550 #if TERMCAP
551 /* Check for buffer full */
552 if (outbuft == &outbuf[sizeof(outbuf)])
553 ttflush();
554
555 /* Add to buffer */
556 *outbuft++ = ch;
557 #endif /* TERMCAP */
558
559 #if CURSES
560 /* Put character on screen */
561 addch(ch);
562 #endif /* CURSES */
563
564 return(0);
565 }
566
567
568 /** Grab input characters, with wait **/
grabwait()569 unsigned char grabwait()
570 {
571 #if (BSD && !TERMIOS)
572 unsigned char ch;
573
574 /* Perform read */
575 if (read(0, &ch, 1) != 1) {
576 puts("** Horrible read error occured **");
577 exit(1);
578 }
579 return(ch);
580 #endif /* (BSD && !TERMIOS) */
581 #if USG || AIX || AUX || SMOS || HPUX8 || HPUX9 || (SUN && !TERMIOS) || XENIX || (AVVION || TERMIOS)
582 unsigned char ch;
583
584 /* Change mode, if necessary */
585 if (curterm.c_cc[VTIME]) {
586 curterm.c_cc[VMIN] = 1;
587 curterm.c_cc[VTIME] = 0;
588 #if USG || AIX || AUX || SMOS || HPUX8 || HPUX9 || (SUN && !TERMIOS) || XENIX
589 ioctl(0, TCSETA, &curterm);
590 #endif /* USG || AIX || AUX || SMOS || HPUX8 || HPUX9 || SUN || XENIX */
591 #if (AVVION || TERMIOS)
592 tcsetattr(0, TCSANOW, &curterm);
593 #endif /* (AVVION || TERMIOS) */
594 }
595
596 /* Perform read */
597 #if HANDLE_WINCH
598 while (read(0, &ch, 1) != 1) {
599 if (winch_flag)
600 return 0;
601 }
602 #else
603 if (read(0, &ch, 1) != 1) {
604 puts("** Horrible read error occured **");
605 exit(1);
606 }
607 #endif
608 /* Return new character */
609 return(ch);
610 #endif /* USG || AIX || AUX || SMOS || HPUX8 || HPUX9 || (SUN && !TERMIOS) || XENIX || (AVVION || TERMIOS) */
611 }
612
613 /** Grab input characters, short wait **/
grabnowait()614 unsigned char grabnowait()
615 {
616 #if (BSD && !TERMIOS)
617 static struct timeval timout = { 0, 500000L };
618 int count, r;
619
620 /* Select input */
621 r = 1;
622 count = select(1, &r, NULL, NULL, &timout);
623 if (count == 0)
624 return(TIMEOUT);
625 if (count < 0) {
626 puts("** Horrible select error occured **");
627 exit(1);
628 }
629
630 /* Perform read */
631 return(grabwait());
632 #endif /* (BSD && !TERMIOS) */
633 #if USG || AIX || AUX || SMOS || HPUX8 || HPUX9 || SUN || XENIX || (AVVION || TERMIOS)
634 int count;
635 unsigned char ch;
636
637 /* Change mode, if necessary */
638 if (curterm.c_cc[VTIME] == 0) {
639 curterm.c_cc[VMIN] = 0;
640 curterm.c_cc[VTIME] = 5;
641 #if USG || AIX || AUX || SMOS || HPUX8 || HPUX9 || (SUN && !TERMIOS) || XENIX
642 ioctl(0, TCSETA, &curterm);
643 #endif /* USG || AIX || AUX || SMOS || HPUX8 || HPUX9 || (SUN && !TERMIOS) || XENIX */
644 #if (AVVION || TERMIOS)
645 tcsetattr(0, TCSANOW, &curterm);
646 #endif /* (AVVION || TERMIOS) */
647 }
648
649 /* Perform read */
650 #if HANDLE_WINCH
651 while ((count = read(0, &ch, 1)) < 0) {
652 if (winch_flag)
653 return 0;
654 }
655 #else
656 count = read(0, &ch, 1);
657 if (count < 0) {
658 puts("** Horrible read error occured **");
659 exit(1);
660 }
661 #endif
662 if (count == 0)
663 return(TIMEOUT);
664
665 /* Return new character */
666 return(ch);
667 #endif /* USG || AIX || AUX || SMOS || HPUX8 || HPUX9 || SUN || XENIX || (AVVION || TERMIOS) */
668 }
669
670 /*
671 * qin - queue in a character to the input buffer.
672 */
673 #if PROTO
qin(int ch)674 VOID qin(int ch)
675 #else
676 VOID qin( ch)
677 int ch;
678 #endif
679 {
680 /* Check for overflow */
681 if (inbuft == &inbuf[sizeof(inbuf)]) {
682 /* Annoy user */
683 scbeep();
684 return;
685 }
686
687 /* Add character */
688 *inbuft++ = ch;
689 }
690
691 /*
692 * qrep - replace a key sequence with a single character in the input buffer.
693 */
694 #if PROTO
qrep(int ch)695 VOID qrep(int ch)
696 #else
697 VOID qrep( ch)
698 int ch;
699 #endif
700 {
701 inbuft = inbuf;
702 qin(ch);
703 }
704
705
706 /** Return cooked characters **/
ttgetc()707 int ttgetc()
708 {
709 int ch;
710 ttflush();
711 /* Loop until character is in input buffer */
712 while (inbufh == inbuft)
713 cook();
714
715 /* Get input from buffer, now that it is available */
716 ch = *inbufh++;
717
718 /* reset us to the beginning of the buffer if there are no more
719 pending characters */
720 if (inbufh == inbuft)
721 inbufh = inbuft = inbuf;
722
723 /* Return next character */
724 return(ch);
725 }
726
727 #if TYPEAH
typahead()728 int typahead()
729 {
730 int count;
731
732 /* See if internal buffer is non-empty */
733 if (inbufh != inbuft)
734 return(1);
735
736 /* Now check with system */
737 #ifdef FIONREAD /* Watch out! This could bite you! */
738 /* Get number of pending characters */
739 if (ioctl(0, FIONREAD, &count))
740 return(0);
741 return(count);
742 #else /* not FIONREAD */
743 #ifdef VAT
744 return(0);
745 #else /* not VAT */
746 /* Ask hardware for count */
747 count = ioctl(0, FIORDCHK, 0);
748 if (count < 0)
749 return(0);
750 return(count);
751 #endif /* VAT */
752 #endif /* FIONREAD */
753 }
754 #endif /* TYPEAH */
755
756 #if TERMCAP || TERMIOS
757 /** Put out sequence, with padding **/
putpad(seq)758 void putpad(seq)
759 char * seq; /* Character sequence */
760 {
761 /* Check for null */
762 if (!seq)
763 return;
764
765 /* Call on termcap to send sequence */
766 tputs(seq, 1, ttputc);
767 }
768 #endif /* TERMCAP */
769
770 /** Initialize screen package **/
scopen()771 int scopen()
772 {
773 #if TERMCAP || TERMIOS
774 char * cp, tcbuf[1024];
775 int status;
776 struct capbind * cb;
777 struct keybind * kp;
778 char err_str[NSTRING];
779
780 char * tgetstr();
781
782 #ifndef VAT
783 #define TGETSTR(a,b) tgetstr((a), (b))
784 #else
785 #define TGETSTR(a,b) tgetstr((a), *(b))
786 #endif
787
788 #if HPUX8 || HPUX9 || VAT || AUX || (AVVION || TERMIOS) || AIX
789
790 /* HP-UX and AUX doesn't seem to have these in the termcap library */
791 char PC, * UP;
792 short ospeed;
793 #else /* not HPUX8 || HPUX9 || VAT || AUX */
794 extern char PC, * UP;
795 extern short ospeed;
796 #endif /* HPUX8 || HPUX9 || VAT || AUX */
797
798 /* Get terminal type */
799 cp = getenv("TERM");
800 if (!cp) {
801 puts(TEXT182);
802 /* "Environment variable \"TERM\" not define!" */
803 exit(1);
804 }
805
806 /* Try to load termcap */
807 status = tgetent(tcbuf, cp);
808 if (status == -1) {
809 puts("Cannot open termcap file");
810 exit(1);
811 }
812 if (status == 0) {
813 sprintf(err_str, TEXT183, cp);
814 /* "No entry for terminal type \"%s\"\n" */
815 puts(err_str);
816 exit(1);
817 }
818
819 /*
820 * If LINES and/or COLUMNS are set in the environment then use those
821 * values, otherwise get them from termcap.
822 */
823 if ((cp = getenv("LINES")) == NULL || sscanf(cp, "%d",
824 &term.t_nrow) != 1)
825 term.t_nrow = tgetnum("li");
826 term.t_nrow -= 1;
827
828 if ((cp = getenv("COLUMNS")) == NULL || sscanf(cp, "%d",
829 &term.t_ncol) != 1)
830 term.t_ncol = tgetnum("co");
831
832 if (term.t_nrow < 3 || term.t_ncol < 3) {
833 puts("Screen size is too small!");
834 exit(1);
835 }
836
837 /* initialize max number of rows and cols */
838 term.t_mrow = term.t_nrow;
839 term.t_mcol = term.t_ncol;
840
841 /* Start grabbing termcap commands */
842 cp = tcapbuf;
843
844 /* Get the reset string */
845 reset = TGETSTR("is", &cp);
846
847 /* Get the pad character */
848 if (tgetstr("pc", &cp))
849 PC = tcapbuf[0];
850
851 /* Get up line capability */
852 UP = TGETSTR("up", &cp);
853
854 /* Get other capabilities */
855 cb = capbind;
856 while (cb < &capbind[sizeof(capbind)/sizeof(*capbind)]) {
857 cb->store = TGETSTR(cb->name, &cp);
858 cb++;
859 }
860
861 /* Check for minimum */
862 if (!capbind[CAP_CL].store && (!capbind[CAP_CM].store || !UP)) {
863 puts("This terminal doesn't have enough power to run microEmacs!");
864 exit(1);
865 }
866
867 /* Set reverse video and erase to end of line */
868 if (capbind[CAP_SO].store && capbind[CAP_SE].store)
869 revexist = TRUE;
870 if (!capbind[CAP_CE].store)
871 eolexist = FALSE;
872
873 /* Get keybindings */
874 kp = keybind;
875 while (kp < &keybind[sizeof(keybind)/sizeof(*keybind)]) {
876 addkey(TGETSTR(kp->name, &cp), kp->value);
877 kp++;
878 }
879
880 /* check for HP-Terminal (so we can label its function keys) */
881 hpterm = tgetflag("xs");
882
883 /* Open terminal device */
884 if (ttopen()) {
885 puts("Cannot open terminal");
886 exit(1);
887 }
888
889 /* Set speed for padding sequences */
890 #if (BSD && !TERMIOS)
891 ospeed = cursgtty.sg_ospeed;
892 #endif /* (BSD && !TERMIOS) */
893 #if USG || AIX || AUX || SMOS || HPUX8 || HPUX9 || (SUN && !TERMIOS) || XENIX
894 ospeed = curterm.c_cflag & CBAUD;
895 #endif /* USG || AIX || AUX || SMOS || HPUX8 || HPUX9 || (SUN && !TERMIOS) || XENIX */
896 #if (AVVION || TERMIOS)
897 ospeed = cfgetospeed(&curterm);
898 #endif /* (AVVION || TERMIOS) */
899
900 /* Send out initialization sequences */
901 #if AIX == 0
902 putpad(capbind[CAP_IS].store);
903 #endif
904 putpad(capbind[CAP_KS].store);
905 sckopen();
906 #endif /* TERMCAP */
907
908 #if CURSES
909 /* Initialize screen */
910 initscr();
911
912 /* Set size of screen */
913 term.t_nrow = LINES - 1;
914 term.t_ncol = COLS;
915
916 /* Open terminal device */
917 if (ttopen()) {
918 puts("Cannot open terminal");
919 exit(1);
920 }
921 #endif /* CURSES */
922
923 /* Success */
924 return(0);
925 }
926
927 /** Close screen package **/
scclose()928 int scclose()
929 {
930 #if TERMCAP
931 /* Turn off keypad mode */
932 putpad(capbind[CAP_KE].store);
933 sckclose();
934
935 /* Close terminal device */
936 ttflush();
937 ttclose();
938 #endif /* TERMCAP */
939
940 #if TERMIOS
941 /* Close terminal device */
942 ttflush();
943 ttclose();
944 #endif /* TERMIOS */
945
946 #if CURSES
947 /* Turn off curses */
948 endwin();
949
950 /* Close terminal device */
951 ttflush();
952 ttclose();
953 #endif /* CURSES */
954
955 /* Success */
956 return(0);
957 }
958
959 /* open keyboard -hm */
sckopen()960 int sckopen()
961 {
962 #if TERMCAP
963 putpad(capbind[CAP_KS].store);
964 ttflush();
965 #if FLABEL
966 dis_ufk();
967 #endif
968 #endif
969 }
970
971 /* close keyboard -hm */
sckclose()972 int sckclose()
973 {
974 #if TERMCAP
975 putpad(capbind[CAP_KE].store);
976 ttflush();
977 #if FLABEL
978 dis_sfk();
979 #endif
980 #endif
981 }
982
983 /** Move cursor **/
scmove(row,col)984 int scmove(row, col)
985 int row; /* Row number */
986 int col; /* Column number */
987 {
988 char *tgoto();
989
990 #if TERMCAP || TERMIOS
991 /* Call on termcap to create move sequence */
992 putpad(tgoto(capbind[CAP_CM].store, col, row));
993 #endif /* TERMCAP */
994
995 #if CURSES
996 move(row, col);
997 #endif /* CURSES */
998
999 /* Success */
1000 return(0);
1001 }
1002
1003 /** Erase to end of line **/
sceeol()1004 int sceeol()
1005 {
1006 #if TERMCAP || TERMIOS
1007 /* Send erase sequence */
1008 putpad(capbind[CAP_CE].store);
1009 #endif /* TERMCAP */
1010
1011 #if CURSES
1012 clrtoeol();
1013 #endif /* CURSES */
1014
1015 /* Success */
1016 return(0);
1017 }
1018
1019 /** Clear screen **/
sceeop()1020 int sceeop()
1021 {
1022 #if TERMCAP || TERMIOS
1023 #if COLOR
1024 scfcol(gfcolor);
1025 scbcol(gbcolor);
1026 #endif /* COLOR */
1027 /* Send clear sequence */
1028 putpad(capbind[CAP_CL].store);
1029 #endif /* TERMCAP */
1030
1031 #if CURSES
1032 erase();
1033 #endif /* CURSES */
1034
1035
1036 /* Success */
1037 return(0);
1038 }
1039
1040 /** Set reverse video state **/
screv(state)1041 int screv(state)
1042 int state; /* New state */
1043 {
1044 #if TERMCAP || TERMIOS
1045 #if COLOR
1046 int ftmp, btmp; /* temporaries for colors */
1047 #endif /* COLOR */
1048
1049 /* Set reverse video state */
1050 putpad(state ? capbind[CAP_SO].store : capbind[CAP_SE].store);
1051
1052 #if COLOR
1053 if (state == FALSE) {
1054 ftmp = cfcolor;
1055 btmp = cbcolor;
1056 cfcolor = -1;
1057 cbcolor = -1;
1058 scfcol(ftmp);
1059 scbcol(btmp);
1060 }
1061 #endif /* COLOR */
1062 #endif /* TERMCAP */
1063
1064 #if CURSES
1065 if (state)
1066 standout();
1067 else
1068 standend();
1069 #endif /* CURSES */
1070
1071 /* Success */
1072 return(0);
1073 }
1074
1075 /** Beep **/
scbeep()1076 scbeep()
1077 {
1078 #if TERMCAP || TERMIOS
1079 #if !NOISY
1080 /* Send out visible bell, if it exists */
1081 if (capbind[CAP_VB].store)
1082 putpad(capbind[CAP_VB].store);
1083 else
1084 #endif /* not NOISY */
1085 /* The old standby method */
1086 ttputc('\7');
1087 #endif /* TERMCAP */
1088
1089 #if CURSES
1090 addch('\7'); /* FIX THIS! beep() and flash comes up undefined */
1091 #endif /* CURSES */
1092
1093 /* Success */
1094 return(0);
1095 }
1096
1097 #if COLOR
1098 static char cmap[8] = { 0, 4, 2, 6, 1, 5, 3, 7 };
1099
1100 /** Set foreground color **/
scfcol(color)1101 int scfcol(color)
1102 int color; /* Color to set */
1103 {
1104 #if TERMCAP || TERMIOS
1105 /* Skip if already the correct color */
1106 if (color == cfcolor)
1107 return(0);
1108
1109 /* Send out color sequence */
1110 if (capbind[CAP_C0].store) {
1111 putpad(capbind[CAP_C0 + (color & 7)].store);
1112 cfcolor = color;
1113 }
1114 #if USG || AUX
1115 else if (capbind[CAP_SF].store) {
1116 putpad(tparm(capbind[CAP_SF].store, cmap[color & 7]));
1117 cfcolor = color;
1118 }
1119 #endif /* USG || AUX */
1120 #endif /* TERMCAP */
1121
1122 #if CURSES
1123 /* ? */
1124 #endif /* CURSES */
1125 return(0);
1126 }
1127
1128 /** Set background color **/
scbcol(color)1129 int scbcol(color)
1130 int color; /* Color to set */
1131 {
1132 #if TERMCAP || TERMIOS
1133 /* Skip if already the correct color */
1134 if (color == cbcolor)
1135 return(0);
1136
1137 /* Send out color sequence */
1138 if (capbind[CAP_C0].store) {
1139 putpad(capbind[CAP_D0 + (color & 7)].store);
1140 cbcolor = color;
1141 }
1142 #if USG || AUX
1143 else if (capbind[CAP_SB].store) {
1144 putpad(tparm(capbind[CAP_SB].store, cmap[color & 7]));
1145 cbcolor = color;
1146 }
1147 #endif /* USG || AUX */
1148 #endif /* TERMCAP */
1149
1150 #if CURSES
1151 /* ? */
1152 #endif /* CURSES */
1153 return(0);
1154 }
1155 #endif /* COLOR */
1156
1157 /** Set palette **/
spal(cmd)1158 int spal(cmd)
1159 char * cmd; /* Palette command */
1160 {
1161 int code, dokeymap;
1162 char * cp;
1163
1164 /* Check for keymapping command */
1165 if (strncmp(cmd, "KEYMAP ", 7) == 0)
1166 dokeymap = 1;
1167 else
1168 #if TERMCAP
1169 #if COLOR
1170 if (strncmp(cmd, "CLRMAP ", 7) == 0)
1171 dokeymap = 0;
1172 else
1173 #endif /* COLOR */
1174 #endif /* TERMCAP */
1175 return(0);
1176 cmd += 7;
1177
1178 /* Look for space */
1179 for (cp = cmd; *cp != '\0'; cp++)
1180 if (*cp == ' ') {
1181 *cp++ = '\0';
1182 break;
1183 }
1184 if (*cp == '\0')
1185 return(1);
1186
1187 /* Perform operation */
1188 if (dokeymap) {
1189
1190 /* Convert to keycode */
1191 code = stock(cmd);
1192
1193 /* Add to tree */
1194 addkey(cp, code);
1195 }
1196 #if TERMCAP
1197 #if COLOR
1198 else {
1199
1200 /* Convert to color number */
1201 code = atoi(cmd);
1202 if (code < 0 || code > 15)
1203 return(1);
1204
1205 /* Move color code to capability structure */
1206 capbind[CAP_C0 + code].store = malloc(strlen(cp) + 1);
1207 if (capbind[CAP_C0 + code].store)
1208 strcpy(capbind[CAP_C0 + code].store, cp);
1209 }
1210 #endif /* COLOR */
1211 #endif /* TERMCAP */
1212 return(0);
1213 }
1214
1215 #if BSD || FREEBSD || SUN || HPUX8 || HPUX9 || (AVVION || TERMIOS)
1216 /* Surely more than just BSD systems do this */
1217
1218 /** Perform a stop signal **/
bktoshell(f,n)1219 int bktoshell(f, n)
1220 {
1221 /* Reset the terminal and go to the last line */
1222 vttidy();
1223
1224 /* Okay, stop... */
1225 kill(getpid(), SIGTSTP);
1226
1227 /* We should now be back here after resuming */
1228
1229 /* Reopen the screen and redraw */
1230 scopen();
1231 curwp->w_flag = WFHARD;
1232 sgarbf = TRUE;
1233
1234 /* Success */
1235 return(0);
1236 }
1237
1238 #endif /* BSD || FREEBSD || SUN || HPUX8 || HPUX9 || (AVVION || TERMIOS) */
1239
1240 /** Get time of day **/
timeset()1241 char * timeset()
1242 {
1243 long int buf; /* Should be time_t */
1244 char * sp, * cp;
1245
1246 char * ctime();
1247
1248 /* Get system time */
1249 time(&buf);
1250
1251 /* Pass system time to converter */
1252 sp = ctime(&buf);
1253
1254 /* Eat newline character */
1255 for (cp = sp; *cp; cp++)
1256 if (*cp == '\n') {
1257 *cp = '\0';
1258 break;
1259 }
1260 return(sp);
1261 }
1262
1263 #if USG || AUX || SMOS || HPUX8 || XENIX
1264 /** Rename a file **/
rename(file1,file2)1265 int rename(file1, file2)
1266 char * file1; /* Old file name */
1267 char * file2; /* New file name */
1268 {
1269 struct stat buf1;
1270 struct stat buf2;
1271
1272 /* No good if source file doesn't exist */
1273 if (stat(file1, &buf1))
1274 return(-1);
1275
1276 /* Check for target */
1277 if (stat(file2, &buf2) == 0) {
1278
1279 /* See if file is the same */
1280 if (buf1.st_dev == buf2.st_dev &&
1281 buf1.st_ino == buf2.st_ino)
1282
1283 /* Not necessary to rename file */
1284 return(0);
1285 }
1286
1287 /* Get rid of target */
1288 unlink(file2);
1289
1290 /* Link two files together */
1291 if (link(file1, file2))
1292 return(-1);
1293
1294 /* Unlink original file */
1295 return(unlink(file1));
1296 }
1297 #endif /* USG || AUX || SMOS || HPUX8 || XENIX */
1298
1299 /** Callout to system to perform command **/
callout(cmd)1300 int callout(cmd)
1301 char * cmd; /* Command to execute */
1302 {
1303 int status;
1304
1305 /* Close down */
1306 scmove(term.t_nrow, 0);
1307 ttflush();
1308 sckclose();
1309 ttclose();
1310
1311 /* Do command */
1312 status = system(cmd) == 0;
1313
1314 /* Restart system */
1315 sgarbf = TRUE;
1316 sckopen();
1317 if (ttopen()) {
1318 puts("** Error reopening terminal device **");
1319 exit(1);
1320 }
1321
1322 /* Success */
1323 return(status);
1324 }
1325
1326 /** Create subshell **/
spawncli(f,n)1327 int spawncli(f, n)
1328 int f; /* Flags */
1329 int n; /* Argument count */
1330 {
1331 char * sh;
1332
1333 /* Don't allow this command if restricted */
1334 if (restflag)
1335 return(resterr());
1336
1337 /* Get shell path */
1338 sh = getenv("SHELL");
1339 if (!sh)
1340 #if BSD || FREEBSD || SUN
1341 sh = "/bin/csh";
1342 #endif /* BSD || FREEBSD || SUN */
1343 #if USG || AIX || AUX || SMOS || HPUX8 || HPUX9 || XENIX || (AVVION || TERMIOS)
1344 sh = "/bin/sh";
1345 #endif /* USG || AIX || AUX || SMOS || HPUX8 || HPUX9 || XENIX || (AVVION || TERMIOS) */
1346
1347 /* Do shell */
1348 return(callout(sh));
1349 }
1350
1351 /** Spawn a command **/
spawn(f,n)1352 int spawn(f, n)
1353 int f; /* Flags */
1354 int n; /* Argument count */
1355 {
1356 char line[NLINE];
1357 int s;
1358
1359 /* Don't allow this command if restricted */
1360 if (restflag)
1361 return(resterr());
1362
1363 /* Get command line */
1364 s = mlreply("!", line, NLINE);
1365 if (!s)
1366 return(s);
1367
1368 /* Perform the command */
1369 s = callout(line);
1370
1371 /* if we are interactive, pause here */
1372 if (clexec == FALSE) {
1373 mlwrite("[End]");
1374 ttflush();
1375 ttgetc();
1376 }
1377 return(s);
1378 }
1379
1380 /** Execute program **/
execprg(f,n)1381 int execprg(f, n)
1382 int f; /* Flags */
1383 int n; /* Argument count */
1384 {
1385 /* Same as spawn */
1386 return(spawn(f, n));
1387 }
1388
1389 /** Pipe output of program to buffer **/
pipecmd(f,n)1390 int pipecmd(f, n)
1391 int f; /* Flags */
1392 int n; /* Argument count */
1393 {
1394 char line[NLINE];
1395 int s;
1396 BUFFER * bp;
1397 EWINDOW * wp;
1398 static char filnam[] = "command";
1399
1400 /* Don't allow this command if restricted */
1401 if (restflag)
1402 return(resterr());
1403
1404 /* Get pipe-in command */
1405 s = mlreply("@", line, NLINE);
1406 if (!s)
1407 return(s);
1408
1409 /* Get rid of the command output buffer if it exists */
1410 bp = bfind(filnam, FALSE, 0);
1411 if (bp) {
1412 /* Try to make sure we are off screen */
1413 wp = wheadp;
1414 while (wp) {
1415 if (wp->w_bufp == bp) {
1416 onlywind(FALSE, 1);
1417 break;
1418 }
1419 wp = wp->w_wndp;
1420 }
1421 if (!zotbuf(bp))
1422 return(0);
1423 }
1424
1425 /* Add output specification */
1426 strcat(line, ">");
1427 strcat(line, filnam);
1428
1429 /* Do command */
1430 s = callout(line);
1431 if (!s)
1432 return(s);
1433
1434 /* Split the current window to make room for the command output */
1435 if (!splitwind(FALSE, 1))
1436 return(0);
1437
1438 /* ...and read the stuff in */
1439 if (!getfile(filnam, FALSE))
1440 return(0);
1441
1442 /* Make this window in VIEW mode, update all mode lines */
1443 curwp->w_bufp->b_mode |= MDVIEW;
1444 wp = wheadp;
1445 while (wp) {
1446 wp->w_flag |= WFMODE;
1447 wp = wp->w_wndp;
1448 }
1449
1450 /* ...and get rid of the temporary file */
1451 unlink(filnam);
1452 return(1);
1453 }
1454
1455 /** Filter buffer through command **/
filter(f,n)1456 int filter(f, n)
1457 int f; /* Flags */
1458 int n; /* Argument count */
1459 {
1460 char line[NLINE], tmpnam[NFILEN];
1461 int s;
1462 BUFFER * bp;
1463 static char bname1[] = "fltinp";
1464 static char filnam1[] = "fltinp";
1465 static char filnam2[] = "fltout";
1466
1467 /* Don't allow this command if restricted */
1468 if (restflag)
1469 return(resterr());
1470
1471 /* Don't allow filtering of VIEW mode buffer */
1472 if (curbp->b_mode & MDVIEW)
1473 return(rdonly());
1474
1475 /* Get the filter name and its args */
1476 s = mlreply("#", line, NLINE);
1477 if (!s)
1478 return(s);
1479
1480 /* Setup the proper file names */
1481 bp = curbp;
1482 strcpy(tmpnam, bp->b_fname); /* Save the original name */
1483 strcpy(bp->b_fname, bname1); /* Set it to our new one */
1484
1485 /* Write it out, checking for errors */
1486 if (!writeout(filnam1, "w")) {
1487 mlwrite("[Cannot write filter file]");
1488 strcpy(bp->b_fname, tmpnam);
1489 return(0);
1490 }
1491
1492 /* Setup input and output */
1493 strcat(line," <fltinp >fltout");
1494
1495 /* Perform command */
1496 s = callout(line);
1497
1498 /* If successful, read in file */
1499 if (s) {
1500 s = readin(filnam2, FALSE);
1501 if (s)
1502 /* Mark buffer as changed */
1503 bp->b_flag |= BFCHG;
1504 }
1505
1506
1507 /* Reset file name */
1508 strcpy(bp->b_fname, tmpnam);
1509
1510 /* and get rid of the temporary file */
1511 unlink(filnam1);
1512 unlink(filnam2);
1513
1514 /* Show status */
1515 if (!s)
1516 mlwrite("[Execution failed]");
1517 return(s);
1518 }
1519
1520 /** Get first filename from pattern **/
getffile(fspec)1521 char *getffile(fspec)
1522 char *fspec; /* Filename specification */
1523 {
1524 int index, point, extflag;
1525
1526 /* First parse the file path off the file spec */
1527 strcpy(path, fspec);
1528 index = strlen(path) - 1;
1529 while (index >= 0 && (path[index] != '/'))
1530 --index;
1531 path[index+1] = '\0';
1532
1533
1534 /* Check for an extension */
1535 point = strlen(fspec) - 1;
1536 extflag = FALSE;
1537 while (point >= 0) {
1538 if (fspec[point] == '.') {
1539 extflag = TRUE;
1540 break;
1541 }
1542 point--;
1543 }
1544
1545 /* Open the directory pointer */
1546 if (dirptr) {
1547 closedir(dirptr);
1548 dirptr = NULL;
1549 }
1550
1551 dirptr = opendir((path[0] == '\0') ? "./" : path);
1552
1553 if (!dirptr)
1554 return(NULL);
1555
1556 strcpy(rbuf, path);
1557 nameptr = &rbuf[strlen(rbuf)];
1558
1559 /* ...and call for the first file */
1560 return(getnfile());
1561 }
1562
1563 /** Get next filename from pattern **/
getnfile()1564 char *getnfile()
1565 {
1566 int index;
1567 struct DIRENTRY * dp;
1568 struct stat fstat;
1569
1570 /* ...and call for the next file */
1571 do {
1572 dp = readdir(dirptr);
1573 if (!dp)
1574 return(NULL);
1575
1576 /* Check to make sure we skip all weird entries except directories */
1577 strcpy(nameptr, dp->d_name);
1578
1579 } while (stat(rbuf, &fstat) ||
1580 ((fstat.st_mode & S_IFMT) & (S_IFREG | S_IFDIR)) == 0);
1581
1582 /* if this entry is a directory name, say so */
1583 if ((fstat.st_mode & S_IFMT) == S_IFDIR)
1584 strcat(rbuf, DIRSEPSTR);
1585
1586 /* Return the next file name! */
1587 return(rbuf);
1588 }
1589
1590 #if FLABEL
1591 /*---------------------------------------------------------------------------*
1592
1593 handle the function keys and function key labels on HP-Terminals
1594 -----------------------------------------------------------------
1595
1596 Hellmuth Michaelis e-mail: hm@hcshh.hcs.de
1597
1598 *---------------------------------------------------------------------------*/
1599
1600 static unsigned char flabstor[8][50]; /* label & xmit backup store */
1601 static char flabstof[8] = {0,0,0,0,0,0,0,0}; /* filled flag */
1602
fnclabel(f,n)1603 int fnclabel(f, n) /* label a function key */
1604
1605 int f; /* Default argument */
1606 int n; /* function key number 1...8 on hp-terminals */
1607
1608 {
1609 char lbl[20]; /* label string buffer */
1610 char xmit[5]; /* transmitted string ( ESC 'p'...'w' ) */
1611 char buf[80]; /* writeout buffer */
1612 int i; /* general purpose index */
1613 int status; /* return status */
1614
1615 /* check if we are connected to an hp-terminal */
1616 if (!hpterm)
1617 return(FALSE);
1618
1619 /* must be called with an argument */
1620 if (f == FALSE) {
1621 mlwrite(TEXT246);
1622 /* "%%Need function key number"*/
1623 return(FALSE);
1624 }
1625
1626 /* and it must be a legal key number */
1627 if (n < 1 || n > 8) {
1628 mlwrite(TEXT247);
1629 /* "%%Function key number out of range"*/
1630 return(FALSE);
1631 }
1632
1633 /* get the string to send */
1634 lbl[0] = '\0'; /* we don't now the label yet */
1635
1636 if ((status = mlreply(TEXT248, lbl, 19)) != TRUE)
1637 /* "Enter Label String: "*/
1638 return(status);
1639
1640 lbl[16] = '\0';
1641 i = strlen(lbl);
1642
1643 /* set up escape sequence to send to terminal */
1644 xmit[0] = 0x1b;
1645 xmit[1] = 'o' + n;
1646 xmit[2] = '\0';
1647
1648 sprintf(flabstor[n-1], "%c&f0a%dk%dd2L%s%s", (char)0x1b, n, i,
1649 lbl, xmit);
1650 write(1, flabstor[n-1], strlen(flabstor[n-1]));
1651 flabstof[n-1] = 1;
1652
1653 sprintf(buf, "%c&jB", (char)0x1b);
1654 write(1, buf, strlen(buf));
1655
1656 return(TRUE);
1657 }
1658
1659 /* display user function key labels */
dis_ufk()1660 static void dis_ufk()
1661
1662 {
1663 int label_num;
1664 char buf[6];
1665
1666 if (!hpterm)
1667 return;
1668
1669 for (label_num = 0; label_num < 8; label_num++)
1670 if (flabstof[label_num])
1671 write(1, flabstor[label_num],
1672 strlen(flabstor[label_num]));
1673 sprintf(buf, "%c&jB", (char)0x1b);
1674 write(1, buf, strlen(buf));
1675 }
1676
1677 /* display system function key labels */
dis_sfk()1678 static void dis_sfk()
1679
1680 {
1681 char buf[6];
1682
1683 if (!hpterm)
1684 return;
1685 sprintf(buf, "%c&jA", (char)0x1b);
1686 write(1, buf, strlen(buf));
1687 }
1688 #endif /* FLABEL */
1689
1690 #if XENIX && FILOCK
mkdir(name,mode)1691 int mkdir(name, mode)
1692 char *name; /* name of directory to create */
1693 int mode; /* umask for creation (which we blissfully ignore...) */
1694 {
1695 char buf[80];
1696
1697 strcpy(buf, "mkdir ");
1698 strcat(buf, name);
1699 strcat(buf, " > /dev/null 2>&1");
1700 return(system(buf));
1701 }
1702
rmdir(name)1703 int rmdir(name)
1704 char *name; /* name of directory to delete */
1705 {
1706 char buf[80];
1707
1708 strcpy(buf,"rmdir ");
1709 strcat(buf, name);
1710 strcat(buf, " > /dev/null 2>&1");
1711 return(system(buf));
1712 }
1713 #endif /* XENIX & FILOCK */
1714
1715 #if HANDLE_WINCH
1716 /*
1717 * Window size changes handled via signals.
1718 */
winch_changed()1719 void winch_changed()
1720 {
1721 signal(SIGWINCH,winch_changed);
1722 winch_flag = 1;
1723 }
1724
winch_new_size()1725 void winch_new_size()
1726 {
1727 EWINDOW *wp;
1728 struct winsize win;
1729
1730 winch_flag=0;
1731 ioctl(fileno(stdin),TIOCGWINSZ,&win);
1732 winch_vtresize(win.ws_row,win.ws_col);
1733 onlywind(0,0);
1734 TTmove(0,0);
1735 TTeeop();
1736 }
1737 #endif
1738
1739 #endif /* BSD || FREEBSD || USG || AIX || AUX || SMOS || HPUX8 || HPUX9 || SUN || XENIX || (AVVION || TERMIOS) */
1740