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