Source:NetHack 2.3e/termcap.c

From NetHackWiki
Jump to navigation Jump to search

Below is the full text to termcap.c from the source code of NetHack 2.3e. To link to a particular line, write [[NetHack 2.3e/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	2.3	87/12/12
2.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3.    
4.    #include <stdio.h>
5.    #include <ctype.h>	/* for isdigit() */
6.    #include "hack.h"	/* for ROWNO, COLNO, *HI, *HE */
7.    #ifdef GENIX
8.    #define	void	int	/* jhn - mod to prevent compiler from bombing */
9.    #endif
10.   
11.   extern char *tgetstr(), *tgoto(), *getenv();
12.   extern long *alloc();
13.   
14.   #ifndef SYSV
15.   # ifndef LINT
16.   extern			/* it is defined in libtermlib (libtermcap) */
17.   # endif
18.   	short ospeed;	/* terminal baudrate; used by tputs */
19.   #else
20.   short	ospeed = 0;	/* gets around "not defined" error message */
21.   #endif
22.   
23.   static char tbuf[512];
24.   static char *HO, *CL, *CE, *UP, *CM, *ND, *XD, *BC, *SO, *SE, *TI, *TE;
25.   static char *VS, *VE, *US, *UE;
26.   static int SG;
27.   static char PC = '\0';
28.   char *CD;		/* tested in pri.c: docorner() */
29.   int CO, LI;		/* used in pri.c and whatis.c */
30.   
31.   #if defined(MSDOS) && !defined(TERMLIB)
32.   static char tgotobuf[20];
33.   #define tgoto(fmt, x, y)	(sprintf(tgotobuf, fmt, y+1, x+1), tgotobuf)
34.   #endif /* MSDOS /**/
35.   
36.   startup()
37.   {
38.   	register char *term;
39.   	register char *tptr;
40.   	char *tbufptr, *pc;
41.   	register int i;
42.   
43.   	tptr = (char *) alloc(1024);
44.   
45.   	tbufptr = tbuf;
46.   	if(!(term = getenv("TERM")))
47.   		error("Can't get TERM.");
48.   	if(!strncmp(term, "5620", 4))
49.   		flags.nonull = 1;	/* this should be a termcap flag */
50.   	if(tgetent(tptr, term) < 1)
51.   		error("Unknown terminal type: %s.", term);
52.   	if(pc = tgetstr("pc", &tbufptr))
53.   		PC = *pc;
54.   	if(!(BC = tgetstr("bc", &tbufptr))) {	
55.   		if(!tgetflag("bs"))
56.   			error("Terminal must backspace.");
57.   		BC = tbufptr;
58.   		tbufptr += 2;
59.   		*BC = '\b';
60.   	}
61.   	HO = tgetstr("ho", &tbufptr);
62.   	CO = tgetnum("co");
63.   	LI = tgetnum("li");
64.   	if(CO < COLNO || LI < ROWNO+2)
65.   		setclipped();
66.   	if(!(CL = tgetstr("cl", &tbufptr)))
67.   		error("Hack needs CL.");
68.   	ND = tgetstr("nd", &tbufptr);
69.   	if(tgetflag("os"))
70.   		error("Hack can't have OS.");
71.   	CE = tgetstr("ce", &tbufptr);
72.   	UP = tgetstr("up", &tbufptr);
73.   	/* It seems that xd is no longer supported, and we should use
74.   	   a linefeed instead; unfortunately this requires resetting
75.   	   CRMOD, and many output routines will have to be modified
76.   	   slightly. Let's leave that till the next release. */
77.   	XD = tgetstr("xd", &tbufptr);
78.   /* not: 		XD = tgetstr("do", &tbufptr); */
79.   	if(!(CM = tgetstr("cm", &tbufptr))) {
80.   		if(!UP && !HO)
81.   			error("Hack needs CM or UP or HO.");
82.   		printf("Playing hack on terminals without cm is suspect...\n");
83.   		getret();
84.   	}
85.   	SO = tgetstr("so", &tbufptr);
86.   	SE = tgetstr("se", &tbufptr);
87.   	US = tgetstr("us", &tbufptr);
88.   	UE = tgetstr("ue", &tbufptr);
89.   	SG = tgetnum("sg");	/* -1: not fnd; else # of spaces left by so */
90.   	if(!SO || !SE || (SG > 0)) SO = SE = US = UE = "";
91.   	TI = tgetstr("ti", &tbufptr);
92.   	TE = tgetstr("te", &tbufptr);
93.   	VS = VE = "";
94.   #if defined(SORTING) || defined(MSDOSCOLOR)
95.   	/* Get rid of padding numbers for HI and HE.  Hope they
96.   	 * aren't really needed!!!  HI and HE are ouputted to the
97.   	 * pager as a string - so how can you send it NULLS???
98.   	 *  -jsb
99.   	 */
100.  	    HI = (char *) alloc((unsigned)(strlen(SO)+1));
101.  	    HE = (char *) alloc((unsigned)(strlen(SE)+1));
102.  	    i = 0;
103.  	    while(isdigit(SO[i])) i++;
104.  	    strcpy(HI, &SO[i]);
105.  	    i = 0;
106.  	    while(isdigit(SE[i])) i++;
107.  	    strcpy(HE, &SE[i]);
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.  #ifdef MSDOSCOLOR
114.  	init_hilite();
115.  #endif
116.  }
117.  
118.  start_screen()
119.  {
120.  	xputs(TI);
121.  	xputs(VS);
122.  #ifdef DGK
123.  	/* Select normal ASCII and line drawing character sets.
124.  	 */
125.  	if (flags.DECRainbow)
126.  		xputs("\033(B\033)0");
127.  #endif
128.  }
129.  
130.  end_screen()
131.  {
132.  	clear_screen();
133.  	xputs(VE);
134.  	xputs(TE);
135.  }
136.  
137.  /* Cursor movements */
138.  extern xchar curx, cury;
139.  
140.  curs(x, y)
141.  register int x, y;	/* not xchar: perhaps xchar is unsigned and
142.  			   curx-x would be unsigned as well */
143.  {
144.  
145.  	if (y == cury && x == curx)
146.  		return;
147.  	if(!ND && (curx != x || x <= 3)) {	/* Extremely primitive */
148.  		cmov(x, y);			/* bunker!wtm */
149.  		return;
150.  	}
151.  	if(abs(cury-y) <= 3 && abs(curx-x) <= 3)
152.  		nocmov(x, y);
153.  	else if((x <= 3 && abs(cury-y)<= 3) || (!CM && x<abs(curx-x))) {
154.  		(void) putchar('\r');
155.  		curx = 1;
156.  		nocmov(x, y);
157.  	} else if(!CM) {
158.  		nocmov(x, y);
159.  	} else
160.  		cmov(x, y);
161.  }
162.  
163.  nocmov(x, y)
164.  {
165.  	if (cury > y) {
166.  		if(UP) {
167.  			while (cury > y) {	/* Go up. */
168.  				xputs(UP);
169.  				cury--;
170.  			}
171.  		} else if(CM) {
172.  			cmov(x, y);
173.  		} else if(HO) {
174.  			home();
175.  			curs(x, y);
176.  		} /* else impossible("..."); */
177.  	} else if (cury < y) {
178.  		if(XD) {
179.  			while(cury < y) {
180.  				xputs(XD);
181.  				cury++;
182.  			}
183.  		} else if(CM) {
184.  			cmov(x, y);
185.  		} else {
186.  			while(cury < y) {
187.  				xputc('\n');
188.  				curx = 1;
189.  				cury++;
190.  			}
191.  		}
192.  	}
193.  	if (curx < x) {		/* Go to the right. */
194.  		if(!ND) cmov(x, y); else	/* bah */
195.  			/* should instead print what is there already */
196.  		while (curx < x) {
197.  			xputs(ND);
198.  			curx++;
199.  		}
200.  	} else if (curx > x) {
201.  		while (curx > x) {	/* Go to the left. */
202.  			xputs(BC);
203.  			curx--;
204.  		}
205.  	}
206.  }
207.  
208.  cmov(x, y)
209.  register x, y;
210.  {
211.  	xputs(tgoto(CM, x-1, y-1));
212.  	cury = y;
213.  	curx = x;
214.  }
215.  
216.  xputc(c) char c; {
217.  	(void) fputc(c, stdout);
218.  }
219.  
220.  xputs(s) char *s; {
221.  #if defined(MSDOS) && !defined(TERMLIB)
222.  	fputs(s, stdout);
223.  #else
224.  	tputs(s, 1, xputc);
225.  #endif
226.  }
227.  
228.  cl_end() {
229.  	if(CE)
230.  		xputs(CE);
231.  	else {	/* no-CE fix - free after Harold Rynes */
232.  		/* this looks terrible, especially on a slow terminal
233.  		   but is better than nothing */
234.  		register cx = curx, cy = cury;
235.  
236.  		while(curx < COLNO) {
237.  			xputc(' ');
238.  			curx++;
239.  		}
240.  		curs(cx, cy);
241.  	}
242.  }
243.  
244.  clear_screen() {
245.  	xputs(CL);
246.  	home();
247.  }
248.  
249.  home()
250.  {
251.  	if(HO)
252.  		xputs(HO);
253.  	else if(CM)
254.  		xputs(tgoto(CM, 0, 0));
255.  	else
256.  		curs(1, 1);	/* using UP ... */
257.  	curx = cury = 1;
258.  }
259.  
260.  standoutbeg()
261.  {
262.  	if(SO) xputs(SO);
263.  }
264.  
265.  standoutend()
266.  {
267.  	if(SE) xputs(SE);
268.  }
269.  
270.  backsp()
271.  {
272.  	xputs(BC);
273.  	curx--;
274.  }
275.  
276.  bell()
277.  {
278.  #ifdef DGKMOD
279.  	if (flags.silent) return;
280.  #endif /* DGKMOD /**/
281.  	(void) putchar('\007');		/* curx does not change */
282.  	(void) fflush(stdout);
283.  }
284.  
285.  static short tmspc10[] = {		/* from termcap */
286.  	0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5
287.  };
288.  
289.  delay_output() {
290.  	/* delay 50 ms - could also use a 'nap'-system call */
291.  	/* BUG: if the padding character is visible, as it is on the 5620
292.  	   then this looks terrible. */
293.  #ifdef MSDOS
294.  	/* simulate the delay with "cursor here" */
295.  	register i;
296.  	for (i = 0; i < 3; i++) {
297.  		cmov(curx, cury);
298.  		(void) fflush(stdout);
299.  	}
300.  #else /* MSDOS /**/
301.  	if(!flags.nonull)
302.  #ifdef TERMINFO
303.  		tputs("$<50>", 1, xputs);
304.  #else
305.  		tputs("50", 1, xputs);
306.  #endif
307.  		/* cbosgd!cbcephus!pds for SYS V R2 */
308.  		/* is this terminfo, or what? */
309.  		/* tputs("$<50>", 1, xputc); */
310.  
311.  	else if(ospeed > 0 || ospeed < SIZE(tmspc10)) if(CM) {
312.  		/* delay by sending cm(here) an appropriate number of times */
313.  		register int cmlen = strlen(tgoto(CM, curx-1, cury-1));
314.  		register int i = 500 + tmspc10[ospeed]/2;
315.  
316.  		while(i > 0) {
317.  			cmov(curx, cury);
318.  			i -= cmlen*tmspc10[ospeed];
319.  		}
320.  	}
321.  #endif /* MSDOS /**/
322.  }
323.  
324.  cl_eos()			/* free after Robert Viduya */
325.  {				/* must only be called with curx = 1 */
326.  
327.  	if(CD)
328.  		xputs(CD);
329.  	else {
330.  		register int cx = curx, cy = cury;
331.  		while(cury <= LI-2) {
332.  			cl_end();
333.  			xputc('\n');
334.  			curx = 1;
335.  			cury++;
336.  		}
337.  		cl_end();
338.  		curs(cx, cy);
339.  	}
340.  }
341.  
342.  #ifdef MSDOSCOLOR
343.  /* Sets up highlighting, using ANSI escape sequences, for monsters and 
344.   * objects (highlight code found in pri.c). 
345.   * The termcap entry for HI (from SO) is scanned to find the background 
346.   * color. If everything is o.k., monsters are displayed in the color 
347.   * used to define HILITE_MONSTER and objects are displayed in the color 
348.   * used to define HILITE_OBJECT. */
349.  
350.  #define ESC		0x1b
351.  #define NONE		0
352.  #define HIGH_INTENSITY	1
353.  #define BLACK		0
354.  #define RED		1
355.  #define GREEN		2
356.  #define YELLOW		3
357.  #define BLUE		4
358.  #define MAGENTA		5
359.  #define CYAN		6
360.  #define WHITE		7
361.  
362.  #define HILITE_ATTRIB	NONE
363.  #define HILITE_MONSTER	RED
364.  #define HILITE_OBJECT	YELLOW
365.  
366.  init_hilite()
367.  {
368.  	register int backg, len, mfore, ofore;
369.  
370.  	backg = BLACK;
371.  	mfore = ofore = WHITE;
372.  	/* find the background color, HI[len] == 'm' */
373.  	len = strlen(HI) - 1;
374.  	if (len > 3) 
375.  	if (isdigit(HI[len-1]) && 
376.  	    isdigit(HI[len-2]) && HI[len-2] != 3) {
377.  			backg = HI[len-1] - '0';
378.  			mfore = HILITE_MONSTER;
379.  			ofore = HILITE_OBJECT;
380.  	}
381.  	if (mfore == backg || ofore == backg) {
382.  		if (len < 7) mfore = ofore = WHITE;
383.  		else {
384.  			if (HI[2] == '3') mfore = ofore = HI[3] - '0';
385.  			else if (HI[4] == '3') mfore = ofore = HI[5] - '0';
386.  			else mfore = ofore = WHITE; /* give up! */
387.  		}
388.  	}
389.  
390.  	HI_MON = (char *) alloc(sizeof("E[0;33;44;54m"));
391.  	sprintf(HI_MON, "%c[%d;3%d;4%dm", ESC, HILITE_ATTRIB, 
392.  	        mfore, backg);
393.  	HI_OBJ = (char *) alloc(sizeof("E[0;33;44;54m"));
394.  	sprintf(HI_OBJ, "%c[%d;3%d;4%dm", ESC, HILITE_ATTRIB, 
395.  	        ofore, backg);
396.  }
397.  
398.  #endif