OSDN Git Service

upgrade to 3.6.2
[jnethack/source.git] / sys / share / unixtty.c
1 /* NetHack 3.6  unixtty.c       $NHDT-Date: 1548372343 2019/01/24 23:25:43 $  $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.25 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /*-Copyright (c) Michael Allison, 2006. */
4 /* NetHack may be freely redistributed.  See license for details. */
5
6 /* tty.c - (Unix) version */
7
8 /* With thanks to the people who sent code for SYSV - hpscdi!jon,
9  * arnold@ucsf-cgl, wcs@bo95b, cbcephus!pds and others.
10  */
11
12 #define NEED_VARARGS
13 #include "hack.h"
14
15 /*
16  * The distinctions here are not BSD - rest but rather USG - rest, as
17  * BSD still has the old sgttyb structure, but SYSV has termio. Thus:
18  */
19 #if (defined(BSD) || defined(ULTRIX)) && !defined(POSIX_TYPES)
20 #define V7
21 #else
22 #define USG
23 #endif
24
25 #ifdef USG
26
27 #ifdef POSIX_TYPES
28 #include <termios.h>
29 #include <unistd.h>
30 #define termstruct termios
31 #else
32 #include <termio.h>
33 #if defined(TCSETS) && !defined(AIX_31)
34 #define termstruct termios
35 #else
36 #define termstruct termio
37 #endif
38 #endif /* POSIX_TYPES */
39 #ifdef LINUX
40 #include <sys/ioctl.h>
41 #undef delay_output /* curses redefines this */
42 #include <curses.h>
43 #endif
44 #define kill_sym c_cc[VKILL]
45 #define erase_sym c_cc[VERASE]
46 #define intr_sym c_cc[VINTR]
47 #ifdef TAB3 /* not a POSIX flag, but some have it anyway */
48 #define EXTABS TAB3
49 #else
50 #define EXTABS 0
51 #endif
52 #define tabflgs c_oflag
53 #define echoflgs c_lflag
54 #define cbrkflgs c_lflag
55 #define CBRKMASK ICANON
56 #define CBRKON !/* reverse condition */
57 #ifdef POSIX_TYPES
58 #define OSPEED(x) (speednum(cfgetospeed(&x)))
59 #else
60 #ifndef CBAUD
61 #define CBAUD _CBAUD /* for POSIX nitpickers (like RS/6000 cc) */
62 #endif
63 #define OSPEED(x) ((x).c_cflag & CBAUD)
64 #endif
65 #define IS_7BIT(x) ((x).c_cflag & CS7)
66 #define inputflags c_iflag
67 #define STRIPHI ISTRIP
68 #ifdef POSIX_TYPES
69 #define GTTY(x) (tcgetattr(0, x))
70 #define STTY(x) (tcsetattr(0, TCSADRAIN, x))
71 #else
72 #if defined(TCSETS) && !defined(AIX_31)
73 #define GTTY(x) (ioctl(0, TCGETS, x))
74 #define STTY(x) (ioctl(0, TCSETSW, x))
75 #else
76 #define GTTY(x) (ioctl(0, TCGETA, x))
77 #define STTY(x) (ioctl(0, TCSETAW, x))
78 #endif
79 #endif /* POSIX_TYPES */
80 #define GTTY2(x) 1
81 #define STTY2(x) 1
82 #ifdef POSIX_TYPES
83 #if defined(BSD) && !defined(__DGUX__)
84 #define nonesuch _POSIX_VDISABLE
85 #else
86 #define nonesuch (fpathconf(0, _PC_VDISABLE))
87 #endif
88 #else
89 #define nonesuch 0
90 #endif
91 #define inittyb2 inittyb
92 #define curttyb2 curttyb
93
94 #else /* V7 */
95
96 #include <sgtty.h>
97 #define termstruct sgttyb
98 #define kill_sym sg_kill
99 #define erase_sym sg_erase
100 #define intr_sym t_intrc
101 #define EXTABS XTABS
102 #define tabflgs sg_flags
103 #define echoflgs sg_flags
104 #define cbrkflgs sg_flags
105 #define CBRKMASK CBREAK
106 #define CBRKON              /* empty */
107 #define inputflags sg_flags /* don't know how enabling meta bits */
108 #define IS_7BIT(x) (FALSE)
109 #define STRIPHI 0 /* should actually be done on BSD */
110 #define OSPEED(x) (x).sg_ospeed
111 #if defined(bsdi) || defined(__386BSD) || defined(SUNOS4)
112 #define GTTY(x) (ioctl(0, TIOCGETP, (char *) x))
113 #define STTY(x) (ioctl(0, TIOCSETP, (char *) x))
114 #else
115 #define GTTY(x) (gtty(0, x))
116 #define STTY(x) (stty(0, x))
117 #endif
118 #define GTTY2(x) (ioctl(0, TIOCGETC, (char *) x))
119 #define STTY2(x) (ioctl(0, TIOCSETC, (char *) x))
120 #define nonesuch -1
121 struct tchars inittyb2, curttyb2;
122
123 #endif /* V7 */
124
125 /*
126  * Old curses.h relied on implicit declaration of has_colors().
127  * Modern compilers tend to warn about implicit declarations and
128  * modern curses.h declares has_colors() explicitly.  However, the
129  * declaration it uses is not one we can simply clone (requires
130  * <stdbool.h>).  This simpler declaration suffices but can't be
131  * used unconditionally because it conflicts with the 'bool' one.
132  */
133 #ifdef NEED_HAS_COLORS_DECL
134 int has_colors();
135 #endif
136
137 #if defined(TTY_GRAPHICS) && ((!defined(SYSV) && !defined(HPUX)) \
138                               || defined(UNIXPC) || defined(SVR4))
139 #ifndef LINT
140 extern /* it is defined in libtermlib (libtermcap) */
141 #endif
142     short ospeed; /* terminal baudrate; set by gettty */
143 #else
144 short ospeed = 0; /* gets around "not defined" error message */
145 #endif
146
147 #if defined(POSIX_TYPES) && defined(BSD)
148 unsigned
149 #endif
150     char erase_char,
151     intr_char, kill_char;
152 static boolean settty_needed = FALSE;
153 struct termstruct inittyb, curttyb;
154
155 #ifdef POSIX_TYPES
156 static int
157 speednum(speed)
158 speed_t speed;
159 {
160     switch (speed) {
161     case B0:
162         return 0;
163     case B50:
164         return 1;
165     case B75:
166         return 2;
167     case B110:
168         return 3;
169     case B134:
170         return 4;
171     case B150:
172         return 5;
173     case B200:
174         return 6;
175     case B300:
176         return 7;
177     case B600:
178         return 8;
179     case B1200:
180         return 9;
181     case B1800:
182         return 10;
183     case B2400:
184         return 11;
185     case B4800:
186         return 12;
187     case B9600:
188         return 13;
189     case B19200:
190         return 14;
191     case B38400:
192         return 15;
193     }
194
195     return 0;
196 }
197 #endif
198
199 static void
200 setctty()
201 {
202     if (STTY(&curttyb) < 0 || STTY2(&curttyb2) < 0)
203         perror("NetHack (setctty)");
204 }
205
206 /*
207  * Get initial state of terminal, set ospeed (for termcap routines)
208  * and switch off tab expansion if necessary.
209  * Called by startup() in termcap.c and after returning from ! or ^Z
210  */
211 void
212 gettty()
213 {
214     if (GTTY(&inittyb) < 0 || GTTY2(&inittyb2) < 0)
215         perror("NetHack (gettty)");
216     curttyb = inittyb;
217     curttyb2 = inittyb2;
218     ospeed = OSPEED(inittyb);
219     erase_char = inittyb.erase_sym;
220     kill_char = inittyb.kill_sym;
221     intr_char = inittyb2.intr_sym;
222     getioctls();
223
224     /* do not expand tabs - they might be needed inside a cm sequence */
225     if (curttyb.tabflgs & EXTABS) {
226         curttyb.tabflgs &= ~EXTABS;
227         setctty();
228     }
229     settty_needed = TRUE;
230 }
231
232 /* reset terminal to original state */
233 void
234 settty(s)
235 const char *s;
236 {
237     end_screen();
238     if (s)
239         raw_print(s);
240     if (STTY(&inittyb) < 0 || STTY2(&inittyb2) < 0)
241         perror("NetHack (settty)");
242     iflags.echo = (inittyb.echoflgs & ECHO) ? ON : OFF;
243     iflags.cbreak = (CBRKON(inittyb.cbrkflgs & CBRKMASK)) ? ON : OFF;
244     curttyb.inputflags |= STRIPHI;
245     setioctls();
246 }
247
248 void
249 setftty()
250 {
251     unsigned ef, cf;
252     int change = 0;
253
254     ef = 0;                /* desired value of flags & ECHO */
255     cf = CBRKON(CBRKMASK); /* desired value of flags & CBREAK */
256     iflags.cbreak = ON;
257     iflags.echo = OFF;
258     /* Should use (ECHO|CRMOD) here instead of ECHO */
259     if ((unsigned) (curttyb.echoflgs & ECHO) != ef) {
260         curttyb.echoflgs &= ~ECHO;
261         /*              curttyb.echoflgs |= ef; */
262         change++;
263     }
264     if ((unsigned) (curttyb.cbrkflgs & CBRKMASK) != cf) {
265         curttyb.cbrkflgs &= ~CBRKMASK;
266         curttyb.cbrkflgs |= cf;
267 #ifdef USG
268         /* be satisfied with one character; no timeout */
269         curttyb.c_cc[VMIN] = 1;  /* was VEOF */
270         curttyb.c_cc[VTIME] = 0; /* was VEOL */
271 #ifdef POSIX_JOB_CONTROL
272 /* turn off system suspend character
273  * due to differences in structure layout, this has to be
274  * here instead of in ioctl.c:getioctls() with the BSD
275  * equivalent
276  */
277 #ifdef VSUSP /* real POSIX */
278         curttyb.c_cc[VSUSP] = nonesuch;
279 #else /* other later SYSV */
280         curttyb.c_cc[VSWTCH] = nonesuch;
281 #endif
282 #endif
283 #ifdef VDSUSP /* SunOS Posix extensions */
284         curttyb.c_cc[VDSUSP] = nonesuch;
285 #endif
286 #ifdef VREPRINT
287         curttyb.c_cc[VREPRINT] = nonesuch;
288 #endif
289 #ifdef VDISCARD
290         curttyb.c_cc[VDISCARD] = nonesuch;
291 #endif
292 #ifdef VWERASE
293         curttyb.c_cc[VWERASE] = nonesuch;
294 #endif
295 #ifdef VLNEXT
296         curttyb.c_cc[VLNEXT] = nonesuch;
297 #endif
298 #endif
299         change++;
300     }
301     if (!IS_7BIT(inittyb))
302         curttyb.inputflags &= ~STRIPHI;
303     /* If an interrupt character is used, it will be overridden and
304      * set to ^C.
305      */
306     if (intr_char != nonesuch && curttyb2.intr_sym != '\003') {
307         curttyb2.intr_sym = '\003';
308         change++;
309     }
310
311     if (change)
312         setctty();
313     start_screen();
314 }
315
316 void intron() /* enable kbd interupts if enabled when game started */
317 {
318 #ifdef TTY_GRAPHICS
319     /* Ugly hack to keep from changing tty modes for non-tty games -dlc */
320     if (WINDOWPORT("tty") && intr_char != nonesuch
321         && curttyb2.intr_sym != '\003') {
322         curttyb2.intr_sym = '\003';
323         setctty();
324     }
325 #endif
326 }
327
328 void introff() /* disable kbd interrupts if required*/
329 {
330 #ifdef TTY_GRAPHICS
331     /* Ugly hack to keep from changing tty modes for non-tty games -dlc */
332     if (WINDOWPORT("tty") && curttyb2.intr_sym != nonesuch) {
333         curttyb2.intr_sym = nonesuch;
334         setctty();
335     }
336 #endif
337 }
338
339 #ifdef _M_UNIX /* SCO UNIX (3.2.4), from Andreas Arens */
340 #include <sys/console.h>
341
342 #define BSIZE (E_TABSZ * 2)
343 #define LDIOC ('D' << 8) /* POSIX prevents definition */
344
345 #include <sys/emap.h>
346
347 int sco_flag_console = 0;
348 int sco_map_valid = -1;
349 unsigned char sco_chanmap_buf[BSIZE];
350
351 void NDECL(sco_mapon);
352 void NDECL(sco_mapoff);
353 void NDECL(check_sco_console);
354 void NDECL(init_sco_cons);
355
356 void
357 sco_mapon()
358 {
359 #ifdef TTY_GRAPHICS
360     if (WINDOWPORT("tty") && sco_flag_console) {
361         if (sco_map_valid != -1) {
362             ioctl(0, LDSMAP, sco_chanmap_buf);
363         }
364         sco_map_valid = -1;
365     }
366 #endif
367 }
368
369 void
370 sco_mapoff()
371 {
372 #ifdef TTY_GRAPHICS
373     if (WINDOWPORT("tty") && sco_flag_console) {
374         sco_map_valid = ioctl(0, LDGMAP, sco_chanmap_buf);
375         if (sco_map_valid != -1) {
376             ioctl(0, LDNMAP, (char *) 0);
377         }
378     }
379 #endif
380 }
381
382 void
383 check_sco_console()
384 {
385     if (isatty(0) && ioctl(0, CONS_GET, 0) != -1) {
386         sco_flag_console = 1;
387     }
388 }
389
390 void
391 init_sco_cons()
392 {
393 #ifdef TTY_GRAPHICS
394     if (WINDOWPORT("tty") && sco_flag_console) {
395         atexit(sco_mapon);
396         sco_mapoff();
397         load_symset("IBMGraphics", PRIMARY);
398         load_symset("RogueIBM", ROGUESET);
399         switch_symbols(TRUE);
400 #ifdef TEXTCOLOR
401         if (has_colors())
402             iflags.use_color = TRUE;
403 #endif
404     }
405 #endif
406 }
407 #endif /* _M_UNIX */
408
409 #ifdef __linux__ /* via Jesse Thilo and Ben Gertzfield */
410 #include <sys/vt.h>
411 #include <sys/ioctl.h>
412
413 int linux_flag_console = 0;
414
415 void NDECL(linux_mapon);
416 void NDECL(linux_mapoff);
417 void NDECL(check_linux_console);
418 void NDECL(init_linux_cons);
419
420 void
421 linux_mapon()
422 {
423 #ifdef TTY_GRAPHICS
424     if (WINDOWPORT("tty") && linux_flag_console) {
425         write(1, "\033(B", 3);
426     }
427 #endif
428 }
429
430 void
431 linux_mapoff()
432 {
433 #ifdef TTY_GRAPHICS
434     if (WINDOWPORT("tty") && linux_flag_console) {
435         write(1, "\033(U", 3);
436     }
437 #endif
438 }
439
440 void
441 check_linux_console()
442 {
443     struct vt_mode vtm;
444
445     if (isatty(0) && ioctl(0, VT_GETMODE, &vtm) >= 0) {
446         linux_flag_console = 1;
447     }
448 }
449
450 void
451 init_linux_cons()
452 {
453 #ifdef TTY_GRAPHICS
454     if (WINDOWPORT("tty") && linux_flag_console) {
455         atexit(linux_mapon);
456         linux_mapoff();
457 #ifdef TEXTCOLOR
458         if (has_colors())
459             iflags.use_color = TRUE;
460 #endif
461     }
462 #endif
463 }
464 #endif /* __linux__ */
465
466 #ifndef __begui__ /* the Be GUI will define its own error proc */
467 /* fatal error */
468 /*VARARGS1*/
469 void error
470 VA_DECL(const char *, s)
471 {
472     VA_START(s);
473     VA_INIT(s, const char *);
474     if (settty_needed)
475         settty((char *) 0);
476     Vprintf(s, VA_ARGS);
477     (void) putchar('\n');
478     VA_END();
479     exit(EXIT_FAILURE);
480 }
481 #endif /* !__begui__ */