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