1 /**************************************************************************** 2 * Copyright (c) 2000-2006,2008 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.13 2008/08/16 19:29:32 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++] = (char) *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 } 204