Initial import from FreeBSD RELENG_4:
[dragonfly.git] / contrib / ncurses / ncurses / tinfo / lib_tgoto.c
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 }