xref: /netbsd/lib/libcurses/tscroll.c (revision bf9ec67e)
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