abstract
| - Below is the full text to unixtty.c from the source code of NetHack 1.4f. To link to a particular line, write [[NetHack 1.4f/unixtty.c#line123]], for example. Warning! This is the source code from an old release. For the latest release, see Source code 1. /* SCCS Id: @(#)unixtty.c 1.4 87/08/08 2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3. /* tty.c - (Unix) version 1.0.3 */ 4. /* With thanks to the people who sent code for SYSV - hpscdi!jon, 5. arnold@ucsf-cgl, wcs@bo95b, cbcephus!pds and others. */ 6. 7. #include 8. #include "extern.h" 9. #include "flag.h" 10. #include "func_tab.h" 11. 12. #define ON 1 13. #define OFF 0 14. #define BUFSZ 256 15. 16. 17. /* 18. * The distinctions here are not BSD - rest but rather USG - rest, as 19. * BSD still has the old sgttyb structure, but SYSV has termio. Thus: 20. */ 21. #ifdef BSD 22. #define V7 23. #else 24. #define USG 25. #endif 26. 27. /* 28. * Some systems may have getchar() return EOF for various reasons, and 29. * we should not quit before seeing at least NR_OF_EOFS consecutive EOFs. 30. */ 31. #ifndef BSD 32. #define NR_OF_EOFS 20 33. #endif 34. 35. 36. #ifdef USG 37. 38. #include 39. #define termstruct termio 40. #define kill_sym c_cc[VKILL] 41. #define erase_sym c_cc[VERASE] 42. #define EXTABS TAB3 43. #define tabflgs c_oflag 44. #define echoflgs c_lflag 45. #define cbrkflgs c_lflag 46. #define CBRKMASK ICANON 47. #define CBRKON ! /* reverse condition */ 48. #define OSPEED(x) ((x).c_cflag & CBAUD) 49. #define GTTY(x) (ioctl(0, TCGETA, x)) 50. #define STTY(x) (ioctl(0, TCSETA, x)) /* TCSETAF? TCSETAW? */ 51. 52. #else /* V7 */ 53. 54. #include 55. #define termstruct sgttyb 56. #define kill_sym sg_kill 57. #define erase_sym sg_erase 58. #define EXTABS XTABS 59. #define tabflgs sg_flags 60. #define echoflgs sg_flags 61. #define cbrkflgs sg_flags 62. #define CBRKMASK CBREAK 63. #define CBRKON /* empty */ 64. #define OSPEED(x) (x).sg_ospeed 65. #define GTTY(x) (gtty(0, x)) 66. #define STTY(x) (stty(0, x)) 67. 68. #endif 69. 70. extern short ospeed; 71. static char erase_char, kill_char; 72. static boolean settty_needed = FALSE; 73. struct termstruct inittyb, curttyb; 74. 75. /* 76. * Get initial state of terminal, set ospeed (for termcap routines) 77. * and switch off tab expansion if necessary. 78. * Called by startup() in termcap.c and after returning from ! or ^Z 79. */ 80. gettty(){ 81. if(GTTY(&inittyb) < 0) 82. perror("Hack (gettty)"); 83. curttyb = inittyb; 84. ospeed = OSPEED(inittyb); 85. erase_char = inittyb.erase_sym; 86. kill_char = inittyb.kill_sym; 87. getioctls(); 88. 89. /* do not expand tabs - they might be needed inside a cm sequence */ 90. if(curttyb.tabflgs & EXTABS) { 91. curttyb.tabflgs &= ~EXTABS; 92. setctty(); 93. } 94. settty_needed = TRUE; 95. } 96. 97. /* reset terminal to original state */ 98. settty(s) char *s; { 99. clear_screen(); 100. end_screen(); 101. if(s) printf(s); 102. (void) fflush(stdout); 103. if(STTY(&inittyb) < 0) 104. perror("Hack (settty)"); 105. flags.echo = (inittyb.echoflgs & ECHO) ? ON : OFF; 106. flags.cbreak = (CBRKON(inittyb.cbrkflgs & CBRKMASK)) ? ON : OFF; 107. setioctls(); 108. } 109. 110. setctty(){ 111. if(STTY(&curttyb) < 0) 112. perror("Hack (setctty)"); 113. } 114. 115. 116. setftty(){ 117. register int ef = 0; /* desired value of flags & ECHO */ 118. register int cf = CBRKON(CBRKMASK); /* desired value of flags & CBREAK */ 119. register int change = 0; 120. flags.cbreak = ON; 121. flags.echo = OFF; 122. /* Should use (ECHO|CRMOD) here instead of ECHO */ 123. if((curttyb.echoflgs & ECHO) != ef){ 124. curttyb.echoflgs &= ~ECHO; 125. /* curttyb.echoflgs |= ef; */ 126. change++; 127. } 128. if((curttyb.cbrkflgs & CBRKMASK) != cf){ 129. curttyb.cbrkflgs &= ~CBRKMASK; 130. curttyb.cbrkflgs |= cf; 131. #ifdef USG 132. /* be satisfied with one character; no timeout */ 133. curttyb.c_cc[VMIN] = 1; /* was VEOF */ 134. curttyb.c_cc[VTIME] = 0; /* was VEOL */ 135. #endif 136. change++; 137. } 138. if(change){ 139. setctty(); 140. } 141. start_screen(); 142. } 143. 144. 145. /* fatal error */ 146. /*VARARGS1*/ 147. error(s,x,y) char *s; { 148. if(settty_needed) 149. settty((char *) 0); 150. printf(s,x,y); 151. putchar('
'); 152. exit(1); 153. } 154. 155. /* 156. * Read a line closed with '
' into the array char bufp[BUFSZ]. 157. * (The '
' is not stored. The string is closed with a '\0'.) 158. * Reading can be interrupted by an escape ('\033') - now the 159. * resulting string is "\033". 160. */ 161. getlin(bufp) 162. register char *bufp; 163. { 164. register char *obufp = bufp; 165. register int c; 166. 167. flags.toplin = 2; /* nonempty, no --More-- required */ 168. for(;;) { 169. (void) fflush(stdout); 170. if((c = getchar()) == EOF) { 171. *bufp = 0; 172. return; 173. } 174. if(c == '\033') { 175. *obufp = c; 176. obufp[1] = 0; 177. return; 178. } 179. if(c == erase_char || c == '\b') { 180. if(bufp != obufp) { 181. bufp--; 182. putstr("\b \b"); /* putsym converts \b */ 183. } else bell(); 184. } else if(c == '
') { 185. *bufp = 0; 186. return; 187. } else if(' ' <= c && c < '\177') { 188. /* avoid isprint() - some people don't have it 189. ' ' is not always a printing char */ 190. *bufp = c; 191. bufp[1] = 0; 192. putstr(bufp); 193. if(bufp-obufp < BUFSZ-1 && bufp-obufp < COLNO) 194. bufp++; 195. } else if(c == kill_char || c == '\177') { /* Robert Viduya */ 196. /* this test last - @ might be the kill_char */ 197. while(bufp != obufp) { 198. bufp--; 199. putstr("\b \b"); 200. } 201. } else 202. bell(); 203. } 204. } 205. 206. getret() { 207. cgetret(""); 208. } 209. 210. cgetret(s) 211. register char *s; 212. { 213. putsym('
'); 214. if(flags.standout) 215. standoutbeg(); 216. putstr("Hit "); 217. putstr(flags.cbreak ? "space" : "return"); 218. putstr(" to continue: "); 219. if(flags.standout) 220. standoutend(); 221. xwaitforspace(s); 222. } 223. 224. char morc; /* tell the outside world what char he used */ 225. 226. xwaitforspace(s) 227. register char *s; /* chars allowed besides space or return */ 228. { 229. register int c; 230. 231. morc = 0; 232. 233. while((c = readchar()) != '
') { 234. if(flags.cbreak) { 235. if(c == ' ') break; 236. if(s && index(s,c)) { 237. morc = c; 238. break; 239. } 240. bell(); 241. } 242. } 243. } 244. 245. static int last_multi; 246. 247. char * 248. parse() 249. { 250. static char inline[COLNO]; 251. register foo; 252. 253. multi = 0; 254. flags.move = 1; 255. if(!Invisible) curs_on_u(); else home(); 256. while((foo = readchar()) >= '0' && foo <= '9') { 257. multi = 10*multi+foo-'0'; 258. #ifdef DGKMOD 259. if (multi < 0 || multi > LARGEST_INT) 260. multi = LARGEST_INT; 261. if (multi > 9) { 262. remember_topl(); 263. home(); 264. cl_end(); 265. printf("Count: %d", multi); 266. } 267. #endif 268. last_multi = multi; 269. } 270. # ifdef REDO 271. if (foo == DOAGAIN || in_doagain) 272. multi = last_multi; 273. else { 274. savech(0); /* reset input queue */ 275. savech(foo); 276. } 277. # endif 278. if(multi) { 279. multi--; 280. save_cm = inline; 281. } 282. inline[0] = foo; 283. inline[1] = 0; 284. if(foo == 'g' || foo == 'G'){ 285. inline[1] = getchar(); 286. #ifdef QUEST 287. if(inline[1] == foo) inline[2] = getchar(); else 288. #endif 289. inline[2] = 0; 290. } 291. if(foo == 'm' || foo == 'M'){ 292. inline[1] = getchar(); 293. inline[2] = 0; 294. } 295. clrlin(); 296. return(inline); 297. } 298. 299. char 300. readchar() { 301. register int sym; 302. 303. (void) fflush(stdout); 304. if((sym = getchar()) == EOF) 305. #ifdef NR_OF_EOFS 306. { /* 307. * Some SYSV systems seem to return EOFs for various reasons 308. * (?like when one hits break or for interrupted systemcalls?), 309. * and we must see several before we quit. 310. */ 311. register int cnt = NR_OF_EOFS; 312. while (cnt--) { 313. clearerr(stdin); /* omit if clearerr is undefined */ 314. if((sym = getchar()) != EOF) goto noteof; 315. } 316. end_of_input(); 317. noteof: ; 318. } 319. #else 320. end_of_input(); 321. #endif /* NR_OF_EOFS /**/ 322. if(flags.toplin == 1) 323. flags.toplin = 2; 324. return((char) sym); 325. } 326. 327. end_of_input() 328. { 329. settty("End of input?
"); 330. clearlocks(); 331. exit(0); 332. } 333. 334. #ifdef COM_COMPL 335. /* Read in an extended command - doing command line completion for 336. * when enough character have been entered to make a unique command. 337. * This is just a modified getlin(). -jsb 338. */ 339. get_ext_cmd(bufp) 340. register char *bufp; 341. { 342. register char *obufp = bufp; 343. register int c; 344. int com_index, index; 345. 346. flags.toplin = 2; /* nonempty, no --More-- required */ 347. 348. for(;;) { 349. (void) fflush(stdout); 350. if((c = readchar()) == EOF) { 351. *bufp = 0; 352. return; 353. } 354. if(c == '\033') { 355. *obufp = c; 356. obufp[1] = 0; 357. return; 358. } 359. if(c == erase_char || c == '\b') { 360. if(bufp != obufp) { 361. bufp--; 362. putstr("\b \b"); /* putsym converts \b */ 363. } else bell(); 364. } else if(c == '
') { 365. *bufp = 0; 366. return; 367. } else if(' ' <= c && c < '\177') { 368. /* avoid isprint() - some people don't have it 369. ' ' is not always a printing char */ 370. *bufp = c; 371. bufp[1] = 0; 372. index = 0; 373. com_index = -1; 374. 375. while(extcmdlist[index].ef_txt != (char *) 0){ 376. if(!strncmp(obufp, extcmdlist[index].ef_txt, 377. strlen(obufp))) 378. if(com_index == -1) /* No matches yet*/ 379. com_index = index; 380. else /* More than 1 match */ 381. com_index = -2; 382. index++; 383. } 384. if(com_index >= 0){ 385. strcpy(obufp, 386. extcmdlist[com_index].ef_txt); 387. /* finish print our string */ 388. putstr(bufp); 389. bufp = obufp; /* reset it */ 390. if(strlen(obufp) < BUFSIZ-1 && 391. strlen(obufp) < COLNO) 392. /* set bufp at the end of our 393. * string 394. */ 395. bufp += strlen(obufp); 396. } else { 397. putstr(bufp); 398. if(bufp-obufp < BUFSZ-1 && bufp-obufp < COLNO) 399. bufp++; 400. } 401. } else if(c == kill_char || c == '\177') { /* Robert Viduya */ 402. /* this test last - @ might be the kill_char */ 403. while(bufp != obufp) { 404. bufp--; 405. putstr("\b \b"); 406. } 407. } else 408. bell(); 409. } 410. 411. } 412. #endif COM_COMPL
|