166963Speter/****************************************************************************
2184989Srafan * Copyright (c) 2000-2006,2008 Free Software Foundation, Inc.              *
366963Speter *                                                                          *
466963Speter * Permission is hereby granted, free of charge, to any person obtaining a  *
566963Speter * copy of this software and associated documentation files (the            *
666963Speter * "Software"), to deal in the Software without restriction, including      *
766963Speter * without limitation the rights to use, copy, modify, merge, publish,      *
866963Speter * distribute, distribute with modifications, sublicense, and/or sell       *
966963Speter * copies of the Software, and to permit persons to whom the Software is    *
1066963Speter * furnished to do so, subject to the following conditions:                 *
1166963Speter *                                                                          *
1266963Speter * The above copyright notice and this permission notice shall be included  *
1366963Speter * in all copies or substantial portions of the Software.                   *
1466963Speter *                                                                          *
1566963Speter * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
1666963Speter * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
1766963Speter * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
1866963Speter * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
1966963Speter * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
2066963Speter * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
2166963Speter * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
2266963Speter *                                                                          *
2366963Speter * Except as contained in this notice, the name(s) of the above copyright   *
2466963Speter * holders shall not be used in advertising or otherwise to promote the     *
2566963Speter * sale, use or other dealings in this Software without prior written       *
2666963Speter * authorization.                                                           *
2766963Speter ****************************************************************************/
2866963Speter
2966963Speter/****************************************************************************
3066963Speter *  Author: Thomas E. Dickey                                                *
3166963Speter ****************************************************************************/
3266963Speter
3366963Speter#include <curses.priv.h>
3466963Speter
3566963Speter#include <ctype.h>
3666963Speter#include <termcap.h>
3766963Speter
38184989SrafanMODULE_ID("$Id: lib_tgoto.c,v 1.13 2008/08/16 19:29:32 tom Exp $")
3966963Speter
4066963Speter#if !PURE_TERMINFO
4166963Speterstatic bool
4266963Speteris_termcap(const char *string)
4366963Speter{
4466963Speter    bool result = TRUE;
4566963Speter
4676726Speter    if (string == 0 || *string == '\0') {
4776726Speter	result = FALSE;		/* tparm() handles empty strings */
4876726Speter    } else {
4976726Speter	while ((*string != '\0') && result) {
5076726Speter	    if (*string == '%') {
5176726Speter		switch (*++string) {
5276726Speter		case 'p':
5376726Speter		    result = FALSE;
5476726Speter		    break;
5576726Speter		case '\0':
5676726Speter		    string--;
5776726Speter		    break;
5876726Speter		}
5976726Speter	    } else if (string[0] == '$' && string[1] == '<') {
6066963Speter		result = FALSE;
6166963Speter	    }
6276726Speter	    string++;
6366963Speter	}
6466963Speter    }
6566963Speter    return result;
6666963Speter}
6766963Speter
6866963Speterstatic char *
6966963Spetertgoto_internal(const char *string, int x, int y)
7066963Speter{
7166963Speter    static char *result;
7266963Speter    static size_t length;
7366963Speter
7466963Speter    int swap_arg;
7566963Speter    int param[3];
7666963Speter    size_t used = 0;
7766963Speter    size_t need = 10;
7866963Speter    int *value = param;
7966963Speter    bool need_BC = FALSE;
8066963Speter
8166963Speter    if (BC)
8266963Speter	need += strlen(BC);
8366963Speter
8466963Speter    param[0] = y;
8566963Speter    param[1] = x;
8666963Speter    param[2] = 0;
8766963Speter
8866963Speter    while (*string != 0) {
8966963Speter	if ((used + need) > length) {
9066963Speter	    length += (used + need);
91166124Srafan	    if ((result = typeRealloc(char, length, result)) == 0) {
9266963Speter		length = 0;
9366963Speter		break;
9466963Speter	    }
9566963Speter	}
9666963Speter	if (*string == '%') {
9776726Speter	    const char *fmt = 0;
9866963Speter
9966963Speter	    switch (*++string) {
10066963Speter	    case '\0':
10166963Speter		string--;
10266963Speter		break;
10366963Speter	    case 'd':
10466963Speter		fmt = "%d";
10566963Speter		break;
10666963Speter	    case '2':
10766963Speter		fmt = "%02d";
10866963Speter		*value %= 100;
10966963Speter		break;
11066963Speter	    case '3':
11166963Speter		fmt = "%03d";
11266963Speter		*value %= 1000;
11366963Speter		break;
11466963Speter	    case '+':
11597049Speter		*value += UChar(*++string);
11666963Speter		/* FALLTHRU */
11766963Speter	    case '.':
11866963Speter		/*
11966963Speter		 * Guard against tputs() seeing a truncated string.  The
12066963Speter		 * termcap documentation refers to a similar fixup for \n
12166963Speter		 * and \r, but I don't see that it could work -TD
12266963Speter		 */
12366963Speter		if (*value == 0) {
12466963Speter		    if (BC != 0) {
12566963Speter			*value += 1;
12666963Speter			need_BC = TRUE;
12766963Speter		    } else {
12866963Speter			*value = 0200;	/* tputs will treat this as \0 */
12966963Speter		    }
13066963Speter		}
131184989Srafan		result[used++] = (char) *value++;
13266963Speter		break;
13366963Speter	    case '%':
13466963Speter		result[used++] = *string;
13566963Speter		break;
13666963Speter	    case 'r':
13766963Speter		swap_arg = param[0];
13866963Speter		param[0] = param[1];
13966963Speter		param[1] = swap_arg;
14066963Speter		break;
14166963Speter	    case 'i':
14266963Speter		param[0] += 1;
14366963Speter		param[1] += 1;
14466963Speter		break;
14566963Speter	    case '>':
14666963Speter		if (*value > string[1])
14766963Speter		    *value += string[2];
14866963Speter		string += 2;
14966963Speter		break;
15066963Speter	    case 'n':		/* Datamedia 2500 */
15166963Speter		param[0] ^= 0140;
15266963Speter		param[1] ^= 0140;
15366963Speter		break;
15466963Speter	    case 'B':		/* BCD */
15566963Speter		*value = 16 * (*value / 10) + (*value % 10);
15666963Speter		break;
15766963Speter	    case 'D':		/* Reverse coding (Delta Data) */
158166124Srafan		*value -= 2 * (*value % 16);
15966963Speter		break;
16066963Speter	    }
16166963Speter	    if (fmt != 0) {
16266963Speter		sprintf(result + used, fmt, *value++);
16366963Speter		used += strlen(result + used);
16466963Speter		fmt = 0;
16566963Speter	    }
16666963Speter	    if (value - param > 2) {
16766963Speter		value = param + 2;
16866963Speter		*value = 0;
16966963Speter	    }
17066963Speter	} else {
17166963Speter	    result[used++] = *string;
17266963Speter	}
17366963Speter	string++;
17466963Speter    }
175166124Srafan    if (result != 0) {
176166124Srafan	if (need_BC) {
177166124Srafan	    strcpy(result + used, BC);
178166124Srafan	    used += strlen(BC);
179166124Srafan	}
180166124Srafan	result[used] = '\0';
18166963Speter    }
18266963Speter    return result;
18366963Speter}
18466963Speter#endif
18566963Speter
18666963Speter/*
18766963Speter * Retained solely for upward compatibility.  Note the intentional reversing of
18866963Speter * the last two arguments when invoking tparm().
18966963Speter */
19076726SpeterNCURSES_EXPORT(char *)
191166124Srafantgoto(const char *string, int x, int y)
19266963Speter{
19366963Speter    char *result;
19466963Speter
19566963Speter    T((T_CALLED("tgoto(%s, %d, %d)"), _nc_visbuf(string), x, y));
19666963Speter#if !PURE_TERMINFO
19766963Speter    if (is_termcap(string))
19866963Speter	result = tgoto_internal(string, x, y);
19966963Speter    else
20066963Speter#endif
201166124Srafan	result = TPARM_2((NCURSES_CONST char *) string, y, x);
20266963Speter    returnPtr(result);
20366963Speter}
204