xref: /illumos-gate/usr/src/ucblib/libtermcap/tgoto.c (revision dd72704bd9e794056c558153663c739e2012d721)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 1997 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
28 /*	  All Rights Reserved  	*/
29 
30 /* Copyright (c) 1979 Regents of the University of California */
31 
32 /*LINTLIBRARY*/
33 
34 #include <sys/types.h>
35 #include <string.h>
36 #include <sys/ttychars.h>
37 
38 #if 0
39 static char
40 sccsid[] = "@(#)tgoto.c 1.5 88/02/08 SMI"; /* from UCB 4.1 6/27/83 */
41 #endif
42 
43 #define	MAXRETURNSIZE 64
44 
45 char	*UP;
46 char	*BC;
47 
48 /*
49  * Routine to perform cursor addressing.
50  * CM is a string containing printf type escapes to allow
51  * cursor addressing.  We start out ready to print the destination
52  * line, and switch each time we print row or column.
53  * The following escapes are defined for substituting row/column:
54  *
55  *	%d	as in printf
56  *	%2	like %2d
57  *	%3	like %3d
58  *	%.	gives %c hacking special case characters
59  *	%+x	like %c but adding x first
60  *
61  *	The codes below affect the state but don't use up a value.
62  *
63  *	%>xy	if value > x add y
64  *	%r	reverses row/column
65  *	%i	increments row/column (for one origin indexing)
66  *	%%	gives %
67  *	%B	BCD (2 decimal digits encoded in one byte)
68  *	%D	Delta Data (backwards bcd)
69  *
70  * all other characters are ``self-inserting''.
71  */
72 
73 char *
74 tgoto(char *CM, int destcol, int destline)
75 {
76 	static char result[MAXRETURNSIZE];
77 	static char added[10];
78 	char *cp = CM;
79 	char *dp = result;
80 	int c;
81 	int oncol = 0;
82 	int which = destline;
83 
84 	if (cp == 0) {
85 toohard:
86 		/*
87 		 * ``We don't do that under BOZO's big top''
88 		 */
89 		return ("OOPS");
90 	}
91 	added[0] = 0;
92 	while ((c = *cp++) != 0) {
93 		if (c != '%') {
94 			*dp++ = (char) c;
95 			continue;
96 		}
97 		switch (c = *cp++) {
98 
99 #ifdef CM_N
100 		case 'n':
101 			destcol ^= 0140;
102 			destline ^= 0140;
103 			goto setwhich;
104 #endif
105 
106 		case 'd':
107 			if (which < 10)
108 				goto one;
109 			if (which < 100)
110 				goto two;
111 			/*FALLTHRU*/
112 
113 		case '3':
114 			*dp++ = (which / 100) | '0';
115 			which %= 100;
116 			/*FALLTHRU*/
117 
118 		case '2':
119 two:
120 			*dp++ = which / 10 | '0';
121 one:
122 			*dp++ = which % 10 | '0';
123 swap:
124 			oncol = 1 - oncol;
125 setwhich:
126 			which = oncol ? destcol : destline;
127 			continue;
128 
129 #ifdef CM_GT
130 		case '>':
131 			if (which > *cp++)
132 				which += *cp++;
133 			else
134 				cp++;
135 			continue;
136 #endif
137 
138 		case '+':
139 			which += *cp++;
140 			/*FALLTHRU*/
141 
142 		case '.':
143 			/*
144 			 * This code is worth scratching your head at for a
145 			 * while.  The idea is that various weird things can
146 			 * happen to nulls, EOT's, tabs, and newlines by the
147 			 * tty driver, arpanet, and so on, so we don't send
148 			 * them if we can help it.
149 			 *
150 			 * Tab is taken out to get Ann Arbors to work, otherwise
151 			 * when they go to column 9 we increment which is wrong
152 			 * because bcd isn't continuous.  We should take out
153 			 * the rest too, or run the thing through more than
154 			 * once until it doesn't make any of these, but that
155 			 * would make termlib (and hence pdp-11 ex) bigger,
156 			 * and also somewhat slower.  This requires all
157 			 * programs which use termlib to stty tabs so they
158 			 * don't get expanded.  They should do this anyway
159 			 * because some terminals use ^I for other things,
160 			 * like nondestructive space.
161 			 */
162 			if (which == 0 || which == CTRL('d') || which == '\n') {
163 				if (oncol || UP)
164 					/* Assumption: backspace works */
165 					/*
166 					 * Loop needed because newline happens
167 					 * to be the successor of tab.
168 					 */
169 					do {
170 						(void) strcat(added, oncol ?
171 							(BC ? BC : "\b") : UP);
172 						which++;
173 					} while (which == '\n');
174 			}
175 			*dp++ = (char) which;
176 			goto swap;
177 
178 		case 'r':
179 			oncol = 1;
180 			goto setwhich;
181 
182 		case 'i':
183 			destcol++;
184 			destline++;
185 			which++;
186 			continue;
187 
188 		case '%':
189 			*dp++ = (char) c;
190 			continue;
191 
192 #ifdef CM_B
193 		case 'B':
194 			which = (which/10 << 4) + which%10;
195 			continue;
196 #endif
197 
198 #ifdef CM_D
199 		case 'D':
200 			which = which - 2 * (which%16);
201 			continue;
202 #endif
203 
204 		default:
205 			goto toohard;
206 		}
207 	}
208 	(void) strcpy(dp, added);
209 	return (result);
210 }
211