xref: /openbsd-src/lib/libcurses/tinfo/lib_tgoto.c (revision b2ea75c1b17e1a9a339660e7ed45cd24946b230e)
1 /*	$OpenBSD: lib_tgoto.c,v 1.2 2001/01/22 18:01:53 millert Exp $	*/
2 
3 /****************************************************************************
4  * Copyright (c) 2000 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("$From: lib_tgoto.c,v 1.5 2000/12/10 01:33:16 tom 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     int *value = param;
81     bool need_BC = FALSE;
82 
83     if (BC)
84 	need += strlen(BC);
85 
86     param[0] = y;
87     param[1] = x;
88     param[2] = 0;
89 
90     while (*string != 0) {
91 	if ((used + need) > length) {
92 	    length += (used + need);
93 	    if ((result = _nc_doalloc(result, length)) == 0) {
94 		length = 0;
95 		break;
96 	    }
97 	}
98 	if (*string == '%') {
99 	    char *fmt = 0;
100 
101 	    switch (*++string) {
102 	    case '\0':
103 		string--;
104 		break;
105 	    case 'd':
106 		fmt = "%d";
107 		break;
108 	    case '2':
109 		fmt = "%02d";
110 		*value %= 100;
111 		break;
112 	    case '3':
113 		fmt = "%03d";
114 		*value %= 1000;
115 		break;
116 	    case '+':
117 		*value += CharOf(*++string);
118 		/* FALLTHRU */
119 	    case '.':
120 		/*
121 		 * Guard against tputs() seeing a truncated string.  The
122 		 * termcap documentation refers to a similar fixup for \n
123 		 * and \r, but I don't see that it could work -TD
124 		 */
125 		if (*value == 0) {
126 		    if (BC != 0) {
127 			*value += 1;
128 			need_BC = TRUE;
129 		    } else {
130 			*value = 0200;	/* tputs will treat this as \0 */
131 		    }
132 		}
133 		result[used++] = *value++;
134 		break;
135 	    case '%':
136 		result[used++] = *string;
137 		break;
138 	    case 'r':
139 		swap_arg = param[0];
140 		param[0] = param[1];
141 		param[1] = swap_arg;
142 		break;
143 	    case 'i':
144 		param[0] += 1;
145 		param[1] += 1;
146 		break;
147 	    case '>':
148 		if (*value > string[1])
149 		    *value += string[2];
150 		string += 2;
151 		break;
152 	    case 'n':		/* Datamedia 2500 */
153 		param[0] ^= 0140;
154 		param[1] ^= 0140;
155 		break;
156 	    case 'B':		/* BCD */
157 		*value = 16 * (*value / 10) + (*value % 10);
158 		break;
159 	    case 'D':		/* Reverse coding (Delta Data) */
160 		*value -= 2 * (*value / 16);
161 		break;
162 	    }
163 	    if (fmt != 0) {
164 		sprintf(result + used, fmt, *value++);
165 		used += strlen(result + used);
166 		fmt = 0;
167 	    }
168 	    if (value - param > 2) {
169 		value = param + 2;
170 		*value = 0;
171 	    }
172 	} else {
173 	    result[used++] = *string;
174 	}
175 	string++;
176     }
177     if (need_BC) {
178 	strcpy(result + used, BC);
179 	used += strlen(BC);
180     }
181     result[used] = '\0';
182     return result;
183 }
184 #endif
185 
186 /*
187  * Retained solely for upward compatibility.  Note the intentional reversing of
188  * the last two arguments when invoking tparm().
189  */
190 NCURSES_EXPORT(char *)
191 tgoto
192 (const char *string, int x, int y)
193 {
194     char *result;
195 
196     T((T_CALLED("tgoto(%s, %d, %d)"), _nc_visbuf(string), x, y));
197 #if !PURE_TERMINFO
198     if (is_termcap(string))
199 	result = tgoto_internal(string, x, y);
200     else
201 #endif
202 	result = tparm((NCURSES_CONST char *) string, y, x);
203     returnPtr(result);
204 }
205