xref: /csrg-svn/games/rogue/curses.c (revision 36704)
132689Sbostic /*
2*36704Sbostic  * Copyright (c) 1988 The Regents of the University of California.
3*36704Sbostic  * All rights reserved.
4*36704Sbostic  *
5*36704Sbostic  * This code is derived from software contributed to Berkeley by
6*36704Sbostic  * Timothy C. Stoehr.
7*36704Sbostic  *
8*36704Sbostic  * Redistribution and use in source and binary forms are permitted
9*36704Sbostic  * provided that the above copyright notice and this paragraph are
10*36704Sbostic  * duplicated in all such forms and that any documentation,
11*36704Sbostic  * advertising materials, and other materials related to such
12*36704Sbostic  * distribution and use acknowledge that the software was developed
13*36704Sbostic  * by the University of California, Berkeley.  The name of the
14*36704Sbostic  * University may not be used to endorse or promote products derived
15*36704Sbostic  * from this software without specific prior written permission.
16*36704Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17*36704Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18*36704Sbostic  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19*36704Sbostic  */
20*36704Sbostic 
21*36704Sbostic #ifndef lint
22*36704Sbostic static char sccsid[] = "@(#)curses.c	5.2 (Berkeley) 02/07/89";
23*36704Sbostic #endif /* not lint */
24*36704Sbostic 
25*36704Sbostic /*
2632689Sbostic  * curses.c
2732689Sbostic  *
2832689Sbostic  * This source herein may be modified and/or distributed by anybody who
2932689Sbostic  * so desires, with the following restrictions:
3032689Sbostic  *    1.)  No portion of this notice shall be removed.
3132689Sbostic  *    2.)  Credit shall not be taken for the creation of this source.
3232689Sbostic  *    3.)  This code is not to be traded, sold, or used for personal
3332689Sbostic  *         gain or profit.
3432689Sbostic  *
3532689Sbostic  */
3632689Sbostic 
3732689Sbostic #ifdef CURSES
3832689Sbostic 
3932689Sbostic /* The following is a curses emulation package suitable for the rogue program
4032689Sbostic  * in which it is included.  No other suitability is claimed or suspected.
4132689Sbostic  * Only those routines currently needed by this rogue program are included.
4232689Sbostic  * This is being provided for those systems that don't have a suitable
4332689Sbostic  * curses package and want to run this rogue program.
4432689Sbostic  *
4532689Sbostic  * Compile the entire program with -DCURSES to incorporate this package.
4632689Sbostic  *
4732689Sbostic  * The following is NOT supported:
4832689Sbostic  *   "%D", "%B", "%n", or "%>" inside a cursor motion (cm) termcap string.
4932689Sbostic  *   Terminals in which the cursor motion addresses the row differently from
5032689Sbostic  *       the column, as in ":cm=\E%2,%3" or ":cm=\EY%+x;%+y"
5132689Sbostic  *   Termcap database stored in the TERMCAP environ variable as returned
5232689Sbostic  *       from md_getenv().  Only the termcap file name can be stored there.
5332689Sbostic  *       See the comments for md_getenv() in machdep.c.
5432689Sbostic  *   Terminals without non-destructive backspace.  Backspace (^H) is used
5532689Sbostic  *       for cursor motion regardless of any termcap entries.
5632689Sbostic  *   The ":tc=" termcap entry is ignored.
5732689Sbostic  *
5832689Sbostic  * Suggestions:
5932689Sbostic  *   Use line-feed as your termcap "do" entry: ":do=^J", ":do=\012" or
6032689Sbostic  *      ":do=\n"  This will help cursor motion optimization.  If line-feed
6132689Sbostic  *      won't work, then a short escape sequence will do.
6232689Sbostic  */
6332689Sbostic 
6432689Sbostic #include <stdio.h>
6532689Sbostic #include "rogue.h"
6632689Sbostic 
6732689Sbostic boolean tc_tname();
6832689Sbostic 
6932689Sbostic #define BS 010
7032689Sbostic #define LF 012
7132689Sbostic #define CR 015
7232689Sbostic #define ESC '\033'
7332689Sbostic #define TAB '\011'
7432689Sbostic 
7532689Sbostic #define ST_MASK 0x80
7632689Sbostic #define BUFLEN 256
7732689Sbostic 
7832689Sbostic char terminal[DROWS][DCOLS];
7932689Sbostic char buffer[DROWS][DCOLS];
8032689Sbostic char *tc_file;
8132689Sbostic 
8232689Sbostic char cm_esc[16];
8332689Sbostic char cm_sep[16];
8432689Sbostic char cm_end[16];
8532689Sbostic boolean cm_reverse = 0;
8632689Sbostic boolean cm_two = 0;
8732689Sbostic boolean cm_three = 0;
8832689Sbostic boolean cm_char = 0;
8932689Sbostic short cm_inc = 0;
9032689Sbostic 
9132689Sbostic boolean screen_dirty;
9232689Sbostic boolean lines_dirty[DROWS];
9332689Sbostic boolean buf_stand_out = 0;
9432689Sbostic boolean term_stand_out = 0;
9532689Sbostic 
9632689Sbostic int LINES = DROWS;
9732689Sbostic int COLS = DCOLS;
9832689Sbostic WINDOW scr_buf;
9932689Sbostic WINDOW *curscr = &scr_buf;
10032689Sbostic 
10132689Sbostic char *CL = (char *) 0;
10232689Sbostic char *CM = (char *) 0;
10332689Sbostic char *UC = (char *) 0;	/* UP */
10432689Sbostic char *DO = (char *) 0;
10532689Sbostic char *VS = "";
10632689Sbostic char *VE = "";
10732689Sbostic char *TI = "";
10832689Sbostic char *TE = "";
10932689Sbostic char *SO = "";
11032689Sbostic char *SE = "";
11132689Sbostic 
11232689Sbostic short cur_row;
11332689Sbostic short cur_col;
11432689Sbostic 
11532689Sbostic initscr()
11632689Sbostic {
11732689Sbostic 	clear();
11832689Sbostic 	get_term_info();
11932689Sbostic 	printf("%s%s", TI, VS);
12032689Sbostic }
12132689Sbostic 
12232689Sbostic endwin()
12332689Sbostic {
12432689Sbostic 	printf("%s%s", TE, VE);
12532689Sbostic 	md_cbreak_no_echo_nonl(0);
12632689Sbostic }
12732689Sbostic 
12832689Sbostic move(row, col)
12932689Sbostic short row, col;
13032689Sbostic {
13132689Sbostic 	curscr->_cury = row;
13232689Sbostic 	curscr->_curx = col;
13332689Sbostic 	screen_dirty = 1;
13432689Sbostic }
13532689Sbostic 
13632689Sbostic mvaddstr(row, col, str)
13732689Sbostic short row, col;
13832689Sbostic char *str;
13932689Sbostic {
14032689Sbostic 	move(row, col);
14132689Sbostic 	addstr(str);
14232689Sbostic }
14332689Sbostic 
14432689Sbostic addstr(str)
14532689Sbostic char *str;
14632689Sbostic {
14732689Sbostic 	while (*str) {
14832689Sbostic 		addch((int) *str++);
14932689Sbostic 	}
15032689Sbostic }
15132689Sbostic 
15232689Sbostic addch(ch)
15332689Sbostic register int ch;
15432689Sbostic {
15532689Sbostic 	short row, col;
15632689Sbostic 
15732689Sbostic 	row = curscr->_cury;
15832689Sbostic 	col = curscr->_curx++;
15932689Sbostic 
16032689Sbostic 	if (buf_stand_out) {
16132689Sbostic 		ch |= ST_MASK;
16232689Sbostic 	}
16332689Sbostic 	buffer[row][col] = (char) ch;
16432689Sbostic 	lines_dirty[row] = 1;
16532689Sbostic 	screen_dirty = 1;
16632689Sbostic }
16732689Sbostic 
16832689Sbostic mvaddch(row, col, ch)
16932689Sbostic short row, col;
17032689Sbostic int ch;
17132689Sbostic {
17232689Sbostic 	move(row, col);
17332689Sbostic 	addch(ch);
17432689Sbostic }
17532689Sbostic 
17632689Sbostic refresh()
17732689Sbostic {
17832689Sbostic 	register i, j, line;
17932689Sbostic 	short old_row, old_col, first_row;
18032689Sbostic 
18132689Sbostic 	if (screen_dirty) {
18232689Sbostic 
18332689Sbostic 		old_row = curscr->_cury;
18432689Sbostic 		old_col = curscr->_curx;
18532689Sbostic 		first_row = cur_row;
18632689Sbostic 
18732689Sbostic 		for (i = 0; i < DROWS; i++) {
18832689Sbostic 			line = (first_row + i) % DROWS;
18932689Sbostic 			if (lines_dirty[line]) {
19032689Sbostic 				for (j = 0; j < DCOLS; j++) {
19132689Sbostic 					if (buffer[line][j] != terminal[line][j]) {
19232689Sbostic 						put_char_at(line, j, buffer[line][j]);
19332689Sbostic 					}
19432689Sbostic 				}
19532689Sbostic 				lines_dirty[line] = 0;
19632689Sbostic 			}
19732689Sbostic 		}
19832689Sbostic 		put_cursor(old_row, old_col);
19932689Sbostic 		screen_dirty = 0;
20032689Sbostic 		fflush(stdout);
20132689Sbostic 	}
20232689Sbostic }
20332689Sbostic 
20432689Sbostic wrefresh(scr)
20532689Sbostic WINDOW *scr;
20632689Sbostic {
20732689Sbostic 	short i, col;
20832689Sbostic 
20932689Sbostic 	printf("%s", CL);
21032689Sbostic 	cur_row = cur_col = 0;
21132689Sbostic 
21232689Sbostic 	for (i = 0; i < DROWS; i++) {
21332689Sbostic 		col = 0;
21432689Sbostic 		while (col < DCOLS) {
21532689Sbostic 			while ((col < DCOLS) && (buffer[i][col] == ' ')) {
21632689Sbostic 				col++;
21732689Sbostic 			}
21832689Sbostic 			if (col < DCOLS) {
21932689Sbostic 				put_cursor(i, col);
22032689Sbostic 			}
22132689Sbostic 			while ((col < DCOLS) && (buffer[i][col] != ' ')) {
22232689Sbostic 				put_st_char((int) buffer[i][col]);
22332689Sbostic 				cur_col++;
22432689Sbostic 				col++;
22532689Sbostic 			}
22632689Sbostic 		}
22732689Sbostic 	}
22832689Sbostic 	put_cursor(curscr->_cury, curscr->_curx);
22932689Sbostic 	fflush(stdout);
23032689Sbostic 	scr = scr;		/* make lint happy */
23132689Sbostic }
23232689Sbostic 
23332689Sbostic mvinch(row, col)
23432689Sbostic short row, col;
23532689Sbostic {
23632689Sbostic 	move(row, col);
23732689Sbostic 	return((int) buffer[row][col]);
23832689Sbostic }
23932689Sbostic 
24032689Sbostic clear()
24132689Sbostic {
24232689Sbostic 	printf("%s", CL);
24332689Sbostic 	fflush(stdout);
24432689Sbostic 	cur_row = cur_col = 0;
24532689Sbostic 	move(0, 0);
24632689Sbostic 	clear_buffers();
24732689Sbostic }
24832689Sbostic 
24932689Sbostic clrtoeol()
25032689Sbostic {
25132689Sbostic 	short row, col;
25232689Sbostic 
25332689Sbostic 	row = curscr->_cury;
25432689Sbostic 
25532689Sbostic 	for (col = curscr->_curx; col < DCOLS; col++) {
25632689Sbostic 		buffer[row][col] = ' ';
25732689Sbostic 	}
25832689Sbostic 	lines_dirty[row] = 1;
25932689Sbostic }
26032689Sbostic 
26132689Sbostic standout()
26232689Sbostic {
26332689Sbostic 	buf_stand_out = 1;
26432689Sbostic }
26532689Sbostic 
26632689Sbostic standend()
26732689Sbostic {
26832689Sbostic 	buf_stand_out = 0;
26932689Sbostic }
27032689Sbostic 
27132689Sbostic crmode()
27232689Sbostic {
27332689Sbostic 	md_cbreak_no_echo_nonl(1);
27432689Sbostic }
27532689Sbostic 
27632689Sbostic noecho()
27732689Sbostic {
27832689Sbostic 	/* crmode() takes care of this */
27932689Sbostic }
28032689Sbostic 
28132689Sbostic nonl()
28232689Sbostic {
28332689Sbostic 	/* crmode() takes care of this */
28432689Sbostic }
28532689Sbostic 
28632689Sbostic clear_buffers()
28732689Sbostic {
28832689Sbostic 	register i, j;
28932689Sbostic 
29032689Sbostic 	screen_dirty = 0;
29132689Sbostic 
29232689Sbostic 	for (i = 0; i < DROWS; i++) {
29332689Sbostic 		lines_dirty[i] = 0;
29432689Sbostic 		for (j = 0; j < DCOLS; j++) {
29532689Sbostic 			terminal[i][j] = ' ';
29632689Sbostic 			buffer[i][j] = ' ';
29732689Sbostic 		}
29832689Sbostic 	}
29932689Sbostic }
30032689Sbostic 
30132689Sbostic put_char_at(row, col, ch)
30232689Sbostic register row, col, ch;
30332689Sbostic {
30432689Sbostic 	put_cursor(row, col);
30532689Sbostic 	put_st_char(ch);
30632689Sbostic 	terminal[row][col] = (char) ch;
30732689Sbostic 	cur_col++;
30832689Sbostic }
30932689Sbostic 
31032689Sbostic put_cursor(row, col)
31132689Sbostic register row, col;
31232689Sbostic {
31332689Sbostic 	register i, rdif, cdif;
31432689Sbostic 	short ch, t;
31532689Sbostic 
31632689Sbostic 	rdif = (row > cur_row) ? row - cur_row : cur_row - row;
31732689Sbostic 	cdif = (col > cur_col) ? col - cur_col : cur_col - col;
31832689Sbostic 
31932689Sbostic 	if (((row > cur_row) && DO) || ((cur_row > row) && UC)) {
32032689Sbostic 		if ((rdif < 4) && (cdif < 4)) {
32132689Sbostic 			for (i = 0; i < rdif; i++) {
32232689Sbostic 				printf("%s", ((row < cur_row) ? UC : DO));
32332689Sbostic 			}
32432689Sbostic 			cur_row = row;
32532689Sbostic 			if (col == cur_col) {
32632689Sbostic 				return;
32732689Sbostic 			}
32832689Sbostic 		}
32932689Sbostic 	}
33032689Sbostic 	if (row == cur_row) {
33132689Sbostic 		if (cdif <= 6) {
33232689Sbostic 		for (i = 0; i < cdif; i++) {
33332689Sbostic 				ch = (col < cur_col) ? BS :
33432689Sbostic 						terminal[row][cur_col + i];
33532689Sbostic 				put_st_char((int) ch);
33632689Sbostic 			}
33732689Sbostic 			cur_row = row;
33832689Sbostic 			cur_col = col;
33932689Sbostic 			return;
34032689Sbostic 		}
34132689Sbostic 	}
34232689Sbostic 	cur_row = row;
34332689Sbostic 	cur_col = col;
34432689Sbostic 
34532689Sbostic 	row += cm_inc;
34632689Sbostic 	col += cm_inc;
34732689Sbostic 
34832689Sbostic 	if (cm_reverse) {
34932689Sbostic 		t = row;
35032689Sbostic 		row = col;
35132689Sbostic 		col = t;
35232689Sbostic 	}
35332689Sbostic 	if (cm_two) {
35432689Sbostic 		printf("%s%02d%s%02d%s", cm_esc, row, cm_sep, col, cm_end);
35532689Sbostic 	} else if (cm_three) {
35632689Sbostic 		printf("%s%03d%s%03d%s", cm_esc, row, cm_sep, col, cm_end);
35732689Sbostic 	} else if (cm_char) {
35832689Sbostic 		printf("%s%c%s%c%s", cm_esc, row, cm_sep, col, cm_end);
35932689Sbostic 	} else {
36032689Sbostic 		printf("%s%d%s%d%s", cm_esc, row, cm_sep, col, cm_end);
36132689Sbostic 	}
36232689Sbostic }
36332689Sbostic 
36432689Sbostic put_st_char(ch)
36532689Sbostic register ch;
36632689Sbostic {
36732689Sbostic 	if ((ch & ST_MASK) && (!term_stand_out)) {
36832689Sbostic 		ch &= ~ST_MASK;
36932689Sbostic 		printf("%s%c", SO, ch);
37032689Sbostic 		term_stand_out = 1;
37132689Sbostic 	} else if ((!(ch & ST_MASK)) && term_stand_out) {
37232689Sbostic 		printf("%s%c", SE, ch);
37332689Sbostic 		term_stand_out = 0;
37432689Sbostic 	} else {
37532689Sbostic 		ch &= ~ST_MASK;
37632689Sbostic 		putchar(ch);
37732689Sbostic 	}
37832689Sbostic }
37932689Sbostic 
38032689Sbostic get_term_info()
38132689Sbostic {
38232689Sbostic 	FILE *fp;
38332689Sbostic 	char *term, *tcf;
38432689Sbostic 	char buf[BUFLEN];
38532689Sbostic 
38632689Sbostic 	if (tcf = md_getenv("TERMCAP")) {
38732689Sbostic 		if (strlen(tcf) > 40) {
38832689Sbostic 			clean_up("TERMCAP file name too long");
38932689Sbostic 		}
39032689Sbostic 		tc_file = tcf;
39132689Sbostic 	} else {
39232689Sbostic 		if (!(tc_file = md_gdtcf())) {
39332689Sbostic 			clean_up("I need a termcap file");
39432689Sbostic 		}
39532689Sbostic 	}
39632689Sbostic 
39732689Sbostic 	if (!(term = md_getenv("TERM"))) {
39832689Sbostic 		clean_up("Cannot find TERM variable in environ");
39932689Sbostic 	}
40032689Sbostic 	if ((fp = fopen(tc_file, "r")) == NULL) {
40132689Sbostic 		sprintf(buf, "Cannot open TERMCAP file: %s", tc_file);
40232689Sbostic 		clean_up(buf);
40332689Sbostic 	}
40432689Sbostic 
40532689Sbostic 	if (!tc_tname(fp, term, buf)) {
40632689Sbostic 		sprintf(buf, "Cannot find TERM type: %s in TERMCAP file: %s", term,
40732689Sbostic 			tc_file);
40832689Sbostic 		clean_up(buf);
40932689Sbostic 	}
41032689Sbostic 	tc_gtdata(fp, buf);
41132689Sbostic 	fclose(fp);
41232689Sbostic }
41332689Sbostic 
41432689Sbostic boolean
41532689Sbostic tc_tname(fp, term, buf)
41632689Sbostic FILE *fp;
41732689Sbostic char *term;
41832689Sbostic char *buf;
41932689Sbostic {
42032689Sbostic 	short i, j;
42132689Sbostic 	boolean found = 0;
42232689Sbostic 	char *fg;
42332689Sbostic 
42432689Sbostic 	while (!found) {
42532689Sbostic 		i = 0;
42632689Sbostic 		fg = fgets(buf, BUFLEN, fp);
42732689Sbostic 		if (fg != NULL) {
42832689Sbostic 			if (	(buf[0] != '#') && (buf[0] != ' ') && (buf[0] != TAB) &&
42932689Sbostic 					(buf[0] != CR) && (buf[0] != LF)) {
43032689Sbostic 				while (buf[i] && (!found)) {
43132689Sbostic 					j = 0;
43232689Sbostic 					while (buf[i] == term[j]) {
43332689Sbostic 						i++;
43432689Sbostic 						j++;
43532689Sbostic 					}
43632689Sbostic 					if ((!term[j]) && ((buf[i] == '|') || (buf[i] == ':'))) {
43732689Sbostic 						found = 1;
43832689Sbostic 					} else {
43932689Sbostic 						while (buf[i] && (buf[i] != '|') && (buf[i] != ':')) {
44032689Sbostic 							i++;
44132689Sbostic 						}
44232689Sbostic 						if (buf[i]) {
44332689Sbostic 							i++;
44432689Sbostic 						}
44532689Sbostic 					}
44632689Sbostic 				}
44732689Sbostic 			}
44832689Sbostic 		} else {
44932689Sbostic 			break;
45032689Sbostic 		}
45132689Sbostic 	}
45232689Sbostic 	return(found);
45332689Sbostic }
45432689Sbostic 
45532689Sbostic tc_gtdata(fp, buf)
45632689Sbostic FILE *fp;
45732689Sbostic char *buf;
45832689Sbostic {
45932689Sbostic 	short i;
46032689Sbostic 	boolean first = 1;
46132689Sbostic 
46232689Sbostic 	do {
46332689Sbostic 		if (!first) {
46432689Sbostic 			if ((buf[0] != TAB) && (buf[0] != ' ')) {
46532689Sbostic 				break;
46632689Sbostic 			}
46732689Sbostic 		}
46832689Sbostic 		first = 0;
46932689Sbostic 		i = 0;
47032689Sbostic 		while (buf[i]) {
47132689Sbostic 			while (buf[i] && (buf[i] != ':')) {
47232689Sbostic 				i++;
47332689Sbostic 			}
47432689Sbostic 			if (buf[i] == ':') {
47532689Sbostic 				if (!strncmp(buf + i, ":cl=", 4)) {
47632689Sbostic 					tc_gets(buf + i, &CL);
47732689Sbostic 				} else if (!strncmp(buf + i, ":cm=", 4)) {
47832689Sbostic 					tc_gets(buf + i, &CM);
47932689Sbostic 				} else if (!strncmp(buf + i, ":up=", 4)) {
48032689Sbostic 					tc_gets(buf + i, &UC);
48132689Sbostic 				} else if (!strncmp(buf + i, ":do=", 4)) {
48232689Sbostic 					tc_gets(buf + i, &DO);
48332689Sbostic 				} else if (!strncmp(buf + i, ":vs=", 4)) {
48432689Sbostic 					tc_gets(buf + i, &VS);
48532689Sbostic 				} else if (!strncmp(buf + i, ":ve=", 4)) {
48632689Sbostic 					tc_gets(buf + i, &VE);
48732689Sbostic 				} else if (!strncmp(buf + i, ":ti=", 4)) {
48832689Sbostic 					tc_gets(buf + i, &TI);
48932689Sbostic 				} else if (!strncmp(buf + i, ":te=", 4)) {
49032689Sbostic 					tc_gets(buf + i, &TE);
49132689Sbostic 				} else if (!strncmp(buf + i, ":vs=", 4)) {
49232689Sbostic 					tc_gets(buf + i, &VS);
49332689Sbostic 				} else if (!strncmp(buf + i, ":ve=", 4)) {
49432689Sbostic 					tc_gets(buf + i, &VE);
49532689Sbostic 				} else if (!strncmp(buf + i, ":so=", 4)) {
49632689Sbostic 					tc_gets(buf + i, &SO);
49732689Sbostic 				} else if (!strncmp(buf + i, ":se=", 4)) {
49832689Sbostic 					tc_gets(buf + i, &SE);
49932689Sbostic 				} else if (!strncmp(buf + i, ":li#", 4)) {
50032689Sbostic 					tc_gnum(buf + i, &LINES);
50132689Sbostic 				} else if (!strncmp(buf + i, ":co#", 4)) {
50232689Sbostic 					tc_gnum(buf + i, &COLS);
50332689Sbostic 				}
50432689Sbostic 				i++;
50532689Sbostic 			}
50632689Sbostic 		}
50732689Sbostic 	} while (fgets(buf, BUFLEN, fp) != NULL);
50832689Sbostic 
50932689Sbostic 	if ((!CM) || (!CL)) {
51032689Sbostic 		clean_up("Terminal and termcap must have cm and cl");
51132689Sbostic 	}
51232689Sbostic 	tc_cmget();
51332689Sbostic }
51432689Sbostic 
51532689Sbostic tc_gets(ibuf, tcstr)
51632689Sbostic char *ibuf;
51732689Sbostic char **tcstr;
51832689Sbostic {
51932689Sbostic 	short i, j, k, n;
52032689Sbostic 	char obuf[BUFLEN];
52132689Sbostic 
52232689Sbostic 	i = 4;
52332689Sbostic 	j = 0;
52432689Sbostic 
52532689Sbostic 	while (ibuf[i] && is_digit(ibuf[i])) {
52632689Sbostic 		i++;
52732689Sbostic 	}
52832689Sbostic 
52932689Sbostic 	while (ibuf[i] && (ibuf[i] != ':')) {
53032689Sbostic 		if (ibuf[i] == '\\') {
53132689Sbostic 			i++;
53232689Sbostic 			switch(ibuf[i]) {
53332689Sbostic 			case 'E':
53432689Sbostic 				obuf[j] = ESC;
53532689Sbostic 				i++;
53632689Sbostic 				break;
53732689Sbostic 			case 'n':
53832689Sbostic 				obuf[j] = LF;
53932689Sbostic 				i++;
54032689Sbostic 				break;
54132689Sbostic 			case 'r':
54232689Sbostic 				obuf[j] = CR;
54332689Sbostic 				i++;
54432689Sbostic 				break;
54532689Sbostic 			case 'b':
54632689Sbostic 				obuf[j] = BS;
54732689Sbostic 				i++;
54832689Sbostic 				break;
54932689Sbostic 			case 't':
55032689Sbostic 				obuf[j] = TAB;
55132689Sbostic 				i++;
55232689Sbostic 				break;
55332689Sbostic 			case '0':
55432689Sbostic 			case '1':
55532689Sbostic 			case '2':
55632689Sbostic 			case '3':
55732689Sbostic 			case '4':
55832689Sbostic 			case '5':
55932689Sbostic 			case '6':
56032689Sbostic 			case '7':
56132689Sbostic 			case '8':
56232689Sbostic 			case '9':
56332689Sbostic 				n = 0;
56432689Sbostic 				k = 0;
56532689Sbostic 				while (k < 3 && ibuf[i] && is_digit(ibuf[i])) {
56632689Sbostic 					n = (8 * n) + (ibuf[i] - '0');
56732689Sbostic 					i++;
56832689Sbostic 					k++;
56932689Sbostic 				}
57032689Sbostic 				obuf[j] = (char) n;
57132689Sbostic 				break;
57232689Sbostic 			default:
57332689Sbostic 				obuf[j] = ibuf[i];
57432689Sbostic 				i++;
57532689Sbostic 			}
57632689Sbostic 		} else if (ibuf[i] == '^') {
57732689Sbostic 			obuf[j] = ibuf[i+1] - 64;
57832689Sbostic 			i += 2;
57932689Sbostic 		} else {
58032689Sbostic 			obuf[j] = ibuf[i++];
58132689Sbostic 		}
58232689Sbostic 		j++;
58332689Sbostic 	}
58432689Sbostic 	obuf[j] = 0;
58532689Sbostic 	if (!(*tcstr = md_malloc(j + 1))) {
58632689Sbostic 		clean_up("cannot alloc() memory");
58732689Sbostic 	}
58832689Sbostic 	(void) strcpy(*tcstr, obuf);
58932689Sbostic }
59032689Sbostic 
59132689Sbostic tc_gnum(ibuf, n)
59232689Sbostic char *ibuf;
59332689Sbostic int *n;
59432689Sbostic {
59532689Sbostic 	short i;
59632689Sbostic 	int r = 0;
59732689Sbostic 
59832689Sbostic 	i = 4;
59932689Sbostic 
60032689Sbostic 	while (is_digit(ibuf[i])) {
60132689Sbostic 		r = (r * 10) + (ibuf[i] - '0');
60232689Sbostic 		i++;
60332689Sbostic 	}
60432689Sbostic 	*n = r;
60532689Sbostic }
60632689Sbostic 
60732689Sbostic tstp()
60832689Sbostic {
60932689Sbostic 	endwin();
61032689Sbostic 	md_tstp();
61132689Sbostic 
61232689Sbostic 	start_window();
61332689Sbostic 	printf("%s%s", TI, VS);
61432689Sbostic 	wrefresh(curscr);
61532689Sbostic 	md_slurp();
61632689Sbostic }
61732689Sbostic 
61832689Sbostic tc_cmget()
61932689Sbostic {
62032689Sbostic 	short i = 0, j = 0, rc_spec = 0;
62132689Sbostic 
62232689Sbostic 	while (CM[i] && (CM[i] != '%') && (j < 15)) {
62332689Sbostic 		cm_esc[j++] = CM[i++];
62432689Sbostic 	}
62532689Sbostic 	cm_esc[j] = 0;
62632689Sbostic 
62732689Sbostic 	while (CM[i] && (rc_spec < 2)) {
62832689Sbostic 		if (CM[i] == '%') {
62932689Sbostic 			i++;
63032689Sbostic 			switch(CM[i]) {
63132689Sbostic 			case 'd':
63232689Sbostic 				rc_spec++;
63332689Sbostic 				break;
63432689Sbostic 			case 'i':
63532689Sbostic 				cm_inc = 1;
63632689Sbostic 				break;
63732689Sbostic 			case '2':
63832689Sbostic 				cm_two = 1;
63932689Sbostic 				rc_spec++;
64032689Sbostic 				break;
64132689Sbostic 			case '3':
64232689Sbostic 				cm_three = 1;
64332689Sbostic 				rc_spec++;
64432689Sbostic 				break;
64532689Sbostic 			case '.':
64632689Sbostic 				cm_char = 1;
64732689Sbostic 				rc_spec++;
64832689Sbostic 				break;
64932689Sbostic 			case 'r':
65032689Sbostic 				cm_reverse = 1;
65132689Sbostic 				break;
65232689Sbostic 			case '+':
65332689Sbostic 				i++;
65432689Sbostic 				cm_inc = CM[i];
65532689Sbostic 				cm_char = 1;
65632689Sbostic 				rc_spec++;
65732689Sbostic 				break;
65832689Sbostic 			}
65932689Sbostic 			i++;
66032689Sbostic 		} else {
66132689Sbostic 			j = 0;
66232689Sbostic 			while (CM[i] && (CM[i] != '%')) {
66332689Sbostic 				cm_sep[j++] = CM[i++];
66432689Sbostic 			}
66532689Sbostic 			cm_sep[j] = 0;
66632689Sbostic 		}
66732689Sbostic 	}
66832689Sbostic 
66932689Sbostic 	j = 0;
67032689Sbostic 	if (rc_spec == 2) {
67132689Sbostic 		while (CM[i] && (j < 15)) {
67232689Sbostic 			cm_end[j++] = CM[i++];
67332689Sbostic 		}
67432689Sbostic 	}
67532689Sbostic 	cm_end[j] = 0;
67632689Sbostic }
67732689Sbostic 
67832689Sbostic #endif
679