xref: /minix3/lib/libcurses/tscroll.c (revision 51ffecc181005cb45a40108612ee28d1daaeeb86)
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