1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*	Copyright (c) 1988 AT&T	*/
28 /*	  All Rights Reserved	*/
29 
30 /*
31  * University Copyright- Copyright (c) 1982, 1986, 1988
32  * The Regents of the University of California
33  * All Rights Reserved
34  *
35  * University Acknowledgment- Portions of this document are derived from
36  * software developed by the University of California, Berkeley, and its
37  * contributors.
38  */
39 
40 #pragma ident	"%Z%%M%	%I%	%E% SMI"
41 
42 /*
43     Routines to convert terminfo string parameters to termcap form.
44     Not all terminfo strings will be, or could be, converted.
45 
46     The following parameter forms will at least be handled.
47 
48 	%p1%d			-> %d
49 	%p1%2.2d		-> %2
50 	%p1%3.3d		-> %3
51 	%p1%02d			-> %2
52 	%p1%03d			-> %3
53 	%p1%c			-> %.
54 	%p1%'x'%+%c		-> %+x
55 	%i			-> %i
56 	%p2 before %p1		-> %r
57 	%p1%'x'% > %+%p1%'y'%+%;	-> % > xy
58 */
59 
60 #include "curses.h"
61 
62 /* externs from libc */
63 extern char *strcpy();
64 #if !defined(SYSV) && !defined(USG) && !defined(strchr)
65 	/* handle both Sys Vr2 and Vr3 curses */
66 #define	strchr index
67 #endif /* SYSV || USG */
68 extern char *strchr();
69 
70 #define	NULLPTR	((char *) 0)
71 
72 /*
73     lookat looks at a string such as "%p1%d" and a pattern such as "%p*%d",
74     where '*' is the only wild character. Each place that the star matches,
75     the corresponding character in the string is placed in args. If the
76     pattern matches the string, 1 is returned.
77 */
78 
79 static int
80 lookat(char *string, char *pattern, char *args)
81 {
82 	int val, pat;
83 
84 	while ((pat = *pattern++) && (val = *string++))
85 		if (pat == '*')
86 			*args++ = val;
87 		else if (val != pat)
88 			return (0);
89 	if (pat == '\0')
90 		return (1);
91 	else
92 		return (0);
93 }
94 
95 static int currentparm, otherparm, reversedparms;
96 static char *newvalue;
97 static char _newvalue[1024] = "!!! MUST CHANGE BY HAND !!!";
98 #define	BYHANDMSGLEN 27
99 
100 static void setparms();
101 
102 /*
103     Setparms() and checkparms() are used by infotocap() to make
104     sure that the parameters in the terminfo entry alternate and are
105     only '1' or '2'. If the order has been reversed, then %r is added
106     in to the new value being built.
107  */
108 
109 static void
110 setparms()
111 {
112 	currentparm = 1;
113 	otherparm = 2;
114 	reversedparms = 0;
115 	newvalue = &_newvalue[BYHANDMSGLEN];
116 	return;
117 }
118 
119 static int
120 checkparms(int arg)
121 {
122 	arg -= '0';
123 	if (arg != 1 && arg != 2)
124 		return (1);
125 	else if (arg != currentparm)
126 		if (reversedparms)
127 			return (1);
128 		else if (!reversedparms && arg == otherparm) {
129 			(void) strcpy(newvalue, "%r");
130 			newvalue += 2;
131 			reversedparms = TRUE;
132 		} else
133 			return (1);
134 	else {
135 		otherparm = currentparm;
136 		currentparm = 3 - currentparm;
137 	}
138 	return (0);
139 }
140 
141 /*
142     Infotocap looks at the string capability to see if it has any
143     stack manipulation operators. If possible, they are converted to
144     termcap form. If any operator is found that cannot be modified,
145     prepend a message to the beginning of the original value and
146     set err to 1. A pointer to the new copy of the string is returned
147     in either case.
148 */
149 
150 char
151 *infotocap(char *value, int *err)
152 {
153 	char args[4];
154 	char *savevalue;
155 
156 	*err = 0;
157 	if (strchr(value, '%') == NULLPTR)
158 		return (value);
159 
160 	setparms();
161 
162 	savevalue = value;
163 	while (*value)
164 		if (*value != '%')
165 			*newvalue++ = *value++;
166 		else if (lookat(value, "%p*%d", args)) {
167 			if (checkparms(args[0]))
168 				goto dobyhand;
169 			(void) strcpy(newvalue, "%d");
170 			newvalue += 2;
171 			value += 5;
172 		} else if (lookat(value, "%p*%02d", args)) {
173 			if (checkparms(args[0]))
174 				goto dobyhand;
175 			(void) strcpy(newvalue, "%2");
176 			newvalue += 2;
177 			value += 7;
178 		} else if (lookat(value, "%p*%03d", args)) {
179 			if (checkparms(args[0]))
180 				goto dobyhand;
181 			(void) strcpy(newvalue, "%3");
182 			newvalue += 2;
183 			value += 7;
184 		} else if (lookat(value, "%p*%2.2d", args)) {
185 			if (checkparms(args[0]))
186 				goto dobyhand;
187 			(void) strcpy(newvalue, "%2");
188 			newvalue += 2;
189 			value += 8;
190 		} else if (lookat(value, "%p*%3.3d", args)) {
191 			if (checkparms(args[0]))
192 				goto dobyhand;
193 			(void) strcpy(newvalue, "%3");
194 			newvalue += 2;
195 			value += 8;
196 		} else if (lookat(value, "%p*%c", args)) {
197 			if (checkparms(args[0]))
198 				goto dobyhand;
199 			(void) strcpy(newvalue, "%.");
200 			newvalue += 2;
201 			value += 5;
202 		} else if (lookat(value, "%p*%'*'%+%c", args)) {
203 			if (checkparms(args[0]))
204 				goto dobyhand;
205 			(void) sprintf(newvalue, "%%+%c", args[1]);
206 			newvalue += 3;
207 			value += 11;
208 		} else if (lookat(value, "%i", args)) {
209 			(void) strcpy(newvalue, "%i");
210 			newvalue += 2;
211 			value += 2;
212 		} else if (lookat(value, "%%", args)) {
213 			(void) strcpy(newvalue, "%%");
214 			newvalue += 2;
215 			value += 2;
216 		} else if (lookat(value, "p*%'*'%>%+%p*%'*'%+%;", args)) {
217 			if (args[0] != args[2])
218 				goto dobyhand;
219 			if (checkparms(args[0]))
220 				goto dobyhand;
221 			(void) sprintf(newvalue, "%%>%c%c", args[1], args[3]);
222 			newvalue += 2;
223 			value += 21;
224 		} else
225 			goto dobyhand;
226 
227 	*newvalue = '\0';
228 	return (&_newvalue[BYHANDMSGLEN]);
229 
230 dobyhand:
231 	(void) strcpy(&_newvalue[BYHANDMSGLEN], savevalue);
232 	*err = 1;
233 	return (_newvalue);
234 }
235