xref: /openbsd/lib/libcurses/tinfo/lib_tgoto.c (revision 274d7c50)
1 /* $OpenBSD: lib_tgoto.c,v 1.6 2010/01/14 22:53:22 nicm Exp $ */
2 
3 /****************************************************************************
4  * Copyright (c) 2000-2006,2008 Free Software Foundation, Inc.              *
5  *                                                                          *
6  * Permission is hereby granted, free of charge, to any person obtaining a  *
7  * copy of this software and associated documentation files (the            *
8  * "Software"), to deal in the Software without restriction, including      *
9  * without limitation the rights to use, copy, modify, merge, publish,      *
10  * distribute, distribute with modifications, sublicense, and/or sell       *
11  * copies of the Software, and to permit persons to whom the Software is    *
12  * furnished to do so, subject to the following conditions:                 *
13  *                                                                          *
14  * The above copyright notice and this permission notice shall be included  *
15  * in all copies or substantial portions of the Software.                   *
16  *                                                                          *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
20  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
21  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
22  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
23  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
24  *                                                                          *
25  * Except as contained in this notice, the name(s) of the above copyright   *
26  * holders shall not be used in advertising or otherwise to promote the     *
27  * sale, use or other dealings in this Software without prior written       *
28  * authorization.                                                           *
29  ****************************************************************************/
30 
31 /****************************************************************************
32  *  Author: Thomas E. Dickey                                                *
33  ****************************************************************************/
34 
35 #include <curses.priv.h>
36 
37 #include <ctype.h>
38 #include <termcap.h>
39 
40 MODULE_ID("$Id: lib_tgoto.c,v 1.6 2010/01/14 22:53:22 nicm Exp $")
41 
42 #if !PURE_TERMINFO
43 static bool
44 is_termcap(const char *string)
45 {
46     bool result = TRUE;
47 
48     if (string == 0 || *string == '\0') {
49 	result = FALSE;		/* tparm() handles empty strings */
50     } else {
51 	while ((*string != '\0') && result) {
52 	    if (*string == '%') {
53 		switch (*++string) {
54 		case 'p':
55 		    result = FALSE;
56 		    break;
57 		case '\0':
58 		    string--;
59 		    break;
60 		}
61 	    } else if (string[0] == '$' && string[1] == '<') {
62 		result = FALSE;
63 	    }
64 	    string++;
65 	}
66     }
67     return result;
68 }
69 
70 static char *
71 tgoto_internal(const char *string, int x, int y)
72 {
73     static char *result;
74     static size_t length;
75 
76     int swap_arg;
77     int param[3];
78     size_t used = 0;
79     size_t need = 10;
80     size_t copied;
81     int *value = param;
82     bool need_BC = FALSE;
83 
84     if (BC)
85 	need += strlen(BC);
86 
87     param[0] = y;
88     param[1] = x;
89     param[2] = 0;
90 
91     while (*string != 0) {
92 	if ((used + need) > length) {
93 	    length += (used + need);
94 	    if ((result = typeRealloc(char, length, result)) == 0) {
95 		length = 0;
96 		break;
97 	    }
98 	}
99 	if (*string == '%') {
100 	    const char *fmt = 0;
101 
102 	    switch (*++string) {
103 	    case '\0':
104 		string--;
105 		break;
106 	    case 'd':
107 		fmt = "%d";
108 		break;
109 	    case '2':
110 		fmt = "%02d";
111 		*value %= 100;
112 		break;
113 	    case '3':
114 		fmt = "%03d";
115 		*value %= 1000;
116 		break;
117 	    case '+':
118 		*value += UChar(*++string);
119 		/* FALLTHRU */
120 	    case '.':
121 		/*
122 		 * Guard against tputs() seeing a truncated string.  The
123 		 * termcap documentation refers to a similar fixup for \n
124 		 * and \r, but I don't see that it could work -TD
125 		 */
126 		if (*value == 0) {
127 		    if (BC != 0) {
128 			*value += 1;
129 			need_BC = TRUE;
130 		    } else {
131 			*value = 0200;	/* tputs will treat this as \0 */
132 		    }
133 		}
134 		result[used++] = (char) *value++;
135 		break;
136 	    case '%':
137 		result[used++] = *string;
138 		break;
139 	    case 'r':
140 		swap_arg = param[0];
141 		param[0] = param[1];
142 		param[1] = swap_arg;
143 		break;
144 	    case 'i':
145 		param[0] += 1;
146 		param[1] += 1;
147 		break;
148 	    case '>':
149 		if (*value > string[1])
150 		    *value += string[2];
151 		string += 2;
152 		break;
153 	    case 'n':		/* Datamedia 2500 */
154 		param[0] ^= 0140;
155 		param[1] ^= 0140;
156 		break;
157 	    case 'B':		/* BCD */
158 		*value = 16 * (*value / 10) + (*value % 10);
159 		break;
160 	    case 'D':		/* Reverse coding (Delta Data) */
161 		*value -= 2 * (*value % 16);
162 		break;
163 	    }
164 	    if (fmt != 0) {
165 		snprintf(result + used, length - used, fmt, *value++);
166 		used += strlen(result + used);
167 		fmt = 0;
168 	    }
169 	    if (value - param > 2) {
170 		value = param + 2;
171 		*value = 0;
172 	    }
173 	} else {
174 	    result[used++] = *string;
175 	}
176 	string++;
177     }
178     if (result != 0) {
179 	if (need_BC) {
180 	    copied = strlcpy(result + used, BC, length - used);
181 	    if (copied < length - used)
182 		used += copied;
183 	    else
184 		used += length - used - 1;
185 	}
186 	result[used] = '\0';
187     }
188     return result;
189 }
190 #endif
191 
192 /*
193  * Retained solely for upward compatibility.  Note the intentional reversing of
194  * the last two arguments when invoking tparm().
195  */
196 NCURSES_EXPORT(char *)
197 tgoto(const char *string, int x, int y)
198 {
199     char *result;
200 
201     T((T_CALLED("tgoto(%s, %d, %d)"), _nc_visbuf(string), x, y));
202 #if !PURE_TERMINFO
203     if (is_termcap(string))
204 	result = tgoto_internal(string, x, y);
205     else
206 #endif
207 	result = TPARM_2((NCURSES_CONST char *) string, y, x);
208     returnPtr(result);
209 }
210