tscroll.c revision 1.8 1 /* $NetBSD: tscroll.c,v 1.8 2000/04/17 12:25:46 blymn 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.8 2000/04/17 12:25:46 blymn 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 #if __STDC__
85 __parse_cap (char const *cap, ...)
86 #else
87 __parse_cap (cap, va_alist)
88 const char *cap;
89 va_dcl
90 #endif
91 {
92 va_list ap;
93 static char result[MAXRETURNSIZE];
94 int c, n;
95 char *dp;
96 int have_input;
97
98 #if __STDC__
99 va_start (ap, cap);
100 #else
101 va_start(ap);
102 #endif
103 if (cap == NULL)
104 goto err;
105 #ifdef DEBUG
106 __CTRACE ("__parse_cap: cap = %s\n", cap);
107 #endif
108 have_input = 0;
109 for (dp = result; (c = *cap++) != '\0';) {
110 if (c != '%') {
111 *dp++ = c;
112 continue;
113 }
114 switch (c = *cap++) {
115 case 'n':
116 if (!have_input) {
117 n = va_arg (ap, int);
118 have_input = 1;
119 #ifdef DEBUG
120 __CTRACE ("__parse_cap: %%n, val = %d\n", n);
121 #endif
122 }
123 n ^= 0140;
124 continue;
125 case 'd':
126 if (!have_input) {
127 n = va_arg (ap, int);
128 have_input = 1;
129 #ifdef DEBUG
130 __CTRACE ("__parse_cap: %%d, val = %d\n", n);
131 #endif
132 }
133 if (n < 10)
134 goto one;
135 if (n < 100)
136 goto two;
137 /* FALLTHROUGH */
138 case '3':
139 if (!have_input) {
140 n = va_arg (ap, int);
141 have_input = 1;
142 #ifdef DEBUG
143 __CTRACE ("__parse_cap: %%3, val = %d\n", n);
144 #endif
145 }
146 *dp++ = (n / 100) | '0';
147 n %= 100;
148 /* FALLTHROUGH */
149 case '2':
150 if (!have_input) {
151 n = va_arg (ap, int);
152 have_input = 1;
153 #ifdef DEBUG
154 __CTRACE ("__parse_cap: %%2, val = %d\n", n);
155 #endif
156 }
157 two: *dp++ = n / 10 | '0';
158 one: *dp++ = n % 10 | '0';
159 have_input = 0;
160 continue;
161 case '>':
162 if (!have_input) {
163 n = va_arg (ap, int);
164 have_input = 1;
165 #ifdef DEBUG
166 __CTRACE ("__parse_cap: %%>, val = %d\n", n);
167 #endif
168 }
169 if (n > *cap++)
170 n += *cap++;
171 else
172 cap++;
173 continue;
174 case '+':
175 if (!have_input) {
176 n = va_arg (ap, int);
177 have_input = 1;
178 #ifdef DEBUG
179 __CTRACE ("__parse_cap: %%+, val = %d\n", n);
180 #endif
181 }
182 n += *cap++;
183 /* FALLTHROUGH */
184 case '.':
185 if (!have_input) {
186 n = va_arg (ap, int);
187 have_input = 1;
188 #ifdef DEBUG
189 __CTRACE ("__parse_cap: %%., val = %d\n", n);
190 #endif
191 }
192 *dp++ = n;
193 have_input = 0;
194 continue;
195 case 'i':
196 if (!have_input) {
197 n = va_arg (ap, int);
198 have_input = 1;
199 #ifdef DEBUG
200 __CTRACE ("__parse_cap: %%i, val = %d\n", n);
201 #endif
202 }
203 n++;
204 continue;
205 case '%':
206 *dp++ = c;
207 continue;
208 case 'B':
209 if (!have_input) {
210 n = va_arg (ap, int);
211 have_input = 1;
212 #ifdef DEBUG
213 __CTRACE ("__parse_cap: %%B, val = %d\n", n);
214 #endif
215 }
216 n = (n / 10 << 4) + n % 10;
217 continue;
218 case 'D':
219 if (!have_input) {
220 n = va_arg (ap, int);
221 have_input = 1;
222 #ifdef DEBUG
223 __CTRACE ("__parse_cap: %%D, val = %d\n", n);
224 #endif
225 }
226 n = n - 2 * (n % 16);
227 continue;
228 /*
229 * XXX
230 * System V terminfo files have lots of extra gunk.
231 * The only other one we've seen in capability strings
232 * is %pN, and it seems to work okay if we ignore it.
233 */
234 case 'p':
235 ++cap;
236 continue;
237 default:
238 goto err;
239 }
240 }
241 *dp = '\0';
242 va_end (ap);
243 return (result);
244
245 err: va_end (ap);
246 return ((char *) "\0");
247 }
248