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