Wikihack
Advertisement

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

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

Screenshots and source code from Hack are used under the CWI license.
1.    /*	SCCS Id: @(#)termcap.c	1.3	87/07/14
2.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3.    /* termcap.c - version 1.0.3 */
4.    
5.    #include <stdio.h>
6.    #include "config.h"	/* for ROWNO and COLNO */
7.    #include "hack.h"	/* for  *HI, *HE */
8.    extern char *tgetstr(), *tgoto(), *getenv();
9.    extern long *alloc();
10.   
11.   #ifndef lint
12.   extern			/* it is defined in libtermlib (libtermcap) */
13.   #endif
14.   	short ospeed;		/* terminal baudrate; used by tputs */
15.   static char tbuf[512];
16.   static char *HO, *CL, *CE, *UP, *CM, *ND, *XD, *BC, *SO, *SE, *TI, *TE;
17.   static char *VS, *VE;
18.   static int SG;
19.   static char PC = '\0';
20.   char *CD;		/* tested in pri.c: docorner() */
21.   int CO, LI;		/* used in pri.c and whatis.c */
22.   
23.   #ifdef MSDOS
24.   static char tgotobuf[20];
25.   #define tgoto(fmt, x, y)	(sprintf(tgotobuf, fmt, y+1, x+1), tgotobuf)
26.   #endif /* MSDOS /**/
27.   
28.   startup()
29.   {
30.   #ifdef MSDOS
31.   	HO = "\033[H";
32.   	CL = "\033[2J";
33.   	CE = "\033[K";
34.   	UP = "\033[1A";
35.   	CM = "\033[%d;%dH";	/* used with function tgoto() */
36.   	ND = "\033[1C";
37.   	XD = "\033[1B";
38.   	BC = "\033[1D";
39.   	SO = "\033[7m";
40.   	SE = "\033[0m";
41.   	TI = TE = VS = VE = "";
42.   	CD = "\033";
43.   	CO = COLNO;
44.   	LI = ROWNO;
45.   #if defined(DGK) || defined(SORTING)
46.   	/* Both HI and HE have 4 characters.  The function let_to_name()
47.   	 * in msdos.c uses this length when creating a buffer.  If you
48.   	 * make HI and HE longer, you must also change the length of buf[]
49.   	 * in let_to_name()
50.   	 */
51.   	HI = "\033[4m";
52.   	HE = "\033[0m";
53.   #endif
54.   #else
55.   	register char *term;
56.   	register char *tptr;
57.   	char *tbufptr, *pc;
58.   
59.   	tptr = (char *) alloc(1024);
60.   
61.   	tbufptr = tbuf;
62.   	if(!(term = getenv("TERM")))
63.   		error("Can't get TERM.");
64.   	if(!strncmp(term, "5620", 4))
65.   		flags.nonull = 1;	/* this should be a termcap flag */
66.   	if(tgetent(tptr, term) < 1)
67.   		error("Unknown terminal type: %s.", term);
68.   	if(pc = tgetstr("pc", &tbufptr))
69.   		PC = *pc;
70.   	if(!(BC = tgetstr("bc", &tbufptr))) {	
71.   		if(!tgetflag("bs"))
72.   			error("Terminal must backspace.");
73.   		BC = tbufptr;
74.   		tbufptr += 2;
75.   		*BC = '\b';
76.   	}
77.   	HO = tgetstr("ho", &tbufptr);
78.   	CO = tgetnum("co");
79.   	LI = tgetnum("li");
80.   	if(CO < COLNO || LI < ROWNO+2)
81.   		setclipped();
82.   	if(!(CL = tgetstr("cl", &tbufptr)))
83.   		error("Hack needs CL.");
84.   	ND = tgetstr("nd", &tbufptr);
85.   	if(tgetflag("os"))
86.   		error("Hack can't have OS.");
87.   	CE = tgetstr("ce", &tbufptr);
88.   	UP = tgetstr("up", &tbufptr);
89.   	/* It seems that xd is no longer supported, and we should use
90.   	   a linefeed instead; unfortunately this requires resetting
91.   	   CRMOD, and many output routines will have to be modified
92.   	   slightly. Let's leave that till the next release. */
93.   	XD = tgetstr("xd", &tbufptr);
94.   /* not: 		XD = tgetstr("do", &tbufptr); */
95.   	if(!(CM = tgetstr("cm", &tbufptr))) {
96.   		if(!UP && !HO)
97.   			error("Hack needs CM or UP or HO.");
98.   		printf("Playing hack on terminals without cm is suspect...\n");
99.   		getret();
100.  	}
101.  	SO = tgetstr("so", &tbufptr);
102.  	SE = tgetstr("se", &tbufptr);
103.  	SG = tgetnum("sg");	/* -1: not fnd; else # of spaces left by so */
104.  	if(!SO || !SE || (SG > 0)) SO = SE = 0;
105.  #ifdef SORTING
106.  	HI = SO;	/* I know... Its a kluge. (MRS) */
107.  	HE = SE;
108.  #endif
109.  	CD = tgetstr("cd", &tbufptr);
110.  	set_whole_screen();		/* uses LI and CD */
111.  	if(tbufptr-tbuf > sizeof(tbuf)) error("TERMCAP entry too big...\n");
112.  	free(tptr);
113.  #endif /* MSDOS /**/
114.  }
115.  
116.  start_screen()
117.  {
118.  	xputs(TI);
119.  	xputs(VS);
120.  #ifdef DGK
121.  	/* Select normal ASCII and line drawing character sets.
122.  	 */
123.  	if (flags.DECRainbow)
124.  		xputs("\033(B\033)0");
125.  #endif
126.  }
127.  
128.  end_screen()
129.  {
130.  	clear_screen();
131.  	xputs(VE);
132.  	xputs(TE);
133.  }
134.  
135.  /* Cursor movements */
136.  extern xchar curx, cury;
137.  
138.  curs(x, y)
139.  register int x, y;	/* not xchar: perhaps xchar is unsigned and
140.  			   curx-x would be unsigned as well */
141.  {
142.  
143.  	if (y == cury && x == curx)
144.  		return;
145.  	if(!ND && (curx != x || x <= 3)) {	/* Extremely primitive */
146.  		cmov(x, y);			/* bunker!wtm */
147.  		return;
148.  	}
149.  	if(abs(cury-y) <= 3 && abs(curx-x) <= 3)
150.  		nocmov(x, y);
151.  	else if((x <= 3 && abs(cury-y)<= 3) || (!CM && x<abs(curx-x))) {
152.  		(void) putchar('\r');
153.  		curx = 1;
154.  		nocmov(x, y);
155.  	} else if(!CM) {
156.  		nocmov(x, y);
157.  	} else
158.  		cmov(x, y);
159.  }
160.  
161.  nocmov(x, y)
162.  {
163.  	if (cury > y) {
164.  		if(UP) {
165.  			while (cury > y) {	/* Go up. */
166.  				xputs(UP);
167.  				cury--;
168.  			}
169.  		} else if(CM) {
170.  			cmov(x, y);
171.  		} else if(HO) {
172.  			home();
173.  			curs(x, y);
174.  		} /* else impossible("..."); */
175.  	} else if (cury < y) {
176.  		if(XD) {
177.  			while(cury < y) {
178.  				xputs(XD);
179.  				cury++;
180.  			}
181.  		} else if(CM) {
182.  			cmov(x, y);
183.  		} else {
184.  			while(cury < y) {
185.  				xputc('\n');
186.  				curx = 1;
187.  				cury++;
188.  			}
189.  		}
190.  	}
191.  	if (curx < x) {		/* Go to the right. */
192.  		if(!ND) cmov(x, y); else	/* bah */
193.  			/* should instead print what is there already */
194.  		while (curx < x) {
195.  			xputs(ND);
196.  			curx++;
197.  		}
198.  	} else if (curx > x) {
199.  		while (curx > x) {	/* Go to the left. */
200.  			xputs(BC);
201.  			curx--;
202.  		}
203.  	}
204.  }
205.  
206.  cmov(x, y)
207.  register x, y;
208.  {
209.  	xputs(tgoto(CM, x-1, y-1));
210.  	cury = y;
211.  	curx = x;
212.  }
213.  
214.  xputc(c) char c; {
215.  	(void) fputc(c, stdout);
216.  }
217.  
218.  xputs(s) char *s; {
219.  #ifdef MSDOS
220.  	fputs(s, stdout);
221.  #else
222.  	tputs(s, 1, xputc);
223.  #endif
224.  }
225.  
226.  cl_end() {
227.  	if(CE)
228.  		xputs(CE);
229.  	else {	/* no-CE fix - free after Harold Rynes */
230.  		/* this looks terrible, especially on a slow terminal
231.  		   but is better than nothing */
232.  		register cx = curx, cy = cury;
233.  
234.  		while(curx < COLNO) {
235.  			xputc(' ');
236.  			curx++;
237.  		}
238.  		curs(cx, cy);
239.  	}
240.  }
241.  
242.  clear_screen() {
243.  	xputs(CL);
244.  	xputs(HO);
245.  	curx = cury = 1;
246.  }
247.  
248.  home()
249.  {
250.  	if(HO)
251.  		xputs(HO);
252.  	else if(CM)
253.  		xputs(tgoto(CM, 0, 0));
254.  	else
255.  		curs(1, 1);	/* using UP ... */
256.  	curx = cury = 1;
257.  }
258.  
259.  standoutbeg()
260.  {
261.  	if(SO) xputs(SO);
262.  }
263.  
264.  standoutend()
265.  {
266.  	if(SE) xputs(SE);
267.  }
268.  
269.  backsp()
270.  {
271.  	xputs(BC);
272.  	curx--;
273.  }
274.  
275.  bell()
276.  {
277.  #ifdef DGKMOD
278.  	if (flags.silent) return;
279.  #endif /* DGKMOD /**/
280.  	(void) putchar('\007');		/* curx does not change */
281.  	(void) fflush(stdout);
282.  }
283.  
284.  static short tmspc10[] = {		/* from termcap */
285.  	0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5
286.  };
287.  
288.  delay_output() {
289.  	/* delay 50 ms - could also use a 'nap'-system call */
290.  	/* BUG: if the padding character is visible, as it is on the 5620
291.  	   then this looks terrible. */
292.  #ifdef MSDOS
293.  	/* simulate the delay with "cursor here" */
294.  	register i;
295.  	for (i = 0; i < 3; i++) {
296.  		cmov(curx, cury);
297.  		(void) fflush(stdout);
298.  	}
299.  #else
300.  	if(!flags.nonull)
301.  		tputs("50", 1, xputc);
302.  
303.  		/* cbosgd!cbcephus!pds for SYS V R2 */
304.  		/* is this terminfo, or what? */
305.  		/* tputs("$<50>", 1, xputc); */
306.  
307.  	else if(ospeed > 0 || ospeed < SIZE(tmspc10)) if(CM) {
308.  		/* delay by sending cm(here) an appropriate number of times */
309.  		register int cmlen = strlen(tgoto(CM, curx-1, cury-1));
310.  		register int i = 500 + tmspc10[ospeed]/2;
311.  
312.  		while(i > 0) {
313.  			cmov(curx, cury);
314.  			i -= cmlen*tmspc10[ospeed];
315.  		}
316.  	}
317.  #endif /* MSDOS /**/
318.  }
319.  
320.  cl_eos()			/* free after Robert Viduya */
321.  {				/* must only be called with curx = 1 */
322.  
323.  	if(CD)
324.  		xputs(CD);
325.  	else {
326.  		register int cx = curx, cy = cury;
327.  		while(cury <= LI-2) {
328.  			cl_end();
329.  			xputc('\n');
330.  			curx = 1;
331.  			cury++;
332.  		}
333.  		cl_end();
334.  		curs(cx, cy);
335.  	}
336.  }
Advertisement