Esempio n. 1
0
NCURSES_SP_NAME(beep) (NCURSES_SP_DCL0)
{
    int res = ERR;

    T((T_CALLED("beep(%p)"), (void *) SP_PARM));

#ifdef USE_TERM_DRIVER
    if (SP_PARM != 0)
	res = CallDriver_1(SP_PARM, doBeepOrFlash, TRUE);
#else
    /* FIXME: should make sure that we are not in altchar mode */
    if (cur_term == 0) {
	res = ERR;
    } else if (bell) {
	TPUTS_TRACE("bell");
	res = putp(bell);
	_nc_flush();
    } else if (flash_screen) {
	TPUTS_TRACE("flash_screen");
	res = putp(flash_screen);
	_nc_flush();
    }
#endif

    returnCode(res);
}
Esempio n. 2
0
static void set_background_color(int bg, int  (*outc)(int))
{
	if (set_a_background)
	{
	    TPUTS_TRACE("set_a_background");
	    tputs(tparm(set_a_background, bg), 1, outc);
	}
	else
	{
	    TPUTS_TRACE("set_background");
	    tputs(tparm(set_background, toggled_colors(bg)), 1, outc);
	}
}
Esempio n. 3
0
static void set_foreground_color(int fg, int  (*outc)(int))
{
	if (set_a_foreground)
	{
	    TPUTS_TRACE("set_a_foreground");
	    tputs(tparm(set_a_foreground, fg), 1, outc);
	}
	else
	{
	    TPUTS_TRACE("set_foreground");
	    tputs(tparm(set_foreground, toggled_colors(fg)), 1, outc);
	}
}
Esempio n. 4
0
static bool set_original_colors(void)
{
	if (orig_pair != 0) {
		TPUTS_TRACE("orig_pair");
		putp(orig_pair);
		return TRUE;
	}
	else if (orig_colors != NULL)
	{
		TPUTS_TRACE("orig_colors");
		putp(orig_colors);
		return TRUE;
	}
	return FALSE;
}
Esempio n. 5
0
/*
 * Write the soft labels to the soft-key window.
 */
static void
slk_intern_refresh(SLK *slk)
{
int i;
	for (i = 0; i < slk->labcnt; i++) {
		if (slk->dirty || slk->ent[i].dirty) {
			if (slk->ent[i].visible) {
#ifdef num_labels
				if (num_labels > 0 && SLK_STDFMT)
				{
				  if (i < num_labels) {
				    TPUTS_TRACE("plab_norm");
				    putp(tparm(plab_norm, i, slk->win,slk->ent[i].form_text));
				  }
				}
				else
#endif /* num_labels */
				{
					wmove(slk->win,SLK_LINES-1,slk->ent[i].x);
					if (SP && SP->_slk)
					  wattrset(slk->win,SP->_slk->attr);
					waddnstr(slk->win,slk->ent[i].form_text, MAX_SKEY_LEN);
					/* if we simulate SLK's, it's looking much more
					   natural to use the current ATTRIBUTE also
					   for the label window */
					wattrset(slk->win,stdscr->_attrs);
				}
			}
			slk->ent[i].dirty = FALSE;
		}
	}
	slk->dirty = FALSE;

#ifdef num_labels
	if (num_labels > 0) {
	    if (slk->hidden)
	    {
		TPUTS_TRACE("label_off");
		putp(label_off);
	    }
	    else
	    {
		TPUTS_TRACE("label_on");
		putp(label_on);
	    }
	}
#endif /* num_labels */
}
Esempio n. 6
0
_nc_mvcur_resume(void)
/* what to do at initialization time and after each shellout */
{
    /* initialize screen for cursor access */
    if (enter_ca_mode) {
	TPUTS_TRACE("enter_ca_mode");
	putp(enter_ca_mode);
    }

    /*
     * Doing this here rather than in _nc_mvcur_wrap() ensures that
     * ncurses programs will see a reset scroll region even if a
     * program that messed with it died ungracefully.
     *
     * This also undoes the effects of terminal init strings that assume
     * they know the screen size.  This is useful when you're running
     * a vt100 emulation through xterm.
     */
    reset_scroll_region();
    SP->_cursrow = SP->_curscol = -1;

    /* restore cursor shape */
    if (SP->_cursor != -1) {
	int cursor = SP->_cursor;
	SP->_cursor = -1;
	curs_set(cursor);
    }
}
Esempio n. 7
0
int init_color(short color, short r, short g, short b)
{
	T((T_CALLED("init_color(%d,%d,%d,%d)"), color, r, g, b));

	if (initialize_color == NULL)
		returnCode(ERR);

	if (color < 0 || color >= COLORS)
		returnCode(ERR);
	if (r < 0 || r > 1000 || g < 0 ||  g > 1000 || b < 0 || b > 1000)
		returnCode(ERR);

	if (hue_lightness_saturation)
	    rgb2hls(r, g, b,
		      &SP->_color_table[color].red,
		      &SP->_color_table[color].green,
		      &SP->_color_table[color].blue);
	else
	{
		SP->_color_table[color].red = r;
		SP->_color_table[color].green = g;
		SP->_color_table[color].blue = b;
	}

	if (initialize_color)
	{
		TPUTS_TRACE("initialize_color");
		putp(tparm(initialize_color, color, r, g, b));
	}
	returnCode(OK);
}
Esempio n. 8
0
static void
reset_scroll_region(void)
/* Set the scroll-region to a known state (the default) */
{
    if (change_scroll_region) {
	TPUTS_TRACE("change_scroll_region");
	putp(TPARM_2(change_scroll_region, 0, screen_lines - 1));
    }
}
Esempio n. 9
0
static void
set_background_color(NCURSES_SP_DCLx int bg, NCURSES_SP_OUTC outc)
{
#ifdef USE_TERM_DRIVER
    CallDriver_3(SP_PARM, color, FALSE, bg, outc);
#else
    if (set_a_background) {
	TPUTS_TRACE("set_a_background");
	NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx
				TPARM_1(set_a_background, bg),
				1, outc);
    } else {
	TPUTS_TRACE("set_background");
	NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx
				TPARM_1(set_background, toggled_colors(bg)),
				1, outc);
    }
#endif
}
Esempio n. 10
0
/*
 * Write the soft labels to the soft-key window.
 */
static void
slk_intern_refresh(SLK * slk)
{
    int i;
    int fmt = SP->slk_format;

    for (i = 0; i < slk->labcnt; i++) {
        if (slk->dirty || slk->ent[i].dirty) {
            if (slk->ent[i].visible) {
                if (num_labels > 0 && SLK_STDFMT(fmt)) {
                    if (i < num_labels) {
                        TPUTS_TRACE("plab_norm");
                        putp(TPARM_2(plab_norm, i + 1, slk->ent[i].form_text));
                    }
                } else {
                    if (fmt == 4)
                        slk_paint_info(slk->win);
                    wmove(slk->win, SLK_LINES(fmt) - 1, slk->ent[i].ent_x);
                    if (SP->_slk) {
                        wattrset(slk->win, AttrOf(SP->_slk->attr));
                    }
                    waddstr(slk->win, slk->ent[i].form_text);
                    /* if we simulate SLK's, it's looking much more
                       natural to use the current ATTRIBUTE also
                       for the label window */
                    wattrset(slk->win, WINDOW_ATTRS(stdscr));
                }
            }
            slk->ent[i].dirty = FALSE;
        }
    }
    slk->dirty = FALSE;

    if (num_labels > 0) {
        if (slk->hidden) {
            TPUTS_TRACE("label_off");
            putp(label_off);
        } else {
            TPUTS_TRACE("label_on");
            putp(label_on);
        }
    }
}
Esempio n. 11
0
static void
set_foreground_color(NCURSES_SP_DCLx int fg, NCURSES_SP_OUTC outc)
{
#ifdef USE_TERM_DRIVER
    CallDriver_3(SP_PARM, td_color, TRUE, fg, outc);
#else
    if (set_a_foreground) {
	TPUTS_TRACE("set_a_foreground");
	NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx
				TPARM_1(set_a_foreground, fg),
				1, outc);
    } else {
	TPUTS_TRACE("set_foreground");
	NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx
				TPARM_1(set_foreground, toggled_colors(fg)),
				1, outc);
    }
#endif
}
Esempio n. 12
0
int beep(void)
{
	int res = ERR;

	T((T_CALLED("beep()")));

	/* FIXME: should make sure that we are not in altchar mode */
	if (bell) {
		TPUTS_TRACE("bell");
		res = putp(bell);
		fflush(SP->_ofp);
	} else if (flash_screen) {
		TPUTS_TRACE("flash_screen");
		res = putp(flash_screen);
		fflush(SP->_ofp);
	}

	returnCode(res);
}
NCURSES_SP_NAME(flash) (NCURSES_SP_DCL0)
{
    int res = ERR;

    T((T_CALLED("flash()")));

    /* FIXME: should make sure that we are not in altchar mode */
    if (flash_screen) {
	TPUTS_TRACE("flash_screen");
	res = putp(flash_screen);
	_nc_flush();
    } else if (bell) {
	TPUTS_TRACE("bell");
	res = putp(bell);
	_nc_flush();
    }

    returnCode(res);
}
Esempio n. 14
0
/*
 * Extension (1997/1/18) - Allow negative f/b values to set default color
 * values.
 */
int init_pair(short pair, short f, short b)
{
	T((T_CALLED("init_pair(%d,%d,%d)"), pair, f, b));

	if ((pair < 1) || (pair >= COLOR_PAIRS))
		returnCode(ERR);
	if (SP->_default_color)
	{
		if (f < 0)
			f = C_MASK;
		if (b < 0)
			b = C_MASK;
		if (f >= COLORS && f != C_MASK)
			returnCode(ERR);
		if (b >= COLORS && b != C_MASK)
			returnCode(ERR);
	}
	else
	if ((f < 0) || (f >= COLORS)
	 || (b < 0) || (b >= COLORS))
		returnCode(ERR);

	/*
	 * FIXME: when a pair's content is changed, replace its colors
	 * (if pair was initialized before a screen update is performed
	 * replacing original pair colors with the new ones)
	 */

	SP->_color_pairs[pair] = PAIR_OF(f,b);

	if (initialize_pair)
	{
	    const color_t *tp = hue_lightness_saturation ? hls_palette : cga_palette;

	    T(("initializing pair: pair = %d, fg=(%d,%d,%d), bg=(%d,%d,%d)",
	       pair,
	       tp[f].red, tp[f].green, tp[f].blue,
	       tp[b].red, tp[b].green, tp[b].blue));

	    if (initialize_pair)
	    {
		TPUTS_TRACE("initialize_pair");
		putp(tparm(initialize_pair,
			    pair,
			    tp[f].red, tp[f].green, tp[f].blue,
			    tp[b].red, tp[b].green, tp[b].blue));
	    }
	}

	returnCode(OK);
}
Esempio n. 15
0
NCURSES_SP_NAME(init_color) (NCURSES_SP_DCLx
			     short color, short r, short g, short b)
{
    int result = ERR;
    int maxcolors;

    T((T_CALLED("init_color(%p,%d,%d,%d,%d)"),
       (void *) SP_PARM,
       color,
       r, g, b));

    if (SP_PARM == 0)
	returnCode(result);

    maxcolors = MaxColors;

    if (InitColor
	&& SP_PARM->_coloron
	&& (color >= 0 && OkColorHi(color))
	&& (okRGB(r) && okRGB(g) && okRGB(b))) {

	SP_PARM->_color_table[color].init = 1;
	SP_PARM->_color_table[color].r = r;
	SP_PARM->_color_table[color].g = g;
	SP_PARM->_color_table[color].b = b;

	if (UseHlsPalette) {
	    rgb2hls(r, g, b,
		    &SP_PARM->_color_table[color].red,
		    &SP_PARM->_color_table[color].green,
		    &SP_PARM->_color_table[color].blue);
	} else {
	    SP_PARM->_color_table[color].red = r;
	    SP_PARM->_color_table[color].green = g;
	    SP_PARM->_color_table[color].blue = b;
	}

#ifdef USE_TERM_DRIVER
	CallDriver_4(SP_PARM, initcolor, color, r, g, b);
#else
	TPUTS_TRACE("initialize_color");
	putp(TPARM_4(initialize_color, color, r, g, b));
#endif
	SP_PARM->_color_defs = max(color + 1, SP_PARM->_color_defs);

	result = OK;
    }
    returnCode(result);
}
Esempio n. 16
0
/*
 * Reset the color pair, e.g., to whatever color pair 0 is.
 */
static bool
reset_color_pair(NCURSES_SP_DCL0)
{
#ifdef USE_TERM_DRIVER
    return CallDriver(SP_PARM, rescol);
#else
    bool result = FALSE;

    (void) SP_PARM;
    if (orig_pair != 0) {
	TPUTS_TRACE("orig_pair");
	putp(orig_pair);
	result = TRUE;
    }
    return result;
#endif
}
Esempio n. 17
0
NCURSES_SP_NAME(_nc_reset_colors) (NCURSES_SP_DCL0)
{
    int result = FALSE;

    T((T_CALLED("_nc_reset_colors(%p)"), (void *) SP_PARM));
    if (SP_PARM->_color_defs > 0)
	SP_PARM->_color_defs = -(SP_PARM->_color_defs);
    if (reset_color_pair(NCURSES_SP_ARG))
	result = TRUE;

#ifdef USE_TERM_DRIVER
    result = CallDriver(SP_PARM, rescolors);
#else
    if (orig_colors != 0) {
	TPUTS_TRACE("orig_colors");
	putp(orig_colors);
	result = TRUE;
    }
#endif
    returnBool(result);
}
Esempio n. 18
0
_nc_mvcur_wrap(void)
/* wrap up cursor-addressing mode */
{
    /* leave cursor at screen bottom */
    mvcur(-1, -1, screen_lines - 1, 0);

    /* set cursor to normal mode */
    if (SP->_cursor != -1)
	curs_set(1);

    if (exit_ca_mode) {
	TPUTS_TRACE("exit_ca_mode");
	putp(exit_ca_mode);
    }
    /*
     * Reset terminal's tab counter.  There's a long-time bug that
     * if you exit a "curses" program such as vi or more, tab
     * forward, and then backspace, the cursor doesn't go to the
     * right place.  The problem is that the kernel counts the
     * escape sequences that reset things as column positions.
     * Utter a \r to reset this invisibly.
     */
    _nc_outch('\r');
}
Esempio n. 19
0
void _nc_do_color(int pair, bool reverse, int (*outc)(int))
{
    short fg, bg;

    if (reverse)
    	pair = -pair;

    if (pair == 0)
    {
	if (orig_pair)
	{
	    TPUTS_TRACE("orig_pair");
	    tputs(orig_pair, 1, outc);
	}
	else if (set_color_pair)
	{
	    TPUTS_TRACE("set_color_pair");
	    tputs(tparm(set_color_pair, pair), 1, outc);
	}
	else
	{
	    set_foreground_color(COLOR_WHITE, outc);
	    set_background_color(COLOR_BLACK, outc);
	}
    }
    else
    {
	if (set_color_pair)
	{
	    TPUTS_TRACE("set_color_pair");
	    tputs(tparm(set_color_pair, pair), 1, outc);
	}
	else
	{
	    if ( pair_content(pair, &fg, &bg) == ERR)
		  return;
	    if (reverse) {
		short xx = fg;
		fg = bg;
		bg = xx;
	    }

	    T(("setting colors: pair = %d, fg = %d, bg = %d", pair, fg, bg));

	    if (fg == C_MASK || bg == C_MASK)
	    {
		if (set_original_colors() != TRUE)
		{
			if (fg == C_MASK)
				set_foreground_color(COLOR_WHITE, outc);
			if (bg == C_MASK)
				set_background_color(COLOR_BLACK, outc);
		}
	    }
	    if (fg != C_MASK)
	    {
		set_foreground_color(fg, outc);
	    }
	    if (bg != C_MASK)
	    {
		set_background_color(bg, outc);
	    }
	}
    }
}
Esempio n. 20
0
NCURSES_SP_NAME(init_pair) (NCURSES_SP_DCLx short pair, short f, short b)
{
    colorpair_t result;
    colorpair_t previous;
    int maxcolors;

    T((T_CALLED("init_pair(%p,%d,%d,%d)"), (void *) SP_PARM, pair, f, b));

    if (!ValidPair(pair))
	returnCode(ERR);

    maxcolors = MaxColors;

    previous = SP_PARM->_color_pairs[pair];
#if NCURSES_EXT_FUNCS
    if (SP_PARM->_default_color) {
	bool isDefault = FALSE;
	bool wasDefault = FALSE;
	int default_pairs = SP_PARM->_default_pairs;

	/*
	 * Map caller's color number, e.g., -1, 0, 1, .., 7, etc., into
	 * internal unsigned values which we will store in the _color_pairs[]
	 * table.
	 */
	if (isDefaultColor(f)) {
	    f = COLOR_DEFAULT;
	    isDefault = TRUE;
	} else if (!OkColorHi(f)) {
	    returnCode(ERR);
	}

	if (isDefaultColor(b)) {
	    b = COLOR_DEFAULT;
	    isDefault = TRUE;
	} else if (!OkColorHi(b)) {
	    returnCode(ERR);
	}

	/*
	 * Check if the table entry that we are going to init/update used
	 * default colors.
	 */
	if ((FORE_OF(previous) == COLOR_DEFAULT)
	    || (BACK_OF(previous) == COLOR_DEFAULT))
	    wasDefault = TRUE;

	/*
	 * Keep track of the number of entries in the color pair table which
	 * used a default color.
	 */
	if (isDefault && !wasDefault) {
	    ++default_pairs;
	} else if (wasDefault && !isDefault) {
	    --default_pairs;
	}

	/*
	 * As an extension, ncurses allows the pair number to exceed the
	 * terminal's color_pairs value for pairs using a default color.
	 *
	 * Note that updating a pair which used a default color with one
	 * that does not will decrement the count - and possibly interfere
	 * with sequentially adding new pairs.
	 */
	if (pair > (SP_PARM->_pair_count + default_pairs)) {
	    returnCode(ERR);
	}
	SP_PARM->_default_pairs = default_pairs;
    } else
#endif
    {
	if ((f < 0) || !OkColorHi(f)
	    || (b < 0) || !OkColorHi(b)
	    || (pair < 1))
	    returnCode(ERR);
    }

    /*
     * When a pair's content is changed, replace its colors (if pair was
     * initialized before a screen update is performed replacing original
     * pair colors with the new ones).
     */
    result = PAIR_OF(f, b);
    if (previous != 0
	&& previous != result) {
	int y, x;

	for (y = 0; y <= CurScreen(SP_PARM)->_maxy; y++) {
	    struct ldat *ptr = &(CurScreen(SP_PARM)->_line[y]);
	    bool changed = FALSE;
	    for (x = 0; x <= CurScreen(SP_PARM)->_maxx; x++) {
		if (GetPair(ptr->text[x]) == pair) {
		    /* Set the old cell to zero to ensure it will be
		       updated on the next doupdate() */
		    SetChar(ptr->text[x], 0, 0);
		    CHANGED_CELL(ptr, x);
		    changed = TRUE;
		}
	    }
	    if (changed)
		NCURSES_SP_NAME(_nc_make_oldhash) (NCURSES_SP_ARGx y);
	}
    }

    SP_PARM->_color_pairs[pair] = result;
    if (GET_SCREEN_PAIR(SP_PARM) == pair)
	SET_SCREEN_PAIR(SP_PARM, (chtype) (~0));	/* force attribute update */

#ifdef USE_TERM_DRIVER
    CallDriver_3(SP_PARM, initpair, pair, f, b);
#else
    if (initialize_pair && InPalette(f) && InPalette(b)) {
	const color_t *tp = DefaultPalette;

	TR(TRACE_ATTRS,
	   ("initializing pair: pair = %d, fg=(%d,%d,%d), bg=(%d,%d,%d)",
	    pair,
	    tp[f].red, tp[f].green, tp[f].blue,
	    tp[b].red, tp[b].green, tp[b].blue));

	TPUTS_TRACE("initialize_pair");
	putp(TPARM_7(initialize_pair,
		     pair,
		     tp[f].red, tp[f].green, tp[f].blue,
		     tp[b].red, tp[b].green, tp[b].blue));
    }
#endif

    returnCode(OK);
}
Esempio n. 21
0
mvcur(int yold, int xold, int ynew, int xnew)
/* optimized cursor move from (yold, xold) to (ynew, xnew) */
{
    NCURSES_CH_T oldattr;
    int code;

    TR(TRACE_CALLS | TRACE_MOVE, (T_CALLED("mvcur(%d,%d,%d,%d)"),
				  yold, xold, ynew, xnew));

    if (SP == 0) {
	code = ERR;
    } else if (yold == ynew && xold == xnew) {
	code = OK;
    } else {

	/*
	 * Most work here is rounding for terminal boundaries getting the
	 * column position implied by wraparound or the lack thereof and
	 * rolling up the screen to get ynew on the screen.
	 */
	if (xnew >= screen_columns) {
	    ynew += xnew / screen_columns;
	    xnew %= screen_columns;
	}

	/*
	 * Force restore even if msgr is on when we're in an alternate
	 * character set -- these have a strong tendency to screw up the CR &
	 * LF used for local character motions!
	 */
	oldattr = SCREEN_ATTRS(SP);
	if ((AttrOf(oldattr) & A_ALTCHARSET)
	    || (AttrOf(oldattr) && !move_standout_mode)) {
	    TR(TRACE_CHARPUT, ("turning off (%#lx) %s before move",
			       (unsigned long) AttrOf(oldattr),
			       _traceattr(AttrOf(oldattr))));
	    (void) VIDATTR(A_NORMAL, 0);
	}

	if (xold >= screen_columns) {
	    int l;

	    if (SP->_nl) {
		l = (xold + 1) / screen_columns;
		yold += l;
		if (yold >= screen_lines)
		    l -= (yold - screen_lines - 1);

		if (l > 0) {
		    if (carriage_return) {
			TPUTS_TRACE("carriage_return");
			putp(carriage_return);
		    } else
			_nc_outch('\r');
		    xold = 0;

		    while (l > 0) {
			if (newline) {
			    TPUTS_TRACE("newline");
			    putp(newline);
			} else
			    _nc_outch('\n');
			l--;
		    }
		}
	    } else {
		/*
		 * If caller set nonl(), we cannot really use newlines to
		 * position to the next row.
		 */
		xold = -1;
		yold = -1;
	    }
	}

	if (yold > screen_lines - 1)
	    yold = screen_lines - 1;
	if (ynew > screen_lines - 1)
	    ynew = screen_lines - 1;

	/* destination location is on screen now */
	code = onscreen_mvcur(yold, xold, ynew, xnew, TRUE);

	/*
	 * Restore attributes if we disabled them before moving.
	 */
	if (!SameAttrOf(oldattr, SCREEN_ATTRS(SP))) {
	    TR(TRACE_CHARPUT, ("turning on (%#lx) %s after move",
			       (unsigned long) AttrOf(oldattr),
			       _traceattr(AttrOf(oldattr))));
	    (void) VIDATTR(AttrOf(oldattr), GetPair(oldattr));
	}
    }
    returnCode(code);
}
Esempio n. 22
0
static NCURSES_INLINE int
onscreen_mvcur(int yold, int xold, int ynew, int xnew, bool ovw)
/* onscreen move from (yold, xold) to (ynew, xnew) */
{
    string_desc result;
    char buffer[OPT_SIZE];
    int tactic = 0, newcost, usecost = INFINITY;
    int t5_cr_cost;

#if defined(MAIN) || defined(NCURSES_TEST)
    struct timeval before, after;

    gettimeofday(&before, NULL);
#endif /* MAIN */

#define NullResult _nc_str_null(&result, sizeof(buffer))
#define InitResult _nc_str_init(&result, buffer, sizeof(buffer))

    /* tactic #0: use direct cursor addressing */
    if (_nc_safe_strcpy(InitResult, TPARM_2(SP->_address_cursor, ynew, xnew))) {
	tactic = 0;
	usecost = SP->_cup_cost;

#if defined(TRACE) || defined(NCURSES_TEST)
	if (!(_nc_optimize_enable & OPTIMIZE_MVCUR))
	    goto nonlocal;
#endif /* TRACE */

	/*
	 * We may be able to tell in advance that the full optimization
	 * will probably not be worth its overhead.  Also, don't try to
	 * use local movement if the current attribute is anything but
	 * A_NORMAL...there are just too many ways this can screw up
	 * (like, say, local-movement \n getting mapped to some obscure
	 * character because A_ALTCHARSET is on).
	 */
	if (yold == -1 || xold == -1 || NOT_LOCAL(yold, xold, ynew, xnew)) {
#if defined(MAIN) || defined(NCURSES_TEST)
	    if (!profiling) {
		(void) fputs("nonlocal\n", stderr);
		goto nonlocal;	/* always run the optimizer if profiling */
	    }
#else
	    goto nonlocal;
#endif /* MAIN */
	}
    }
#ifndef NO_OPTIMIZE
    /* tactic #1: use local movement */
    if (yold != -1 && xold != -1
	&& ((newcost = relative_move(NullResult, yold, xold, ynew, xnew,
				     ovw)) != INFINITY)
	&& newcost < usecost) {
	tactic = 1;
	usecost = newcost;
    }

    /* tactic #2: use carriage-return + local movement */
    if (yold != -1 && carriage_return
	&& ((newcost = relative_move(NullResult, yold, 0, ynew, xnew, ovw))
	    != INFINITY)
	&& SP->_cr_cost + newcost < usecost) {
	tactic = 2;
	usecost = SP->_cr_cost + newcost;
    }

    /* tactic #3: use home-cursor + local movement */
    if (cursor_home
	&& ((newcost = relative_move(NullResult, 0, 0, ynew, xnew, ovw)) != INFINITY)
	&& SP->_home_cost + newcost < usecost) {
	tactic = 3;
	usecost = SP->_home_cost + newcost;
    }

    /* tactic #4: use home-down + local movement */
    if (cursor_to_ll
	&& ((newcost = relative_move(NullResult, screen_lines - 1, 0, ynew,
				     xnew, ovw)) != INFINITY)
	&& SP->_ll_cost + newcost < usecost) {
	tactic = 4;
	usecost = SP->_ll_cost + newcost;
    }

    /*
     * tactic #5: use left margin for wrap to right-hand side,
     * unless strange wrap behavior indicated by xenl might hose us.
     */
    t5_cr_cost = (xold > 0 ? SP->_cr_cost : 0);
    if (auto_left_margin && !eat_newline_glitch
	&& yold > 0 && cursor_left
	&& ((newcost = relative_move(NullResult, yold - 1, screen_columns -
				     1, ynew, xnew, ovw)) != INFINITY)
	&& t5_cr_cost + SP->_cub1_cost + newcost < usecost) {
	tactic = 5;
	usecost = t5_cr_cost + SP->_cub1_cost + newcost;
    }

    /*
     * These cases are ordered by estimated relative frequency.
     */
    if (tactic)
	InitResult;
    switch (tactic) {
    case 1:
	(void) relative_move(&result, yold, xold, ynew, xnew, ovw);
	break;
    case 2:
	(void) _nc_safe_strcpy(&result, carriage_return);
	(void) relative_move(&result, yold, 0, ynew, xnew, ovw);
	break;
    case 3:
	(void) _nc_safe_strcpy(&result, cursor_home);
	(void) relative_move(&result, 0, 0, ynew, xnew, ovw);
	break;
    case 4:
	(void) _nc_safe_strcpy(&result, cursor_to_ll);
	(void) relative_move(&result, screen_lines - 1, 0, ynew, xnew, ovw);
	break;
    case 5:
	if (xold > 0)
	    (void) _nc_safe_strcat(&result, carriage_return);
	(void) _nc_safe_strcat(&result, cursor_left);
	(void) relative_move(&result, yold - 1, screen_columns - 1, ynew,
			     xnew, ovw);
	break;
    }
#endif /* !NO_OPTIMIZE */

  nonlocal:
#if defined(MAIN) || defined(NCURSES_TEST)
    gettimeofday(&after, NULL);
    diff = after.tv_usec - before.tv_usec
	+ (after.tv_sec - before.tv_sec) * 1000000;
    if (!profiling)
	(void) fprintf(stderr,
		       "onscreen: %d microsec, %f 28.8Kbps char-equivalents\n",
		       (int) diff, diff / 288);
#endif /* MAIN */

    if (usecost != INFINITY) {
	TPUTS_TRACE("mvcur");
	tputs(buffer, 1, _nc_outch);
	SP->_cursrow = ynew;
	SP->_curscol = xnew;
	return (OK);
    } else
	return (ERR);
}
Esempio n. 23
0
/*
 * Write the soft labels to the soft-key window.
 */
static void
slk_intern_refresh(SCREEN *sp)
{
    int i;
    int fmt;
    SLK *slk;
    int numlab;

    if (sp == 0)
	return;

    slk = sp->_slk;
    fmt = sp->slk_format;
    numlab = NumLabels;

    if (slk->hidden)
	return;

    for (i = 0; i < slk->labcnt; i++) {
	if (slk->dirty || slk->ent[i].dirty) {
	    if (slk->ent[i].visible) {
		if (numlab > 0 && SLK_STDFMT(fmt)) {
#ifdef USE_TERM_DRIVER
		    CallDriver_2(sp, hwlabel, i + 1, slk->ent[i].form_text);
#else
		    if (i < num_labels) {
			TPUTS_TRACE("plab_norm");
			putp(TPARM_2(plab_norm, i + 1, slk->ent[i].form_text));
		    }
#endif
		} else {
		    if (fmt == 4)
			slk_paint_info(slk->win);
		    wmove(slk->win, SLK_LINES(fmt) - 1, slk->ent[i].ent_x);
		    if (sp->_slk) {
			(void) wattrset(slk->win, AttrOf(sp->_slk->attr));
		    }
		    waddstr(slk->win, slk->ent[i].form_text);
		    /* if we simulate SLK's, it's looking much more
		       natural to use the current ATTRIBUTE also
		       for the label window */
		    (void) wattrset(slk->win, WINDOW_ATTRS(StdScreen(sp)));
		}
	    }
	    slk->ent[i].dirty = FALSE;
	}
    }
    slk->dirty = FALSE;

    if (numlab > 0) {
#ifdef USE_TERM_DRIVER
	CallDriver_1(sp, hwlabelOnOff, slk->hidden ? FALSE : TRUE);
#else
	if (slk->hidden) {
	    TPUTS_TRACE("label_off");
	    putp(label_off);
	} else {
	    TPUTS_TRACE("label_on");
	    putp(label_on);
	}
#endif
    }
}
Esempio n. 24
0
_nc_init_acs(void)
{
    chtype *fake_map = acs_map;
    chtype *real_map = SP != 0 ? SP->_acs_map : fake_map;
    int j;

    T(("initializing ACS map"));

    /*
     * If we're using this from curses (rather than terminfo), we are storing
     * the mapping information in the SCREEN struct so we can decide how to
     * render it.
     */
    if (real_map != fake_map) {
	for (j = 1; j < ACS_LEN; ++j) {
	    real_map[j] = 0;
	    fake_map[j] = A_ALTCHARSET | j;
	    SP->_screen_acs_map[j] = FALSE;
	}
    } else {
	for (j = 1; j < ACS_LEN; ++j) {
	    real_map[j] = 0;
	}
    }

    /*
     * Initializations for a UNIX-like multi-terminal environment.  Use
     * ASCII chars and count on the terminfo description to do better.
     */
    real_map['l'] = '+';	/* should be upper left corner */
    real_map['m'] = '+';	/* should be lower left corner */
    real_map['k'] = '+';	/* should be upper right corner */
    real_map['j'] = '+';	/* should be lower right corner */
    real_map['u'] = '+';	/* should be tee pointing left */
    real_map['t'] = '+';	/* should be tee pointing right */
    real_map['v'] = '+';	/* should be tee pointing up */
    real_map['w'] = '+';	/* should be tee pointing down */
    real_map['q'] = '-';	/* should be horizontal line */
    real_map['x'] = '|';	/* should be vertical line */
    real_map['n'] = '+';	/* should be large plus or crossover */
    real_map['o'] = '~';	/* should be scan line 1 */
    real_map['s'] = '_';	/* should be scan line 9 */
    real_map['`'] = '+';	/* should be diamond */
    real_map['a'] = ':';	/* should be checker board (stipple) */
    real_map['f'] = '\'';	/* should be degree symbol */
    real_map['g'] = '#';	/* should be plus/minus */
    real_map['~'] = 'o';	/* should be bullet */
    real_map[','] = '<';	/* should be arrow pointing left */
    real_map['+'] = '>';	/* should be arrow pointing right */
    real_map['.'] = 'v';	/* should be arrow pointing down */
    real_map['-'] = '^';	/* should be arrow pointing up */
    real_map['h'] = '#';	/* should be board of squares */
    real_map['i'] = '#';	/* should be lantern symbol */
    real_map['0'] = '#';	/* should be solid square block */
    /* these defaults were invented for ncurses */
    real_map['p'] = '-';	/* should be scan line 3 */
    real_map['r'] = '-';	/* should be scan line 7 */
    real_map['y'] = '<';	/* should be less-than-or-equal-to */
    real_map['z'] = '>';	/* should be greater-than-or-equal-to */
    real_map['{'] = '*';	/* should be greek pi */
    real_map['|'] = '!';	/* should be not-equal */
    real_map['}'] = 'f';	/* should be pound-sterling symbol */

#if !USE_WIDEC_SUPPORT
    if (_nc_unicode_locale() && _nc_locale_breaks_acs()) {
	acs_chars = NULL;
	ena_acs = NULL;
	enter_alt_charset_mode = NULL;
	exit_alt_charset_mode = NULL;
	set_attributes = NULL;
    }
#endif

    if (ena_acs != NULL) {
	TPUTS_TRACE("ena_acs");
	putp(ena_acs);
    }
#if NCURSES_EXT_FUNCS
    /*
     * Linux console "supports" the "PC ROM" character set by the coincidence
     * that smpch/rmpch and smacs/rmacs have the same values.  ncurses has
     * no codepage support (see SCO Merge for an example).  Outside of the
     * values defined in acsc, there are no definitions for the "PC ROM"
     * character set (assumed by some applications to be codepage 437), but we
     * allow those applications to use those codepoints.
     *
     * test/blue.c uses this feature.
     */
#define PCH_KLUDGE(a,b) (a != 0 && b != 0 && !strcmp(a,b))
    if (PCH_KLUDGE(enter_pc_charset_mode, enter_alt_charset_mode) &&
	PCH_KLUDGE(exit_pc_charset_mode, exit_alt_charset_mode)) {
	size_t i;
	for (i = 1; i < ACS_LEN; ++i) {
	    if (real_map[i] == 0) {
		real_map[i] = i;
		if (real_map != fake_map) {
		    if (SP != 0)
			SP->_screen_acs_map[i] = TRUE;
		}
	    }
	}
    }
#endif

    if (acs_chars != NULL) {
	size_t i = 0;
	size_t length = strlen(acs_chars);

	while (i + 1 < length) {
	    if (acs_chars[i] != 0 && UChar(acs_chars[i]) < ACS_LEN) {
		real_map[UChar(acs_chars[i])] = UChar(acs_chars[i + 1]) | A_ALTCHARSET;
		if (SP != 0)
		    SP->_screen_acs_map[UChar(acs_chars[i])] = TRUE;
	    }
	    i += 2;
	}
    }
#ifdef TRACE
    /* Show the equivalent mapping, noting if it does not match the
     * given attribute, whether by re-ordering or duplication.
     */
    if (_nc_tracing & TRACE_CALLS) {
	size_t n, m;
	char show[ACS_LEN * 2 + 1];
	for (n = 1, m = 0; n < ACS_LEN; n++) {
	    if (real_map[n] != 0) {
		show[m++] = (char) n;
		show[m++] = ChCharOf(real_map[n]);
	    }
	}
	show[m] = 0;
	if (acs_chars == NULL || strcmp(acs_chars, show))
	    _tracef("%s acs_chars %s",
		    (acs_chars == NULL) ? "NULL" : "READ",
		    _nc_visbuf(acs_chars));
	_tracef("%s acs_chars %s",
		(acs_chars == NULL)
		? "NULL"
		: (strcmp(acs_chars, show)
		   ? "DIFF"
		   : "SAME"),
		_nc_visbuf(show));
    }
#endif /* TRACE */
}
Esempio n. 25
0
static void
mouse_activate(SCREEN *sp, bool on)
{
    if (!on && !sp->_mouse_initialized)
	return;

    if (!_nc_mouse_init(sp))
	return;

    if (on) {

	switch (sp->_mouse_type) {
	case M_XTERM:
#if NCURSES_EXT_FUNCS
	    NCURSES_SP_NAME(keyok) (NCURSES_SP_ARGx KEY_MOUSE, on);
#endif
	    TPUTS_TRACE("xterm mouse initialization");
	    enable_xterm_mouse(sp, 1);
	    break;
#if USE_GPM_SUPPORT
	case M_GPM:
	    if (enable_gpm_mouse(sp, TRUE)) {
		sp->_mouse_fd = *(my_gpm_fd);
		T(("GPM mouse_fd %d", sp->_mouse_fd));
	    }
	    break;
#endif
#if USE_SYSMOUSE
	case M_SYSMOUSE:
	    signal(SIGUSR2, handle_sysmouse);
	    sp->_mouse_active = TRUE;
	    break;
#endif
#ifdef USE_TERM_DRIVER
	case M_TERM_DRIVER:
	    sp->_mouse_active = TRUE;
	    break;
#endif
	case M_NONE:
	    return;
	}
	/* Make runtime binding to cut down on object size of applications that
	 * do not use the mouse (e.g., 'clear').
	 */
	sp->_mouse_event = _nc_mouse_event;
	sp->_mouse_inline = _nc_mouse_inline;
	sp->_mouse_parse = _nc_mouse_parse;
	sp->_mouse_resume = _nc_mouse_resume;
	sp->_mouse_wrap = _nc_mouse_wrap;
    } else {

	switch (sp->_mouse_type) {
	case M_XTERM:
	    TPUTS_TRACE("xterm mouse deinitialization");
	    enable_xterm_mouse(sp, 0);
	    break;
#if USE_GPM_SUPPORT
	case M_GPM:
	    enable_gpm_mouse(sp, FALSE);
	    break;
#endif
#if USE_SYSMOUSE
	case M_SYSMOUSE:
	    signal(SIGUSR2, SIG_IGN);
	    sp->_mouse_active = FALSE;
	    break;
#endif
#ifdef USE_TERM_DRIVER
	case M_TERM_DRIVER:
	    sp->_mouse_active = FALSE;
	    break;
#endif
	case M_NONE:
	    return;
	}
    }
    NCURSES_SP_NAME(_nc_flush) (NCURSES_SP_ARG);
}
Esempio n. 26
0
tputs(const char *string, int affcnt, int (*outc) (int))
{
    bool always_delay;
    bool normal_delay;
    int number;
#if BSD_TPUTS
    int trailpad;
#endif /* BSD_TPUTS */

#ifdef TRACE
    char addrbuf[32];

    if (USE_TRACEF(TRACE_TPUTS)) {
	if (outc == _nc_outch)
	    (void) strcpy(addrbuf, "_nc_outch");
	else
	    (void) sprintf(addrbuf, "%p", outc);
	if (_nc_tputs_trace) {
	    _tracef("tputs(%s = %s, %d, %s) called", _nc_tputs_trace,
		    _nc_visbuf(string), affcnt, addrbuf);
	} else {
	    _tracef("tputs(%s, %d, %s) called", _nc_visbuf(string), affcnt, addrbuf);
	}
	TPUTS_TRACE(NULL);
	_nc_unlock_global(tracef);
    }
#endif /* TRACE */

    if (!VALID_STRING(string))
	return ERR;

    if (cur_term == 0) {
	always_delay = FALSE;
	normal_delay = TRUE;
    } else {
	always_delay = (string == bell) || (string == flash_screen);
	normal_delay =
	    !xon_xoff
	    && padding_baud_rate
#if NCURSES_NO_PADDING
	    && !GetNoPadding(SP)
#endif
	    && (_nc_baudrate(ospeed) >= padding_baud_rate);
    }

#if BSD_TPUTS
    /*
     * This ugly kluge deals with the fact that some ancient BSD programs
     * (like nethack) actually do the likes of tputs("50") to get delays.
     */
    trailpad = 0;
    if (isdigit(UChar(*string))) {
	while (isdigit(UChar(*string))) {
	    trailpad = trailpad * 10 + (*string - '0');
	    string++;
	}
	trailpad *= 10;
	if (*string == '.') {
	    string++;
	    if (isdigit(UChar(*string))) {
		trailpad += (*string - '0');
		string++;
	    }
	    while (isdigit(UChar(*string)))
		string++;
	}

	if (*string == '*') {
	    trailpad *= affcnt;
	    string++;
	}
    }
#endif /* BSD_TPUTS */

    my_outch = outc;		/* redirect delay_output() */
    while (*string) {
	if (*string != '$')
	    (*outc) (*string);
	else {
	    string++;
	    if (*string != '<') {
		(*outc) ('$');
		if (*string)
		    (*outc) (*string);
	    } else {
		bool mandatory;

		string++;
		if ((!isdigit(UChar(*string)) && *string != '.')
		    || !strchr(string, '>')) {
		    (*outc) ('$');
		    (*outc) ('<');
		    continue;
		}

		number = 0;
		while (isdigit(UChar(*string))) {
		    number = number * 10 + (*string - '0');
		    string++;
		}
		number *= 10;
		if (*string == '.') {
		    string++;
		    if (isdigit(UChar(*string))) {
			number += (*string - '0');
			string++;
		    }
		    while (isdigit(UChar(*string)))
			string++;
		}

		mandatory = FALSE;
		while (*string == '*' || *string == '/') {
		    if (*string == '*') {
			number *= affcnt;
			string++;
		    } else {	/* if (*string == '/') */
			mandatory = TRUE;
			string++;
		    }
		}

		if (number > 0
		    && (always_delay
			|| normal_delay
			|| mandatory))
		    delay_output(number / 10);

	    }			/* endelse (*string == '<') */
	}			/* endelse (*string == '$') */

	if (*string == '\0')
	    break;

	string++;
    }

#if BSD_TPUTS
    /*
     * Emit any BSD-style prefix padding that we've accumulated now.
     */
    if (trailpad > 0
	&& (always_delay || normal_delay))
	delay_output(trailpad / 10);
#endif /* BSD_TPUTS */

    my_outch = _nc_outch;
    return OK;
}
Esempio n. 27
0
mvcur(int yold, int xold, int ynew, int xnew)
/* optimized cursor move from (yold, xold) to (ynew, xnew) */
{
    TR(TRACE_CALLS | TRACE_MOVE, (T_CALLED("mvcur(%d,%d,%d,%d)"),
				  yold, xold, ynew, xnew));

    if (SP == 0)
	returnCode(ERR);

    if (yold == ynew && xold == xnew)
	returnCode(OK);

    /*
     * Most work here is rounding for terminal boundaries getting the
     * column position implied by wraparound or the lack thereof and
     * rolling up the screen to get ynew on the screen.
     */

    if (xnew >= screen_columns) {
	ynew += xnew / screen_columns;
	xnew %= screen_columns;
    }
    if (xold >= screen_columns) {
	int l;

	if (SP->_nl) {
	    l = (xold + 1) / screen_columns;
	    yold += l;
	    if (yold >= screen_lines)
		l -= (yold - screen_lines - 1);

	    while (l > 0) {
		if (newline) {
		    TPUTS_TRACE("newline");
		    tputs(newline, 0, _nc_outch);
		} else
		    putchar('\n');
		l--;
		if (xold > 0) {
		    if (carriage_return) {
			TPUTS_TRACE("carriage_return");
			tputs(carriage_return, 0, _nc_outch);
		    } else
			putchar('\r');
		    xold = 0;
		}
	    }
	} else {
	    /*
	     * If caller set nonl(), we cannot really use newlines to position
	     * to the next row.
	     */
	    xold = -1;
	    yold = -1;
	}
    }

    if (yold > screen_lines - 1)
	yold = screen_lines - 1;
    if (ynew > screen_lines - 1)
	ynew = screen_lines - 1;

    /* destination location is on screen now */
    returnCode(onscreen_mvcur(yold, xold, ynew, xnew, TRUE));
}
Esempio n. 28
0
NCURSES_SP_NAME(_nc_do_color) (NCURSES_SP_DCLx
			       int old_pair,
			       int pair,
			       int reverse,
			       NCURSES_SP_OUTC outc)
{
#ifdef USE_TERM_DRIVER
    CallDriver_4(SP_PARM, td_docolor, old_pair, pair, reverse, outc);
#else
    NCURSES_COLOR_T fg = COLOR_DEFAULT;
    NCURSES_COLOR_T bg = COLOR_DEFAULT;
    NCURSES_COLOR_T old_fg = -1;
    NCURSES_COLOR_T old_bg = -1;

    if (!ValidPair(pair)) {
	return;
    } else if (pair != 0) {
	if (set_color_pair) {
	    TPUTS_TRACE("set_color_pair");
	    NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx
				    TPARM_1(set_color_pair, pair),
				    1, outc);
	    return;
	} else if (SP_PARM != 0) {
	    if (pair_content((NCURSES_COLOR_T) pair, &fg, &bg) == ERR)
		return;
	}
    }

    if (old_pair >= 0
	&& SP_PARM != 0
	&& pair_content((NCURSES_COLOR_T) old_pair, &old_fg, &old_bg) != ERR) {
	if ((isDefaultColor(fg) && !isDefaultColor(old_fg))
	    || (isDefaultColor(bg) && !isDefaultColor(old_bg))) {
#if NCURSES_EXT_FUNCS
	    /*
	     * A minor optimization - but extension.  If "AX" is specified in
	     * the terminal description, treat it as screen's indicator of ECMA
	     * SGR 39 and SGR 49, and assume the two sequences are independent.
	     */
	    if (SP_PARM->_has_sgr_39_49
		&& isDefaultColor(old_bg)
		&& !isDefaultColor(old_fg)) {
		NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx "\033[39m", 1, outc);
	    } else if (SP_PARM->_has_sgr_39_49
		       && isDefaultColor(old_fg)
		       && !isDefaultColor(old_bg)) {
		NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx "\033[49m", 1, outc);
	    } else
#endif
		reset_color_pair(NCURSES_SP_ARG);
	}
    } else {
	reset_color_pair(NCURSES_SP_ARG);
    }

#if NCURSES_EXT_FUNCS
    if (isDefaultColor(fg))
	fg = (NCURSES_COLOR_T) default_fg(NCURSES_SP_ARG);
    if (isDefaultColor(bg))
	bg = (NCURSES_COLOR_T) default_bg(NCURSES_SP_ARG);
#endif

    if (reverse) {
	NCURSES_COLOR_T xx = fg;
	fg = bg;
	bg = xx;
    }

    TR(TRACE_ATTRS, ("setting colors: pair = %d, fg = %d, bg = %d", pair,
		     fg, bg));

    if (!isDefaultColor(fg)) {
	set_foreground_color(NCURSES_SP_ARGx fg, outc);
    }
    if (!isDefaultColor(bg)) {
	set_background_color(NCURSES_SP_ARGx bg, outc);
    }
#endif
}
Esempio n. 29
0
_nc_init_acs(void)
{
    T(("initializing ACS map"));

    /*
     * Initializations for a UNIX-like multi-terminal environment.  Use
     * ASCII chars and count on the terminfo description to do better.
     */
    ACS_ULCORNER = '+';		/* should be upper left corner */
    ACS_LLCORNER = '+';		/* should be lower left corner */
    ACS_URCORNER = '+';		/* should be upper right corner */
    ACS_LRCORNER = '+';		/* should be lower right corner */
    ACS_RTEE = '+';		/* should be tee pointing left */
    ACS_LTEE = '+';		/* should be tee pointing right */
    ACS_BTEE = '+';		/* should be tee pointing up */
    ACS_TTEE = '+';		/* should be tee pointing down */
    ACS_HLINE = '-';		/* should be horizontal line */
    ACS_VLINE = '|';		/* should be vertical line */
    ACS_PLUS = '+';		/* should be large plus or crossover */
    ACS_S1 = '~';		/* should be scan line 1 */
    ACS_S9 = '_';		/* should be scan line 9 */
    ACS_DIAMOND = '+';		/* should be diamond */
    ACS_CKBOARD = ':';		/* should be checker board (stipple) */
    ACS_DEGREE = '\'';		/* should be degree symbol */
    ACS_PLMINUS = '#';		/* should be plus/minus */
    ACS_BULLET = 'o';		/* should be bullet */
    ACS_LARROW = '<';		/* should be arrow pointing left */
    ACS_RARROW = '>';		/* should be arrow pointing right */
    ACS_DARROW = 'v';		/* should be arrow pointing down */
    ACS_UARROW = '^';		/* should be arrow pointing up */
    ACS_BOARD = '#';		/* should be board of squares */
    ACS_LANTERN = '#';		/* should be lantern symbol */
    ACS_BLOCK = '#';		/* should be solid square block */
    /* these defaults were invented for ncurses */
    ACS_S3 = '-';		/* should be scan line 3 */
    ACS_S7 = '-';		/* should be scan line 7 */
    ACS_LEQUAL = '<';		/* should be less-than-or-equal-to */
    ACS_GEQUAL = '>';		/* should be greater-than-or-equal-to */
    ACS_PI = '*';		/* should be greek pi */
    ACS_NEQUAL = '!';		/* should be not-equal */
    ACS_STERLING = 'f';		/* should be pound-sterling symbol */

    if (ena_acs != NULL) {
	TPUTS_TRACE("ena_acs");
	putp(ena_acs);
    }
#define ALTCHAR(c)	((chtype)(((unsigned char)(c)) | A_ALTCHARSET))

    if (acs_chars != NULL) {
	size_t i = 0;
	size_t length = strlen(acs_chars);

	while (i < length)
	    switch (acs_chars[i]) {
	    case 'l':
	    case 'm':
	    case 'k':
	    case 'j':
	    case 'u':
	    case 't':
	    case 'v':
	    case 'w':
	    case 'q':
	    case 'x':
	    case 'n':
	    case 'o':
	    case 's':
	    case '`':
	    case 'a':
	    case 'f':
	    case 'g':
	    case '~':
	    case ',':
	    case '+':
	    case '.':
	    case '-':
	    case 'h':
	    case 'i':
	    case '0':
	    case 'p':
	    case 'r':
	    case 'y':
	    case 'z':
	    case '{':
	    case '|':
	    case '}':
		acs_map[(unsigned int) acs_chars[i]] =
		    ALTCHAR(acs_chars[i + 1]);
		i++;
		/* FALLTHRU */
	    default:
		i++;
		break;
	    }
    }
#ifdef TRACE
    /* Show the equivalent mapping, noting if it does not match the
     * given attribute, whether by re-ordering or duplication.
     */
    if (_nc_tracing & TRACE_CALLS) {
	size_t n, m;
	char show[SIZEOF(acs_map) + 1];
	for (n = 1, m = 0; n < SIZEOF(acs_map); n++) {
	    if (acs_map[n] != 0) {
		show[m++] = (char) n;
		show[m++] = TextOf(acs_map[n]);
	    }
	}
	show[m] = 0;
	_tracef("%s acs_chars %s",
		(acs_chars == NULL)
		? "NULL"
		: (strcmp(acs_chars, show)
		   ? "DIFF"
		   : "SAME"),
		_nc_visbuf(show));
    }
#endif /* TRACE */
}