ncurses 5.6 - patch 20080531
[ncurses.git] / ncurses / tinfo / lib_tgoto.c
1 /****************************************************************************
2  * Copyright (c) 2000-2003,2006 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.12 2006/11/26 00:26:24 tom Exp $")
39
40 #if !PURE_TERMINFO
41 static bool
42 is_termcap(const char *string)
43 {
44     bool result = TRUE;
45
46     if (string == 0 || *string == '\0') {
47         result = FALSE;         /* tparm() handles empty strings */
48     } else {
49         while ((*string != '\0') && result) {
50             if (*string == '%') {
51                 switch (*++string) {
52                 case 'p':
53                     result = FALSE;
54                     break;
55                 case '\0':
56                     string--;
57                     break;
58                 }
59             } else if (string[0] == '$' && string[1] == '<') {
60                 result = FALSE;
61             }
62             string++;
63         }
64     }
65     return result;
66 }
67
68 static char *
69 tgoto_internal(const char *string, int x, int y)
70 {
71     static char *result;
72     static size_t length;
73
74     int swap_arg;
75     int param[3];
76     size_t used = 0;
77     size_t need = 10;
78     int *value = param;
79     bool need_BC = FALSE;
80
81     if (BC)
82         need += strlen(BC);
83
84     param[0] = y;
85     param[1] = x;
86     param[2] = 0;
87
88     while (*string != 0) {
89         if ((used + need) > length) {
90             length += (used + need);
91             if ((result = typeRealloc(char, length, result)) == 0) {
92                 length = 0;
93                 break;
94             }
95         }
96         if (*string == '%') {
97             const char *fmt = 0;
98
99             switch (*++string) {
100             case '\0':
101                 string--;
102                 break;
103             case 'd':
104                 fmt = "%d";
105                 break;
106             case '2':
107                 fmt = "%02d";
108                 *value %= 100;
109                 break;
110             case '3':
111                 fmt = "%03d";
112                 *value %= 1000;
113                 break;
114             case '+':
115                 *value += UChar(*++string);
116                 /* FALLTHRU */
117             case '.':
118                 /*
119                  * Guard against tputs() seeing a truncated string.  The
120                  * termcap documentation refers to a similar fixup for \n
121                  * and \r, but I don't see that it could work -TD
122                  */
123                 if (*value == 0) {
124                     if (BC != 0) {
125                         *value += 1;
126                         need_BC = TRUE;
127                     } else {
128                         *value = 0200;  /* tputs will treat this as \0 */
129                     }
130                 }
131                 result[used++] = *value++;
132                 break;
133             case '%':
134                 result[used++] = *string;
135                 break;
136             case 'r':
137                 swap_arg = param[0];
138                 param[0] = param[1];
139                 param[1] = swap_arg;
140                 break;
141             case 'i':
142                 param[0] += 1;
143                 param[1] += 1;
144                 break;
145             case '>':
146                 if (*value > string[1])
147                     *value += string[2];
148                 string += 2;
149                 break;
150             case 'n':           /* Datamedia 2500 */
151                 param[0] ^= 0140;
152                 param[1] ^= 0140;
153                 break;
154             case 'B':           /* BCD */
155                 *value = 16 * (*value / 10) + (*value % 10);
156                 break;
157             case 'D':           /* Reverse coding (Delta Data) */
158                 *value -= 2 * (*value % 16);
159                 break;
160             }
161             if (fmt != 0) {
162                 sprintf(result + used, fmt, *value++);
163                 used += strlen(result + used);
164                 fmt = 0;
165             }
166             if (value - param > 2) {
167                 value = param + 2;
168                 *value = 0;
169             }
170         } else {
171             result[used++] = *string;
172         }
173         string++;
174     }
175     if (result != 0) {
176         if (need_BC) {
177             strcpy(result + used, BC);
178             used += strlen(BC);
179         }
180         result[used] = '\0';
181     }
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(const char *string, int x, int y)
192 {
193     char *result;
194
195     T((T_CALLED("tgoto(%s, %d, %d)"), _nc_visbuf(string), x, y));
196 #if !PURE_TERMINFO
197     if (is_termcap(string))
198         result = tgoto_internal(string, x, y);
199     else
200 #endif
201         result = TPARM_2((NCURSES_CONST char *) string, y, x);
202     returnPtr(result);
203 }