tscroll.c revision 1.10 1 /* $NetBSD: tscroll.c,v 1.10 2002/05/26 17:01:38 wiz Exp $ */
2
3 /*-
4 * Copyright (c) 1992, 1993, 1994
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36 #include <sys/cdefs.h>
37 #include <stdarg.h>
38
39 #ifndef lint
40 #if 0
41 static char sccsid[] = "@(#)tscroll.c 8.4 (Berkeley) 7/27/94";
42 #else
43 __RCSID("$NetBSD: tscroll.c,v 1.10 2002/05/26 17:01:38 wiz Exp $");
44 #endif
45 #endif /* not lint */
46
47 #include "curses.h"
48 #include "curses_private.h"
49
50 #define MAXRETURNSIZE 64
51
52 char *
53 __tscroll(const char *cap, int n1, int n2)
54 {
55 return (__parse_cap(cap, n1, n2));
56 }
57
58 /*
59 * Routines to parse capabilities. Derived from tgoto.c in termcap(3)
60 * library. Cap is a string containing printf type escapes to allow
61 * scrolling. The following escapes are defined for substituting n:
62 *
63 * %d as in printf
64 * %2 like %2d
65 * %3 like %3d
66 * %. gives %c hacking special case characters
67 * %+x like %c but adding x first
68 *
69 * The codes below affect the state but don't use up a value.
70 *
71 * %>xy if value > x add y
72 * %i increments n
73 * %% gives %
74 * %B BCD (2 decimal digits encoded in one byte)
75 * %D Delta Data (backwards bcd)
76 *
77 * all other characters are ``self-inserting''.
78 *
79 * XXX:
80 * %r reverse order of two parameters
81 * is also defined but we don't support it (yet).
82 */
83 char *
84 __parse_cap (char const *cap, ...)
85 {
86 va_list ap;
87 static char result[MAXRETURNSIZE];
88 int c, n;
89 char *dp;
90 int have_input;
91
92 va_start (ap, cap);
93 n = 0; /* XXX gcc -Wuninitialized */
94
95 if (cap == NULL)
96 goto err;
97 #ifdef DEBUG
98 {
99 int i;
100
101 __CTRACE("__parse_cap: cap = ");
102 for (i = 0; i < strlen(cap); i++)
103 __CTRACE("%s", unctrl(cap[i]));
104 __CTRACE("\n");
105 }
106 #endif
107 have_input = 0;
108 for (dp = result; (c = *cap++) != '\0';) {
109 if (c != '%') {
110 *dp++ = c;
111 continue;
112 }
113 switch (c = *cap++) {
114 case 'n':
115 if (!have_input) {
116 n = va_arg (ap, int);
117 have_input = 1;
118 #ifdef DEBUG
119 __CTRACE ("__parse_cap: %%n, val = %d\n", n);
120 #endif
121 }
122 n ^= 0140;
123 continue;
124 case 'd':
125 if (!have_input) {
126 n = va_arg (ap, int);
127 have_input = 1;
128 #ifdef DEBUG
129 __CTRACE ("__parse_cap: %%d, val = %d\n", n);
130 #endif
131 }
132 if (n < 10)
133 goto one;
134 if (n < 100)
135 goto two;
136 /* FALLTHROUGH */
137 case '3':
138 if (!have_input) {
139 n = va_arg (ap, int);
140 have_input = 1;
141 #ifdef DEBUG
142 __CTRACE ("__parse_cap: %%3, val = %d\n", n);
143 #endif
144 }
145 *dp++ = (n / 100) | '0';
146 n %= 100;
147 /* FALLTHROUGH */
148 case '2':
149 if (!have_input) {
150 n = va_arg (ap, int);
151 have_input = 1;
152 #ifdef DEBUG
153 __CTRACE ("__parse_cap: %%2, val = %d\n", n);
154 #endif
155 }
156 two: *dp++ = n / 10 | '0';
157 one: *dp++ = n % 10 | '0';
158 have_input = 0;
159 continue;
160 case '>':
161 if (!have_input) {
162 n = va_arg (ap, int);
163 have_input = 1;
164 #ifdef DEBUG
165 __CTRACE ("__parse_cap: %%>, val = %d\n", n);
166 #endif
167 }
168 if (n > *cap++)
169 n += *cap++;
170 else
171 cap++;
172 continue;
173 case '+':
174 if (!have_input) {
175 n = va_arg (ap, int);
176 have_input = 1;
177 #ifdef DEBUG
178 __CTRACE ("__parse_cap: %%+, val = %d\n", n);
179 #endif
180 }
181 n += *cap++;
182 /* FALLTHROUGH */
183 case '.':
184 if (!have_input) {
185 n = va_arg (ap, int);
186 have_input = 1;
187 #ifdef DEBUG
188 __CTRACE ("__parse_cap: %%., val = %d\n", n);
189 #endif
190 }
191 *dp++ = n;
192 have_input = 0;
193 continue;
194 case 'i':
195 if (!have_input) {
196 n = va_arg (ap, int);
197 have_input = 1;
198 #ifdef DEBUG
199 __CTRACE ("__parse_cap: %%i, val = %d\n", n);
200 #endif
201 }
202 n++;
203 continue;
204 case '%':
205 *dp++ = c;
206 continue;
207 case 'B':
208 if (!have_input) {
209 n = va_arg (ap, int);
210 have_input = 1;
211 #ifdef DEBUG
212 __CTRACE ("__parse_cap: %%B, val = %d\n", n);
213 #endif
214 }
215 n = (n / 10 << 4) + n % 10;
216 continue;
217 case 'D':
218 if (!have_input) {
219 n = va_arg (ap, int);
220 have_input = 1;
221 #ifdef DEBUG
222 __CTRACE ("__parse_cap: %%D, val = %d\n", n);
223 #endif
224 }
225 n = n - 2 * (n % 16);
226 continue;
227 /*
228 * XXX
229 * System V terminfo files have lots of extra gunk.
230 * The only other one we've seen in capability strings
231 * is %pN, and it seems to work okay if we ignore it.
232 */
233 case 'p':
234 ++cap;
235 continue;
236 default:
237 goto err;
238 }
239 }
240 *dp = '\0';
241 va_end (ap);
242 return (result);
243
244 err: va_end (ap);
245 return ((char *) "\0");
246 }
247