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