xref: /netbsd/lib/libcurses/tscroll.c (revision c4a72b64)
1 /*	$NetBSD: tscroll.c,v 1.11 2002/06/26 18:14:08 christos 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 
38 #ifndef lint
39 #if 0
40 static char sccsid[] = "@(#)tscroll.c	8.4 (Berkeley) 7/27/94";
41 #else
42 __RCSID("$NetBSD: tscroll.c,v 1.11 2002/06/26 18:14:08 christos Exp $");
43 #endif
44 #endif				/* not lint */
45 
46 #include <string.h>
47 #include <stdarg.h>
48 #include "curses.h"
49 #include "curses_private.h"
50 
51 #define	MAXRETURNSIZE	64
52 
53 char   *
54 __tscroll(const char *cap, int n1, int n2)
55 {
56 	return (__parse_cap(cap, n1, n2));
57 }
58 
59 /*
60  * Routines to parse capabilities.  Derived from tgoto.c in termcap(3)
61  * library.  Cap is a string containing printf type escapes to allow
62  * scrolling.  The following escapes are defined for substituting n:
63  *
64  *	%d	as in printf
65  *	%2	like %2d
66  *	%3	like %3d
67  *	%.	gives %c hacking special case characters
68  *	%+x	like %c but adding x first
69  *
70  *	The codes below affect the state but don't use up a value.
71  *
72  *	%>xy	if value > x add y
73  *	%i	increments n
74  *	%%	gives %
75  *	%B	BCD (2 decimal digits encoded in one byte)
76  *	%D	Delta Data (backwards bcd)
77  *
78  * all other characters are ``self-inserting''.
79  *
80  * XXX:
81  *	%r	reverse order of two parameters
82  * is also defined but we don't support it (yet).
83  */
84 char	*
85 __parse_cap (char const *cap, ...)
86 {
87 	va_list	ap;
88 	static char result[MAXRETURNSIZE];
89 	int     c, n;
90 	char   *dp;
91 	int	have_input;
92 
93 	va_start (ap, cap);
94 	n = 0;			/* XXX gcc -Wuninitialized */
95 
96 	if (cap == NULL)
97 		goto err;
98 #ifdef DEBUG
99 	{
100 		int	i;
101 
102 		__CTRACE("__parse_cap: cap = ");
103 		for (i = 0; i < strlen(cap); i++)
104 			__CTRACE("%s", unctrl(cap[i]));
105 		__CTRACE("\n");
106 	}
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