xref: /openbsd-src/distrib/special/more/tgoto.c (revision 434c844085c815c2d64647b8d0907d1d2df11b1f)
1*434c8440Sderaadt /*	$OpenBSD: tgoto.c,v 1.2 2015/11/15 07:12:50 deraadt Exp $	*/
2226e3677Sderaadt /*	$NetBSD: tgoto.c,v 1.5 1995/06/05 19:45:54 pk Exp $	*/
3226e3677Sderaadt 
4226e3677Sderaadt /*
5226e3677Sderaadt  * Copyright (c) 1980, 1993
6226e3677Sderaadt  *	The Regents of the University of California.  All rights reserved.
7226e3677Sderaadt  *
8226e3677Sderaadt  * Redistribution and use in source and binary forms, with or without
9226e3677Sderaadt  * modification, are permitted provided that the following conditions
10226e3677Sderaadt  * are met:
11226e3677Sderaadt  * 1. Redistributions of source code must retain the above copyright
12226e3677Sderaadt  *    notice, this list of conditions and the following disclaimer.
13226e3677Sderaadt  * 2. Redistributions in binary form must reproduce the above copyright
14226e3677Sderaadt  *    notice, this list of conditions and the following disclaimer in the
15226e3677Sderaadt  *    documentation and/or other materials provided with the distribution.
16226e3677Sderaadt  * 3. Neither the name of the University nor the names of its contributors
17226e3677Sderaadt  *    may be used to endorse or promote products derived from this software
18226e3677Sderaadt  *    without specific prior written permission.
19226e3677Sderaadt  *
20226e3677Sderaadt  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21226e3677Sderaadt  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22226e3677Sderaadt  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23226e3677Sderaadt  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24226e3677Sderaadt  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25226e3677Sderaadt  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26226e3677Sderaadt  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27226e3677Sderaadt  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28226e3677Sderaadt  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29226e3677Sderaadt  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30226e3677Sderaadt  * SUCH DAMAGE.
31226e3677Sderaadt  */
32226e3677Sderaadt 
33226e3677Sderaadt #include <string.h>
34226e3677Sderaadt #include <curses.h>
35226e3677Sderaadt 
36226e3677Sderaadt #define	CTRL(c)	((c) & 037)
37226e3677Sderaadt 
38226e3677Sderaadt #define MAXRETURNSIZE 64
39226e3677Sderaadt 
40226e3677Sderaadt char	*UP;
41226e3677Sderaadt char	*BC;
42226e3677Sderaadt 
43226e3677Sderaadt /*
44226e3677Sderaadt  * Routine to perform cursor addressing.
45226e3677Sderaadt  * CM is a string containing printf type escapes to allow
46226e3677Sderaadt  * cursor addressing.  We start out ready to print the destination
47226e3677Sderaadt  * line, and switch each time we print row or column.
48226e3677Sderaadt  * The following escapes are defined for substituting row/column:
49226e3677Sderaadt  *
50226e3677Sderaadt  *	%d	as in printf
51226e3677Sderaadt  *	%2	like %2d
52226e3677Sderaadt  *	%3	like %3d
53226e3677Sderaadt  *	%.	gives %c hacking special case characters
54226e3677Sderaadt  *	%+x	like %c but adding x first
55226e3677Sderaadt  *
56226e3677Sderaadt  *	The codes below affect the state but don't use up a value.
57226e3677Sderaadt  *
58226e3677Sderaadt  *	%>xy	if value > x add y
59226e3677Sderaadt  *	%r	reverses row/column
60226e3677Sderaadt  *	%i	increments row/column (for one origin indexing)
61226e3677Sderaadt  *	%%	gives %
62226e3677Sderaadt  *	%B	BCD (2 decimal digits encoded in one byte)
63226e3677Sderaadt  *	%D	Delta Data (backwards bcd)
64226e3677Sderaadt  *
65226e3677Sderaadt  * all other characters are ``self-inserting''.
66226e3677Sderaadt  */
67226e3677Sderaadt char *
tgoto(char * CM,int destcol,int destline)68*434c8440Sderaadt tgoto(char *CM, int destcol, int destline)
69226e3677Sderaadt {
70226e3677Sderaadt 	static char result[MAXRETURNSIZE];
71226e3677Sderaadt 	static char added[10];
72226e3677Sderaadt 	char *cp = CM;
73*434c8440Sderaadt 	char *dp = result;
74*434c8440Sderaadt 	int c;
75226e3677Sderaadt 	int oncol = 0;
76*434c8440Sderaadt 	int which = destline;
77226e3677Sderaadt 
78226e3677Sderaadt 	if (cp == 0) {
79226e3677Sderaadt toohard:
80226e3677Sderaadt 		/*
81226e3677Sderaadt 		 * ``We don't do that under BOZO's big top''
82226e3677Sderaadt 		 */
83226e3677Sderaadt 		return ("OOPS");
84226e3677Sderaadt 	}
85226e3677Sderaadt 	added[0] = 0;
86226e3677Sderaadt 	while ((c = *cp++) != '\0') {
87226e3677Sderaadt 		if (c != '%') {
88226e3677Sderaadt 			if (dp >= &result[MAXRETURNSIZE])
89226e3677Sderaadt 				goto toohard;
90226e3677Sderaadt 			*dp++ = c;
91226e3677Sderaadt 			continue;
92226e3677Sderaadt 		}
93226e3677Sderaadt 		switch (c = *cp++) {
94226e3677Sderaadt 
95226e3677Sderaadt #ifdef CM_N
96226e3677Sderaadt 		case 'n':
97226e3677Sderaadt 			destcol ^= 0140;
98226e3677Sderaadt 			destline ^= 0140;
99226e3677Sderaadt 			goto setwhich;
100226e3677Sderaadt #endif
101226e3677Sderaadt 
102226e3677Sderaadt 		case 'd':
103226e3677Sderaadt 			if (which < 10)
104226e3677Sderaadt 				goto one;
105226e3677Sderaadt 			if (which < 100)
106226e3677Sderaadt 				goto two;
107226e3677Sderaadt 			/* fall into... */
108226e3677Sderaadt 
109226e3677Sderaadt 		case '3':
110226e3677Sderaadt 			if (dp >= &result[MAXRETURNSIZE])
111226e3677Sderaadt 				goto toohard;
112226e3677Sderaadt 			*dp++ = (which / 100) | '0';
113226e3677Sderaadt 			which %= 100;
114226e3677Sderaadt 			/* fall into... */
115226e3677Sderaadt 
116226e3677Sderaadt 		case '2':
117226e3677Sderaadt two:
118226e3677Sderaadt 			if (dp >= &result[MAXRETURNSIZE])
119226e3677Sderaadt 				goto toohard;
120226e3677Sderaadt 			*dp++ = which / 10 | '0';
121226e3677Sderaadt one:
122226e3677Sderaadt 			if (dp >= &result[MAXRETURNSIZE])
123226e3677Sderaadt 				goto toohard;
124226e3677Sderaadt 			*dp++ = which % 10 | '0';
125226e3677Sderaadt swap:
126226e3677Sderaadt 			oncol = 1 - oncol;
127226e3677Sderaadt setwhich:
128226e3677Sderaadt 			which = oncol ? destcol : destline;
129226e3677Sderaadt 			continue;
130226e3677Sderaadt 
131226e3677Sderaadt #ifdef CM_GT
132226e3677Sderaadt 		case '>':
133226e3677Sderaadt 			if (which > *cp++)
134226e3677Sderaadt 				which += *cp++;
135226e3677Sderaadt 			else
136226e3677Sderaadt 				cp++;
137226e3677Sderaadt 			continue;
138226e3677Sderaadt #endif
139226e3677Sderaadt 
140226e3677Sderaadt 		case '+':
141226e3677Sderaadt 			which += *cp++;
142226e3677Sderaadt 			/* fall into... */
143226e3677Sderaadt 
144226e3677Sderaadt 		case '.':
145226e3677Sderaadt 			/*
146226e3677Sderaadt 			 * This code is worth scratching your head at for a
147226e3677Sderaadt 			 * while.  The idea is that various weird things can
148226e3677Sderaadt 			 * happen to nulls, EOT's, tabs, and newlines by the
149226e3677Sderaadt 			 * tty driver, arpanet, and so on, so we don't send
150226e3677Sderaadt 			 * them if we can help it.
151226e3677Sderaadt 			 *
152226e3677Sderaadt 			 * Tab is taken out to get Ann Arbors to work, otherwise
153226e3677Sderaadt 			 * when they go to column 9 we increment which is wrong
154226e3677Sderaadt 			 * because bcd isn't continuous.  We should take out
155226e3677Sderaadt 			 * the rest too, or run the thing through more than
156226e3677Sderaadt 			 * once until it doesn't make any of these, but that
157226e3677Sderaadt 			 * would make termlib (and hence pdp-11 ex) bigger,
158226e3677Sderaadt 			 * and also somewhat slower.  This requires all
159226e3677Sderaadt 			 * programs which use termlib to stty tabs so they
160226e3677Sderaadt 			 * don't get expanded.  They should do this anyway
161226e3677Sderaadt 			 * because some terminals use ^I for other things,
162226e3677Sderaadt 			 * like nondestructive space.
163226e3677Sderaadt 			 */
164226e3677Sderaadt 			if ((which == 0 || which == CTRL('d') || which == '\n')
165226e3677Sderaadt 			    && (oncol || UP)) /* Assumption: backspace works */
166226e3677Sderaadt 				/*
167226e3677Sderaadt 				 * Loop needed because newline happens
168226e3677Sderaadt 				 * to be the successor of tab.
169226e3677Sderaadt 				 */
170226e3677Sderaadt 				do {
171226e3677Sderaadt 					if (strlcat(added, oncol ?
172226e3677Sderaadt 					    (BC ? BC : "\b") : UP,
173226e3677Sderaadt 					    sizeof(added)) >= sizeof(added))
174226e3677Sderaadt 						goto toohard;
175226e3677Sderaadt 					which++;
176226e3677Sderaadt 				} while (which == '\n');
177226e3677Sderaadt 			if (dp >= &result[MAXRETURNSIZE])
178226e3677Sderaadt 				goto toohard;
179226e3677Sderaadt 			*dp++ = which;
180226e3677Sderaadt 			goto swap;
181226e3677Sderaadt 
182226e3677Sderaadt 		case 'r':
183226e3677Sderaadt 			oncol = 1;
184226e3677Sderaadt 			goto setwhich;
185226e3677Sderaadt 
186226e3677Sderaadt 		case 'i':
187226e3677Sderaadt 			destcol++;
188226e3677Sderaadt 			destline++;
189226e3677Sderaadt 			which++;
190226e3677Sderaadt 			continue;
191226e3677Sderaadt 
192226e3677Sderaadt 		case '%':
193226e3677Sderaadt 			if (dp >= &result[MAXRETURNSIZE])
194226e3677Sderaadt 				goto toohard;
195226e3677Sderaadt 			*dp++ = c;
196226e3677Sderaadt 			continue;
197226e3677Sderaadt 
198226e3677Sderaadt #ifdef CM_B
199226e3677Sderaadt 		case 'B':
200226e3677Sderaadt 			which = (which/10 << 4) + which%10;
201226e3677Sderaadt 			continue;
202226e3677Sderaadt #endif
203226e3677Sderaadt 
204226e3677Sderaadt #ifdef CM_D
205226e3677Sderaadt 		case 'D':
206226e3677Sderaadt 			which = which - 2 * (which%16);
207226e3677Sderaadt 			continue;
208226e3677Sderaadt #endif
209226e3677Sderaadt 
210226e3677Sderaadt 		default:
211226e3677Sderaadt 			goto toohard;
212226e3677Sderaadt 		}
213226e3677Sderaadt 	}
214226e3677Sderaadt 	if (strlcpy(dp, added, sizeof(result) - (dp - result))
215226e3677Sderaadt 	    >= sizeof(result) - (dp - result))
216226e3677Sderaadt 		goto toohard;
217226e3677Sderaadt 	return (result);
218226e3677Sderaadt }
219