1 /* $OpenBSD: tgoto.c,v 1.2 2015/11/15 07:12:50 deraadt Exp $ */
2 /* $NetBSD: tgoto.c,v 1.5 1995/06/05 19:45:54 pk Exp $ */
3
4 /*
5 * Copyright (c) 1980, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33 #include <string.h>
34 #include <curses.h>
35
36 #define CTRL(c) ((c) & 037)
37
38 #define MAXRETURNSIZE 64
39
40 char *UP;
41 char *BC;
42
43 /*
44 * Routine to perform cursor addressing.
45 * CM is a string containing printf type escapes to allow
46 * cursor addressing. We start out ready to print the destination
47 * line, and switch each time we print row or column.
48 * The following escapes are defined for substituting row/column:
49 *
50 * %d as in printf
51 * %2 like %2d
52 * %3 like %3d
53 * %. gives %c hacking special case characters
54 * %+x like %c but adding x first
55 *
56 * The codes below affect the state but don't use up a value.
57 *
58 * %>xy if value > x add y
59 * %r reverses row/column
60 * %i increments row/column (for one origin indexing)
61 * %% gives %
62 * %B BCD (2 decimal digits encoded in one byte)
63 * %D Delta Data (backwards bcd)
64 *
65 * all other characters are ``self-inserting''.
66 */
67 char *
tgoto(char * CM,int destcol,int destline)68 tgoto(char *CM, int destcol, int destline)
69 {
70 static char result[MAXRETURNSIZE];
71 static char added[10];
72 char *cp = CM;
73 char *dp = result;
74 int c;
75 int oncol = 0;
76 int which = destline;
77
78 if (cp == 0) {
79 toohard:
80 /*
81 * ``We don't do that under BOZO's big top''
82 */
83 return ("OOPS");
84 }
85 added[0] = 0;
86 while ((c = *cp++) != '\0') {
87 if (c != '%') {
88 if (dp >= &result[MAXRETURNSIZE])
89 goto toohard;
90 *dp++ = c;
91 continue;
92 }
93 switch (c = *cp++) {
94
95 #ifdef CM_N
96 case 'n':
97 destcol ^= 0140;
98 destline ^= 0140;
99 goto setwhich;
100 #endif
101
102 case 'd':
103 if (which < 10)
104 goto one;
105 if (which < 100)
106 goto two;
107 /* fall into... */
108
109 case '3':
110 if (dp >= &result[MAXRETURNSIZE])
111 goto toohard;
112 *dp++ = (which / 100) | '0';
113 which %= 100;
114 /* fall into... */
115
116 case '2':
117 two:
118 if (dp >= &result[MAXRETURNSIZE])
119 goto toohard;
120 *dp++ = which / 10 | '0';
121 one:
122 if (dp >= &result[MAXRETURNSIZE])
123 goto toohard;
124 *dp++ = which % 10 | '0';
125 swap:
126 oncol = 1 - oncol;
127 setwhich:
128 which = oncol ? destcol : destline;
129 continue;
130
131 #ifdef CM_GT
132 case '>':
133 if (which > *cp++)
134 which += *cp++;
135 else
136 cp++;
137 continue;
138 #endif
139
140 case '+':
141 which += *cp++;
142 /* fall into... */
143
144 case '.':
145 /*
146 * This code is worth scratching your head at for a
147 * while. The idea is that various weird things can
148 * happen to nulls, EOT's, tabs, and newlines by the
149 * tty driver, arpanet, and so on, so we don't send
150 * them if we can help it.
151 *
152 * Tab is taken out to get Ann Arbors to work, otherwise
153 * when they go to column 9 we increment which is wrong
154 * because bcd isn't continuous. We should take out
155 * the rest too, or run the thing through more than
156 * once until it doesn't make any of these, but that
157 * would make termlib (and hence pdp-11 ex) bigger,
158 * and also somewhat slower. This requires all
159 * programs which use termlib to stty tabs so they
160 * don't get expanded. They should do this anyway
161 * because some terminals use ^I for other things,
162 * like nondestructive space.
163 */
164 if ((which == 0 || which == CTRL('d') || which == '\n')
165 && (oncol || UP)) /* Assumption: backspace works */
166 /*
167 * Loop needed because newline happens
168 * to be the successor of tab.
169 */
170 do {
171 if (strlcat(added, oncol ?
172 (BC ? BC : "\b") : UP,
173 sizeof(added)) >= sizeof(added))
174 goto toohard;
175 which++;
176 } while (which == '\n');
177 if (dp >= &result[MAXRETURNSIZE])
178 goto toohard;
179 *dp++ = which;
180 goto swap;
181
182 case 'r':
183 oncol = 1;
184 goto setwhich;
185
186 case 'i':
187 destcol++;
188 destline++;
189 which++;
190 continue;
191
192 case '%':
193 if (dp >= &result[MAXRETURNSIZE])
194 goto toohard;
195 *dp++ = c;
196 continue;
197
198 #ifdef CM_B
199 case 'B':
200 which = (which/10 << 4) + which%10;
201 continue;
202 #endif
203
204 #ifdef CM_D
205 case 'D':
206 which = which - 2 * (which%16);
207 continue;
208 #endif
209
210 default:
211 goto toohard;
212 }
213 }
214 if (strlcpy(dp, added, sizeof(result) - (dp - result))
215 >= sizeof(result) - (dp - result))
216 goto toohard;
217 return (result);
218 }
219