]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libtermcap/tgoto.c
Copy from vendor branch. This mainly undoes most of the backing out of
[FreeBSD/FreeBSD.git] / lib / libtermcap / tgoto.c
1 /*
2  * Copyright (c) 1980, 1993
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by the University of
16  *      California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33
34 #ifndef lint
35 static char sccsid[] = "@(#)tgoto.c     8.1 (Berkeley) 6/4/93";
36 #endif /* not lint */
37
38 #include <string.h>
39 #include "termcap.h"
40
41 #define CTRL(c) ((c) & 037)
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 char *
73 tgoto(const char *CM, int destcol, int destline)
74 {
75         static char result[MAXRETURNSIZE];
76         static char added[10];
77         const char *cp = CM;
78         register char *dp = result;
79         register int c;
80         int oncol = 0;
81         register int which = destline;
82
83         if (cp == 0) {
84 toohard:
85                 /*
86                  * ``We don't do that under BOZO's big top''
87                  */
88                 return ("OOPS");
89         }
90         added[0] = 0;
91         while ( (c = *cp++) ) {
92                 if (c != '%') {
93                         if (dp >= &result[MAXRETURNSIZE])
94                                 return ("OVERFLOW");
95                         *dp++ = c;
96                         continue;
97                 }
98                 switch (c = *cp++) {
99
100 #ifdef CM_N
101                 case 'n':
102                         destcol ^= 0140;
103                         destline ^= 0140;
104                         goto setwhich;
105 #endif
106
107                 case 'd':
108                         if (which < 10)
109                                 goto one;
110                         if (which < 100)
111                                 goto two;
112                         /* fall into... */
113
114                 case '3':
115                         if (dp >= &result[MAXRETURNSIZE])
116                                 return ("OVERFLOW");
117                         *dp++ = (which / 100) | '0';
118                         which %= 100;
119                         /* fall into... */
120
121                 case '2':
122 two:
123                         if (dp >= &result[MAXRETURNSIZE])
124                                 return ("OVERFLOW");
125                         *dp++ = which / 10 | '0';
126 one:
127                         if (dp >= &result[MAXRETURNSIZE])
128                                 return ("OVERFLOW");
129                         *dp++ = which % 10 | '0';
130 swap:
131                         oncol = 1 - oncol;
132 setwhich:
133                         which = oncol ? destcol : destline;
134                         continue;
135
136 #ifdef CM_GT
137                 case '>':
138                         if (which > *cp++)
139                                 which += *cp++;
140                         else
141                                 cp++;
142                         continue;
143 #endif
144
145                 case '+':
146                         which += *cp++;
147                         /* fall into... */
148
149                 case '.':
150 casedot:
151                         /*
152                          * This code is worth scratching your head at for a
153                          * while.  The idea is that various weird things can
154                          * happen to nulls, EOT's, tabs, and newlines by the
155                          * tty driver, arpanet, and so on, so we don't send
156                          * them if we can help it.
157                          *
158                          * Tab is taken out to get Ann Arbors to work, otherwise
159                          * when they go to column 9 we increment which is wrong
160                          * because bcd isn't continuous.  We should take out
161                          * the rest too, or run the thing through more than
162                          * once until it doesn't make any of these, but that
163                          * would make termlib (and hence pdp-11 ex) bigger,
164                          * and also somewhat slower.  This requires all
165                          * programs which use termlib to stty tabs so they
166                          * don't get expanded.  They should do this anyway
167                          * because some terminals use ^I for other things,
168                          * like nondestructive space.
169                          */
170                         if (which == 0 || which == CTRL('d') || /* which == '\t' || */ which == '\n') {
171                                 if (oncol || UP) /* Assumption: backspace works */
172                                         /*
173                                          * Loop needed because newline happens
174                                          * to be the successor of tab.
175                                          */
176                                         do {
177                                                 const char *extra;
178
179                                                 extra = oncol ? (BC ? BC : "\b") : UP;
180                                                 if (strlen(added) + strlen(extra) >= 10)
181                                                         return ("OVERFLOW");
182                                                 strcat(added, extra);
183                                                 which++;
184                                         } while (which == '\n');
185                         }
186                         if (dp >= &result[MAXRETURNSIZE])
187                                 return ("OVERFLOW");
188                         *dp++ = which;
189                         goto swap;
190
191                 case 'r':
192                         oncol = 1;
193                         goto setwhich;
194
195                 case 'i':
196                         destcol++;
197                         destline++;
198                         which++;
199                         continue;
200
201                 case '%':
202                         if (dp >= &result[MAXRETURNSIZE])
203                                 return ("OVERFLOW");
204                         *dp++ = c;
205                         continue;
206
207 #ifdef CM_B
208                 case 'B':
209                         which = (which/10 << 4) + which%10;
210                         continue;
211 #endif
212
213 #ifdef CM_D
214                 case 'D':
215                         which = which - 2 * (which%16);
216                         continue;
217 #endif
218
219                 default:
220                         goto toohard;
221                 }
222         }
223         if (strlen(added) >= &result[MAXRETURNSIZE] - dp)
224                 return ("OVERFLOW");
225         strcpy(dp, added);
226         return (result);
227 }