Source:NetHack 3.0.0/termcap.c

From NetHackWiki
(Redirected from NetHack 3.0.0/termcap.c)
Jump to navigation Jump to search

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

The NetHack General Public License applies to screenshots, source code and other content from NetHack.

This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.

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 <ctype.h>	/* 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<abs(curx-x))) {
229.  		(void) putchar('\r');
230.  		curx = 1;
231.  		nocmov(x, y);
232.  	} else if(!CM) {
233.  		nocmov(x, y);
234.  	} else
235.  		cmov(x, y);
236.  }
237.  
238.  static void
239.  nocmov(x, y)
240.  {
241.  	if (cury > 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