Source:NetHack 3.0.0/termcap.c

Below is the full text to termcap.c from the source code of NetHack 3.0.0. To link to a particular line, write [[NetHack 3.0.0/termcap.c#line123 ]], for example.

Warning! This is the source code from an old release. For the latest release, see Source code

1.   /*	SCCS Id: @(#)termcap.c	3.0	88/11/20 2.   /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3.    /* NetHack may be freely redistributed. See license for details. */ 4.     5.    #include 	/* for isdigit */ 6.    7.    /* block some unused #defines to avoid overloading some cpp's */ 8.   #define MONATTK_H 9.   #include "hack.h"	/* for ROWNO, COLNO, *HI, *HE, *AS, *AE */ 10.   11.   #if !defined(SYSV) || defined(TOS) || defined(UNIXPC) 12.  # ifndef LINT 13.  extern			/* it is defined in libtermlib (libtermcap) */ 14.  # endif 15.  	short ospeed;	/* terminal baudrate; used by tputs */ 16.  #else 17.  short	ospeed = 0;	/* gets around "not defined" error message */ 18.  #endif 19.   20.   static void nocmov; 21.  #ifdef MSDOSCOLOR 22.  static void init_hilite; 23.  #endif /* MSDOSCOLOR */ 24.   25.   static char tbuf[512]; 26.  static char *HO, *CL, *CE, *UP, *CM, *ND, *XD, *BC, *SO, *SE, *TI, *TE; 27.  static char *VS, *VE, *US, *UE; 28.  static char *MR, *ME; 29.  #if 0 30.  static char *MB, *MD, *MH; 31.  #endif 32.  static int SG; 33.  static char PC = '\0'; 34.   35.   #if defined(MSDOS) && !defined(TERMLIB) 36.  static char tgotobuf[20]; 37.  #ifdef TOS 38.  #define tgoto(fmt, x, y)	(Sprintf(tgotobuf, fmt, y+' ', x+' '), tgotobuf) 39.  #else 40.  #define tgoto(fmt, x, y)	(Sprintf(tgotobuf, fmt, y+1, x+1), tgotobuf) 41.  #endif 42.  #endif /* MSDOS /**/ 43.   44.   void 45.  startup 46.  {  47.   #ifdef TOS 48.  	HO = "\033H"; 49.  	CL = "\033E";		/* the VT52 termcap */ 50.  	CE = "\033K"; 51.  	UP = "\033A"; 52.  	CM = "\033Y%c%c";	/* used with function tgoto */ 53.  	ND = "\033C"; 54.  	XD = "\033B"; 55.  	BC = "\033D"; 56.  	SO = "\033p"; 57.  	SE = "\033q"; 58.  	HI = "\033p"; 59.  	HE = "\033q"; 60.  #else 61.  	register char *term; 62.  	register char *tptr; 63.  	char *tbufptr, *pc; 64.  	register int i;  65. 66.  	tptr = (char *) alloc(1024); 67.   68.   	tbufptr = tbuf; 69.  	if(!(term = getenv("TERM"))) 70.  # ifdef ANSI_DEFAULT 71.  	{  72.   		HO = "\033[H"; 73.  		CL = "\033[2J";		/* the ANSI termcap */ 74.  /*		CD = "\033[J"; */ 75.  		CE = "\033[K"; 76.  		CM = "\033[%i%d;%dH"; 77.  		UP = "\033[A"; 78.  		ND = "\033[C"; 79.  		XD = "\033[B"; 80.  		BC = "\033[D"; 81.  		HI = SO = "\033[1m"; 82.  		US = "\033[4m"; 83.  		TI = HE = SE = UE = "\033[0m"; 84.  		/* strictly, SE should be 2, and UE should be 24, 85.  		   but we can't trust all ANSI emulators to be  86. that complete. -3. */ 87.   		AS = "\016"; 88.  		AE = "\017"; 89.  		VS = VE = ""; 90.  	} else { 91.  # else 92.  		error("Can't get TERM."); 93.  # endif 94.  	if(!strncmp(term, "5620", 4)) 95.  		flags.nonull = 1;	/* this should be a termcap flag */ 96.  	if(tgetent(tptr, term) < 1) 97.  		error("Unknown terminal type: %s.", term); 98.  	if(pc = tgetstr("pc", &tbufptr)) 99.  		PC = *pc; 100. #ifdef TERMINFO 101. 	if(!(BC = tgetstr("le", &tbufptr))) { 102. #else 103. 	if(!(BC = tgetstr("bc", &tbufptr))) { 104. #endif 105. #if !defined(MINIMAL_TERM) && !defined(HISX) 106. 		if(!tgetflag("bs")) 107. 			error("Terminal must backspace."); 108. #endif 109. 		BC = tbufptr; 110. 		tbufptr += 2; 111. 		*BC = '\b'; 112. 	}  113.  #ifdef MINIMAL_TERM 114. 	HO = NULL; 115. #else 116. 	HO = tgetstr("ho", &tbufptr); 117. #endif 118. 	CO = tgetnum("co"); 119. 	LI = tgetnum("li"); 120. 	if(CO < COLNO || LI < ROWNO+2) 121. 		setclipped; 122. 	if(!(CL = tgetstr("cl", &tbufptr))) 123. 		error("Hack needs CL."); 124. 	ND = tgetstr("nd", &tbufptr); 125. 	if(tgetflag("os")) 126. 		error("Hack can't have OS."); 127. 	CE = tgetstr("ce", &tbufptr); 128. 	UP = tgetstr("up", &tbufptr); 129. 	/* It seems that xd is no longer supported, and we should use 130. 	   a linefeed instead; unfortunately this requires resetting 131. 	   CRMOD, and many output routines will have to be modified 132. 	   slightly. Let's leave that till the next release. */ 133.  	XD = tgetstr("xd", &tbufptr); 134. /* not: 		XD = tgetstr("do", &tbufptr); */ 135. 	if(!(CM = tgetstr("cm", &tbufptr))) { 136. 		if(!UP && !HO) 137. 			error("Hack needs CM or UP or HO."); 138. 		Printf("Playing hack on terminals without cm is suspect...\n"); 139. 		getret; 140. 	}  141.  	SO = tgetstr("so", &tbufptr); 142. 	SE = tgetstr("se", &tbufptr); 143. 	US = tgetstr("us", &tbufptr); 144. 	UE = tgetstr("ue", &tbufptr); 145. 	SG = tgetnum("sg");	/* -1: not fnd; else # of spaces left by so */ 146. 	if(!SO || !SE || (SG > 0)) SO = SE = US = UE = ""; 147. 	TI = tgetstr("ti", &tbufptr); 148. 	TE = tgetstr("te", &tbufptr); 149. 	VS = VE = ""; 150. #if 0 151. 	MB = tgetstr("mb", &tbufptr);	/* blink */ 152. 	MD = tgetstr("md", &tbufptr);	/* boldface */ 153. 	MH = tgetstr("mh", &tbufptr);	/* dim */ 154. #endif 155. 	MR = tgetstr("mr", &tbufptr);	/* reverse */ 156. 	ME = tgetstr("me", &tbufptr); 157.  158.  	/* Get rid of padding numbers for HI and HE. Hope they 159. 	 * aren't really needed!!! HI and HE are ouputted to the 160. 	 * pager as a string - so how can you send it NULLS??? 161. 	 *  -jsb 162. 	 */  163.  	    HI = (char *) alloc((unsigned)(strlen(SO)+1)); 164. 	    HE = (char *) alloc((unsigned)(strlen(SE)+1)); 165. 	    i = 0; 166. 	    while(isdigit(SO[i])) i++; 167. 	    Strcpy(HI, &SO[i]); 168. 	    i = 0; 169. 	    while(isdigit(SE[i])) i++; 170. 	    Strcpy(HE, &SE[i]); 171. 	AS = tgetstr("as", &tbufptr); 172. 	AE = tgetstr("ae", &tbufptr); 173. 	CD = tgetstr("cd", &tbufptr); 174. # ifdef ANSI_DEFAULT 175. 	}  176.  # endif 177. 	set_whole_screen;		/* uses LI and CD */ 178. 	if(tbufptr-tbuf > sizeof(tbuf)) error("TERMCAP entry too big...\n"); 179. 	free((genericptr_t)tptr); 180. #ifdef MSDOSCOLOR 181. 	init_hilite; 182. #endif 183. #endif /* TOS /* */ 184. }  185.   186.  void 187. start_screen 188. {  189.  	xputs(TI); 190. 	xputs(VS); 191. #ifdef DECRAINBOW 192. 	/* Select normal ASCII and line drawing character sets. 193. 	 */  194.  	if (flags.DECRainbow) { 195. 		xputs("\033(B\033)0"); 196. 		if (!AS) { 197. 			AS = "\016"; 198. 			AE = "\017"; 199. 		}  200.  	}  201.  #endif /* DECRAINBOW */ 202. }  203.   204.  void 205. end_screen 206. {  207.  	clear_screen; 208. 	xputs(VE); 209. 	xputs(TE); 210. }  211.   212.  /* Cursor movements */ 213.  214.  void 215. curs(x, y)  216. register int x, y;	/* not xchar: perhaps xchar is unsigned and 217. 			   curx-x would be unsigned as well */ 218. {  219.   220.  	if (y == cury && x == curx) 221. 		return; 222. 	if(!ND && (curx != x || x <= 3)) {	/* Extremely primitive */ 223. 		cmov(x, y);			/* bunker!wtm */ 224. 		return; 225. 	}  226.  	if(abs(cury-y) <= 3 && abs(curx-x) <= 3) 227. 		nocmov(x, y); 228. 	else if((x <= 3 && abs(cury-y)<= 3) || (!CM && x y) { 242. 		if(UP) { 243. 			while (cury > y) {	/* Go up. */ 244.  				xputs(UP); 245. 				cury--; 246. 			}  247.  		} else if(CM) { 248. 			cmov(x, y); 249. 		} else if(HO) { 250. 			home; 251. 			curs(x, y); 252. 		} /* else impossible("..."); */ 253. 	} else if (cury < y) { 254. 		if(XD) { 255. 			while(cury < y) { 256. 				xputs(XD); 257. 				cury++; 258. 			}  259.  		} else if(CM) { 260. 			cmov(x, y); 261. 		} else { 262. 			while(cury < y) { 263. 				xputc('\n'); 264. 				curx = 1; 265. 				cury++; 266. 			}  267.  		}  268.  	}  269.  	if (curx < x) {		/* Go to the right. */ 270.  		if(!ND) cmov(x, y); else	/* bah */ 271. 			/* should instead print what is there already */ 272. 		while (curx < x) { 273. 			xputs(ND); 274. 			curx++; 275. 		}  276.  	} else if (curx > x) { 277. 		while (curx > x) {	/* Go to the left. */ 278.  			xputs(BC); 279. 			curx--; 280. 		}  281.  	}  282.  }  283.   284.  void 285. cmov(x, y)  286. register int x, y; 287. { 288.  	xputs(tgoto(CM, x-1, y-1)); 289. 	cury = y;  290. curx = x; 291. } 292.   293.  void 294. xputc(c) 295. char c;  296. { 297.  	(void) fputc(c, stdout); 298. }  299.   300.  void 301. xputs(s) 302. char *s; 303. {  304.  #if defined(MSDOS) && !defined(TERMLIB) 305. 	(void) fputs(s, stdout); 306. #else 307. # ifdef __STDC__ 308. 	tputs(s, 1, (int (*))xputc); 309. # else 310. 	tputs(s, 1, xputc); 311. # endif 312. #endif 313. }  314.   315.  void 316. cl_end { 317. 	if(CE) 318. 		xputs(CE); 319. 	else {	/* no-CE fix - free after Harold Rynes */ 320. 		/* this looks terrible, especially on a slow terminal 321. 		   but is better than nothing */ 322. 		register int cx = curx, cy = cury; 323.  324.  		while(curx < COLNO) { 325. 			xputc(' '); 326. 			curx++; 327. 		}  328.  		curs(cx, cy); 329. 	}  330.  }  331.   332.  void 333. clear_screen { 334. 	xputs(CL); 335. 	home; 336. }  337.   338.  void 339. home 340. {  341.  	if(HO) 342. 		xputs(HO); 343. 	else if(CM) 344. 		xputs(tgoto(CM, 0, 0)); 345. 	else 346. 		curs(1, 1);	/* using UP ... */ 347.  	curx = cury = 1; 348. }  349.   350.  void 351. standoutbeg 352. {  353.  	if(SO) xputs(SO); 354. }  355.   356.  void 357. standoutend 358. {  359.  	if(SE) xputs(SE); 360. }  361.   362.  void 363. revbeg 364. {  365.  	if(MR) xputs(MR); 366. }  367.   368.  #if 0	/* if you need one of these, uncomment it (here and in extern.h) */ 369. void 370. boldbeg 371. {  372.  	if(MD) xputs(MD); 373. }  374.   375.  void 376. blinkbeg 377. {  378.  	if(MB) xputs(MB); 379. }  380.   381.  void 382. dimbeg 383. /* not in most termcap entries */ 384. {  385.  	if(MH) xputs(MH); 386. }  387.  #endif 388.  389.  void 390. m_end 391. {  392.  	if(ME) xputs(ME); 393. }  394.   395.  void 396. backsp 397. {  398.  	xputs(BC); 399. }  400.   401.  void 402. bell 403. {  404.  	if (flags.silent) return; 405. 	(void) putchar('\007');		/* curx does not change */ 406. 	(void) fflush(stdout); 407. }  408.   409.  void 410. graph_on { 411. 	if (AS) xputs(AS); 412. }  413.   414.  void 415. graph_off { 416. 	if (AE) xputs(AE); 417. }  418.   419.  #ifndef MSDOS 420. static const short tmspc10[] = {		/* from termcap */ 421. 	0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5  422.  };  423.  #endif 424.  425.  void 426. delay_output { 427. 	/* delay 50 ms - could also use a 'nap'-system call */ 428. 	/* BUG: if the padding character is visible, as it is on the 5620 429. 	   then this looks terrible. */ 430.  #ifdef MSDOS 431. 	/* simulate the delay with "cursor here" */ 432. 	register int i;  433. for (i = 0; i < 3; i++) { 434. 		cmov(curx, cury); 435. 		(void) fflush(stdout); 436. 	}  437.  #else /* MSDOS /**/ 438. 	if(!flags.nonull) 439. #ifdef TERMINFO 440. 		/* cbosgd!cbcephus!pds for SYS V R2 */ 441. # ifdef __STDC__ 442. 		tputs("$<50>", 1, (int (*))xputc); 443. # else 444. 		tputs("$<50>", 1, xputc); 445. # endif 446. #else 447. 		tputs("50", 1, xputs); 448. #endif 449.  450.  	else if(ospeed > 0 || ospeed < SIZE(tmspc10)) if(CM) { 451. 		/* delay by sending cm(here) an appropriate number of times */ 452. 		register int cmlen = strlen(tgoto(CM, curx-1, cury-1)); 453. 		register int i = 500 + tmspc10[ospeed]/2; 454.  455.  		while(i > 0) { 456. 			cmov(curx, cury); 457. 			i -= cmlen*tmspc10[ospeed]; 458. 		}  459.  	}  460.  #endif /* MSDOS /**/ 461. }  462.   463.  void 464. cl_eos			/* free after Robert Viduya */ 465. {				/* must only be called with curx = 1 */ 466.  467.  	if(CD) 468. 		xputs(CD); 469. 	else { 470. 		register int cx = curx, cy = cury; 471. 		while(cury <= LI-2) { 472. 			cl_end; 473. 			xputc('\n'); 474. 			curx = 1; 475. 			cury++; 476. 		}  477.  		cl_end; 478. 		curs(cx, cy); 479. 	}  480.  }  481.   482.  #ifdef MSDOSCOLOR 483. /* Sets up highlighting, using ANSI escape sequences, for monsters, 484.  * objects, and gold (highlight code found in pri.c). 485.  * The termcap entry for HI (from SO) is scanned to find the background 486.  * color. If everything is OK, monsters are displayed in the color 487.  * used to define HILITE_MONSTER, objects are displayed in the color 488.  * used to define HILITE_OBJECT, and gold is displayed in the color 489.  * used to define HILITE_GOLD. -3. */ 490.   491.  #define ESC		0x1b 492. #define NONE		0 493. #define HIGH_INTENSITY	1 494. #define BLACK		0 495. #define RED		1 496. #define GREEN		2 497. #define YELLOW		3 498. #define BLUE		4 499. #define MAGENTA		5 500. #define CYAN		6 501. #define WHITE		7 502.  503.  #define HILITE_ATTRIB	HIGH_INTENSITY 504.  505.  static void 506. init_hilite 507. {  508.  	int backg = BLACK, foreg = WHITE, len; 509. 	register int c, color; 510.  511.  	HI_RED = HI_YELLOW = HI_GREEN = HI_BLUE = HI_WHITE = HI; 512.  513.  	/* find the background color, HI[len] == 'm' */ 514. 	len = strlen(HI) - 1; 515.  516.  	if (HI[len] != 'm' || len < 3) return; 517.  518.  	c = 2; 519. 	while (c < len) { 520. 	    if ((color = atoi(&HI[c])) == 0) { 521. 		/* this also catches errors */ 522. 		foreg = WHITE; backg = BLACK; 523. 	    } else if (color >= 30 && color <= 37) { 524. 		foreg = color - 30; 525. 	    } else if (color >= 40 && color <= 47) { 526. 		backg = color - 40; 527. 	    }  528.  	    while (isdigit(HI[++c])); 529. 	    c++; 530. 	}  531.   532.  	/* avoid invisibility */ 533. 	if (foreg != RED && backg != RED) { 534. 	    HI_RED = (char *) alloc(sizeof("E[0;33;44;54m")); 535. 	    Sprintf(HI_RED, "%c[%d;3%d;4%dm", ESC, HILITE_ATTRIB,  536.  		    RED, backg); 537. 	}  538.   539.  	if (foreg != YELLOW && backg != YELLOW) { 540. 	    HI_YELLOW = (char *) alloc(sizeof("E[0;33;44;54m")); 541. 	    Sprintf(HI_YELLOW, "%c[%d;3%d;4%dm", ESC, HILITE_ATTRIB,  542.  		    YELLOW, backg); 543. 	}  544.   545.  	if (foreg != GREEN && backg != GREEN) { 546. 	    HI_GREEN = (char *) alloc(sizeof("E[0;33;44;54m")); 547. 	    Sprintf(HI_GREEN, "%c[%d;3%d;4%dm", ESC, HILITE_ATTRIB,  548.  		    GREEN, backg); 549. 	}  550.   551.  	if (foreg != BLUE && backg != BLUE) { 552. 	    HI_BLUE = (char *) alloc(sizeof("E[0;33;44;54m")); 553. 	    Sprintf(HI_BLUE, "%c[%d;3%d;4%dm", ESC, HILITE_ATTRIB,  554.  		    BLUE, backg); 555. 	}  556.   557.  	if (foreg != WHITE && backg != WHITE) { 558. 	    HI_WHITE = (char *) alloc(sizeof("E[0;33;44;54m")); 559. 	    Sprintf(HI_WHITE, "%c[%d;3%d;4%dm", ESC, HILITE_ATTRIB,  560.  		    WHITE, backg); 561. 	}  562.  }  563.   564.  #endif