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