X-Git-Url: http://ncurses.scripts.mit.edu/?p=ncurses.git;a=blobdiff_plain;f=ncurses%2Ftty%2Ftty_update.c;h=d57f23f10ef4431b845b2706de78316506559bb5;hp=3addd02e745717ef290c12c7887c9e7b583cdc89;hb=3e37c7d3fa122563a9d88168926f61286ef30cd3;hpb=f486c68b1efe3bab5739c3f464fde6685a52bee5 diff --git a/ncurses/tty/tty_update.c b/ncurses/tty/tty_update.c index 3addd02e..d57f23f1 100644 --- a/ncurses/tty/tty_update.c +++ b/ncurses/tty/tty_update.c @@ -1,5 +1,6 @@ /**************************************************************************** - * Copyright (c) 1998-2012,2013 Free Software Foundation, Inc. * + * Copyright 2018-2019,2020 Thomas E. Dickey * + * Copyright 1998-2016,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -43,6 +44,8 @@ * *-----------------------------------------------------------------*/ +#define NEW_PAIR_INTERNAL 1 + #include #ifndef CUR @@ -82,7 +85,7 @@ #include -MODULE_ID("$Id: tty_update.c,v 1.276 2013/02/16 21:12:02 tom Exp $") +MODULE_ID("$Id: tty_update.c,v 1.307 2020/05/23 19:10:35 tom Exp $") /* * This define controls the line-breakout optimization. Every once in a @@ -114,14 +117,14 @@ static int ClrBottom(SCREEN *, int total); static void ClearScreen(SCREEN *, NCURSES_CH_T blank); static void ClrUpdate(SCREEN *); static void DelChar(SCREEN *, int count); -static void InsStr(SCREEN *, NCURSES_CH_T * line, int count); +static void InsStr(SCREEN *, NCURSES_CH_T *line, int count); static void TransformLine(SCREEN *, int const lineno); #else static int ClrBottom(int total); static void ClearScreen(NCURSES_CH_T blank); static void ClrUpdate(void); static void DelChar(int count); -static void InsStr(NCURSES_CH_T * line, int count); +static void InsStr(NCURSES_CH_T *line, int count); static void TransformLine(int const lineno); #endif @@ -179,7 +182,7 @@ position_check(NCURSES_SP_DCLx int expected_y, int expected_x, char *legend) } } #else -#define position_check(sp, expected_y, expected_x, legend) /* nothing */ +#define position_check(expected_y, expected_x, legend) /* nothing */ #endif /* POSITION_DEBUG */ /**************************************************************************** @@ -194,15 +197,23 @@ GoTo(NCURSES_SP_DCLx int const row, int const col) TR(TRACE_MOVE, ("GoTo(%p, %d, %d) from (%d, %d)", (void *) SP_PARM, row, col, SP_PARM->_cursrow, SP_PARM->_curscol)); - position_check(SP_PARM, SP_PARM->_cursrow, SP_PARM->_curscol, "GoTo"); + position_check(NCURSES_SP_ARGx + SP_PARM->_cursrow, + SP_PARM->_curscol, "GoTo"); TINFO_MVCUR(NCURSES_SP_ARGx SP_PARM->_cursrow, SP_PARM->_curscol, row, col); - position_check(SP_PARM, SP_PARM->_cursrow, SP_PARM->_curscol, "GoTo2"); + position_check(NCURSES_SP_ARGx + SP_PARM->_cursrow, + SP_PARM->_curscol, "GoTo2"); } +#if !NCURSES_WCWIDTH_GRAPHICS +#define is_wacs_value(ch) (_nc_wacs_width(ch) == 1 && wcwidth(ch) > 1) +#endif /* !NCURSES_WCWIDTH_GRAPHICS */ + static NCURSES_INLINE void PutAttrChar(NCURSES_SP_DCLx CARG_CH_T ch) { @@ -229,7 +240,7 @@ PutAttrChar(NCURSES_SP_DCLx CARG_CH_T ch) * Determine the number of character cells which the 'ch' value will use * on the screen. It should be at least one. */ - if ((chlen = wcwidth(CharOf(CHDEREF(ch)))) <= 0) { + if ((chlen = _nc_wacs_width(CharOf(CHDEREF(ch)))) <= 0) { static const NCURSES_CH_T blank = NewChar(BLANK_TEXT); /* @@ -264,8 +275,14 @@ PutAttrChar(NCURSES_SP_DCLx CARG_CH_T ch) if ((AttrOf(attr) & A_ALTCHARSET) && SP_PARM->_acs_map != 0 - && CharOfD(ch) < ACS_LEN) { + && ((CharOfD(ch) < ACS_LEN) +#if !NCURSES_WCWIDTH_GRAPHICS + || is_wacs_value(CharOfD(ch)) +#endif + )) { + int c8; my_ch = CHDEREF(ch); /* work around const param */ + c8 = CharOf(my_ch); #if USE_WIDEC_SUPPORT /* * This is crude & ugly, but works most of the time. It checks if the @@ -273,17 +290,39 @@ PutAttrChar(NCURSES_SP_DCLx CARG_CH_T ch) * character, and uses the wide-character mapping when we expect the * normal one to be broken (by mis-design ;-). */ - if (SP_PARM->_screen_acs_fix - && SP_PARM->_screen_acs_map[CharOf(my_ch)]) { - RemAttr(attr, A_ALTCHARSET); - my_ch = _nc_wacs[CharOf(my_ch)]; - } else if (SP_PARM->_screen_unicode - && !SP_PARM->_screen_acs_map[CharOf(my_ch)] - && _nc_wacs[CharOf(my_ch)].chars[0]) { - RemAttr(attr, A_ALTCHARSET); - my_ch = _nc_wacs[CharOf(my_ch)]; - } + if (SP_PARM->_screen_unicode + && _nc_wacs[CharOf(my_ch)].chars[0]) { + if (SP_PARM->_screen_acs_map[CharOf(my_ch)]) { + if (SP_PARM->_screen_acs_fix) { + RemAttr(attr, A_ALTCHARSET); + my_ch = _nc_wacs[CharOf(my_ch)]; + } + } else { + RemAttr(attr, A_ALTCHARSET); + my_ch = _nc_wacs[CharOf(my_ch)]; + } +#if !NCURSES_WCWIDTH_GRAPHICS + if (!(AttrOf(attr) & A_ALTCHARSET)) { + chlen = 1; + } +#endif /* !NCURSES_WCWIDTH_GRAPHICS */ + } else #endif + if (!SP_PARM->_screen_acs_map[c8]) { + /* + * If we found no mapping for a given alternate-character set item + * in the terminal description, attempt to use the ASCII fallback + * code which is populated in the _acs_map[] array. If that did + * not correspond to a line-drawing, etc., graphics character, the + * array entry would be empty. + */ + chtype temp = UChar(SP_PARM->_acs_map[c8]); + if (temp) { + RemAttr(attr, A_ALTCHARSET); + SetChar(my_ch, temp, AttrOf(attr)); + } + } + /* * If we (still) have alternate character set, it is the normal 8bit * flavor. The _screen_acs_map[] array tells if the character was @@ -303,6 +342,11 @@ PutAttrChar(NCURSES_SP_DCLx CARG_CH_T ch) } ch = CHREF(my_ch); } +#if USE_WIDEC_SUPPORT && !NCURSES_WCWIDTH_GRAPHICS + else if (chlen > 1 && is_wacs_value(CharOfD(ch))) { + chlen = 1; + } +#endif if (tilde_glitch && (CharOfD(ch) == L('~'))) { SetChar(tilde, L('`'), AttrOf(attr)); ch = CHREF(tilde); @@ -390,7 +434,7 @@ PutCharLR(NCURSES_SP_DCLx const ARG_CH_T ch) PutAttrChar(NCURSES_SP_ARGx ch); SP_PARM->_curscol--; - position_check(SP_PARM, + position_check(NCURSES_SP_ARGx SP_PARM->_cursrow, SP_PARM->_curscol, "exit_am_mode"); @@ -444,12 +488,12 @@ wrap_cursor(NCURSES_SP_DCL0) TR(TRACE_CHARPUT, ("turning off (%#lx) %s before wrapping", (unsigned long) AttrOf(SCREEN_ATTRS(SP_PARM)), _traceattr(AttrOf(SCREEN_ATTRS(SP_PARM))))); - (void) VIDATTR(SP_PARM, A_NORMAL, 0); + VIDPUTS(SP_PARM, A_NORMAL, 0); } } else { SP_PARM->_curscol--; } - position_check(SP_PARM, + position_check(NCURSES_SP_ARGx SP_PARM->_cursrow, SP_PARM->_curscol, "wrap_cursor"); @@ -469,7 +513,9 @@ PutChar(NCURSES_SP_DCLx const ARG_CH_T ch) if (SP_PARM->_curscol >= screen_columns(SP_PARM)) wrap_cursor(NCURSES_SP_ARG); - position_check(SP_PARM, SP_PARM->_cursrow, SP_PARM->_curscol, "PutChar"); + position_check(NCURSES_SP_ARGx + SP_PARM->_cursrow, + SP_PARM->_curscol, "PutChar"); } /* @@ -487,14 +533,15 @@ can_clear_with(NCURSES_SP_DCLx ARG_CH_T ch) if (!SP_PARM->_default_color) return FALSE; - if (SP_PARM->_default_fg != C_MASK || SP_PARM->_default_bg != C_MASK) + if (!(isDefaultColor(SP_PARM->_default_fg) && + isDefaultColor(SP_PARM->_default_bg))) return FALSE; if ((pair = GetPair(CHDEREF(ch))) != 0) { - short fg, bg; + NCURSES_COLOR_T fg, bg; if (NCURSES_SP_NAME(pair_content) (NCURSES_SP_ARGx (short) pair, &fg, &bg) == ERR - || (fg != C_MASK || bg != C_MASK)) { + || !(isDefaultColor(fg) && isDefaultColor(bg))) { return FALSE; } } @@ -520,7 +567,7 @@ can_clear_with(NCURSES_SP_DCLx ARG_CH_T ch) * This code is optimized using ech and rep. */ static int -EmitRange(NCURSES_SP_DCLx const NCURSES_CH_T * ntext, int num) +EmitRange(NCURSES_SP_DCLx const NCURSES_CH_T *ntext, int num) { int i; @@ -572,7 +619,18 @@ EmitRange(NCURSES_SP_DCLx const NCURSES_CH_T * ntext, int num) } else { return 1; /* cursor stays in the middle */ } - } else if (repeat_char && runcount > SP_PARM->_rep_cost) { + } else if (repeat_char != 0 && +#if BSD_TPUTS + !isdigit(UChar(CharOf(ntext0))) && +#endif +#if USE_WIDEC_SUPPORT + (!SP_PARM->_screen_unicode && + (CharOf(ntext0) < ((AttrOf(ntext0) & A_ALTCHARSET) + ? ACS_LEN + : 256))) && +#endif + runcount > SP_PARM->_rep_cost) { + NCURSES_CH_T temp; bool wrap_possible = (SP_PARM->_curscol + runcount >= screen_columns(SP_PARM)); int rep_count = runcount; @@ -581,11 +639,19 @@ EmitRange(NCURSES_SP_DCLx const NCURSES_CH_T * ntext, int num) rep_count--; UpdateAttrs(SP_PARM, ntext0); + temp = ntext0; + if ((AttrOf(temp) & A_ALTCHARSET) && + SP_PARM->_acs_map != 0 && + (SP_PARM->_acs_map[CharOf(temp)] & A_CHARTEXT) != 0) { + SetChar(temp, + (SP_PARM->_acs_map[CharOf(ntext0)] & A_CHARTEXT), + AttrOf(ntext0) | A_ALTCHARSET); + } NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx TPARM_2(repeat_char, - CharOf(ntext0), + CharOf(temp), rep_count), - rep_count, + 1, NCURSES_SP_NAME(_nc_outch)); SP_PARM->_curscol += rep_count; @@ -616,12 +682,12 @@ EmitRange(NCURSES_SP_DCLx const NCURSES_CH_T * ntext, int num) */ static int PutRange(NCURSES_SP_DCLx - const NCURSES_CH_T * otext, - const NCURSES_CH_T * ntext, + const NCURSES_CH_T *otext, + const NCURSES_CH_T *ntext, int row, int first, int last) { - int i, j, same; + int rc; TR(TRACE_CHARPUT, ("PutRange(%p, %p, %p, %d, %d, %d)", (void *) SP_PARM, @@ -631,6 +697,8 @@ PutRange(NCURSES_SP_DCLx if (otext != ntext && (last - first + 1) > SP_PARM->_inline_cost) { + int i, j, same; + for (j = first, same = 0; j <= last; j++) { if (!same && isWidecExt(otext[j])) continue; @@ -649,9 +717,11 @@ PutRange(NCURSES_SP_DCLx * Always return 1 for the next GoTo() after a PutRange() if we found * identical characters at end of interval */ - return (same == 0 ? i : 1); + rc = (same == 0 ? i : 1); + } else { + rc = EmitRange(NCURSES_SP_ARGx ntext + first, last - first + 1); } - return EmitRange(NCURSES_SP_ARGx ntext + first, last - first + 1); + return rc; } /* leave unbracketed here so 'indent' works */ @@ -671,9 +741,12 @@ TINFO_DOUPDATE(NCURSES_SP_DCL0) T((T_CALLED("_nc_tinfo:doupdate(%p)"), (void *) SP_PARM)); - if (SP_PARM == 0) - returnCode(ERR); + _nc_lock_global(update); + if (SP_PARM == 0) { + _nc_unlock_global(update); + returnCode(ERR); + } #if !USE_REENTRANT /* * It is "legal" but unlikely that an application could assign a new @@ -694,9 +767,10 @@ TINFO_DOUPDATE(NCURSES_SP_DCL0) if (CurScreen(SP_PARM) == 0 || NewScreen(SP_PARM) == 0 - || StdScreen(SP_PARM) == 0) + || StdScreen(SP_PARM) == 0) { + _nc_unlock_global(update); returnCode(ERR); - + } #ifdef TRACE if (USE_TRACEF(TRACE_UPDATE)) { if (CurScreen(SP_PARM)->_clear) @@ -714,7 +788,8 @@ TINFO_DOUPDATE(NCURSES_SP_DCL0) SP_PARM->_fifohold--; #if USE_SIZECHANGE - if (SP_PARM->_endwin || _nc_handle_sigwinch(SP_PARM)) { + if ((SP_PARM->_endwin == ewSuspend) + || _nc_handle_sigwinch(SP_PARM)) { /* * This is a transparent extension: XSI does not address it, * and applications need not know that ncurses can do it. @@ -727,7 +802,7 @@ TINFO_DOUPDATE(NCURSES_SP_DCL0) } #endif - if (SP_PARM->_endwin) { + if (SP_PARM->_endwin == ewSuspend) { T(("coming back from shell mode")); NCURSES_SP_NAME(reset_prog_mode) (NCURSES_SP_ARG); @@ -736,7 +811,7 @@ TINFO_DOUPDATE(NCURSES_SP_DCL0) NCURSES_SP_NAME(_nc_screen_resume) (NCURSES_SP_ARG); SP_PARM->_mouse_resume(SP_PARM); - SP_PARM->_endwin = FALSE; + SP_PARM->_endwin = ewRunning; } #if USE_TRACE_TIMES /* zero the metering machinery */ @@ -1004,6 +1079,7 @@ TINFO_DOUPDATE(NCURSES_SP_DCL0) _nc_signal_handler(TRUE); + _nc_unlock_global(update); returnCode(OK); } @@ -1075,10 +1151,10 @@ ClrUpdate(NCURSES_SP_DCL0) static void ClrToEOL(NCURSES_SP_DCLx NCURSES_CH_T blank, int needclear) { - int j; - if (CurScreen(SP_PARM) != 0 && SP_PARM->_cursrow >= 0) { + int j; + for (j = SP_PARM->_curscol; j < screen_columns(SP_PARM); j++) { if (j >= 0) { NCURSES_CH_T *cp = @@ -1149,16 +1225,17 @@ ClrToEOS(NCURSES_SP_DCLx NCURSES_CH_T blank) static int ClrBottom(NCURSES_SP_DCLx int total) { - int row; - int col; int top = total; int last = min(screen_columns(SP_PARM), NewScreen(SP_PARM)->_maxx + 1); NCURSES_CH_T blank = NewScreen(SP_PARM)->_line[total - 1].text[last - 1]; - bool ok; if (clr_eos && can_clear_with(NCURSES_SP_ARGx CHREF(blank))) { + int row; for (row = total - 1; row >= 0; row--) { + int col; + bool ok; + for (col = 0, ok = TRUE; ok && col < last; col++) { ok = (CharEq(NewScreen(SP_PARM)->_line[row].text[col], blank)); } @@ -1249,8 +1326,8 @@ TransformLine(NCURSES_SP_DCLx int const lineno) && unColor(oldLine[n]) == unColor(newLine[n])) { if (oldPair < SP_PARM->_pair_limit && newPair < SP_PARM->_pair_limit - && (SP_PARM->_color_pairs[oldPair] == - SP_PARM->_color_pairs[newPair])) { + && (isSamePair(SP_PARM->_color_pairs[oldPair], + SP_PARM->_color_pairs[newPair]))) { SetPair(oldLine[n], GetPair(newLine[n])); } } @@ -1486,9 +1563,17 @@ TransformLine(NCURSES_SP_DCLx int const lineno) if (oLastChar < nLastChar) { int m = max(nLastNonblank, oLastNonblank); #if USE_WIDEC_SUPPORT - while (isWidecExt(newLine[n + 1]) && n) { - --n; - --oLastChar; + if (n) { + while (isWidecExt(newLine[n + 1]) && n) { + --n; + --oLastChar; /* increase cost */ + } + } else if (n >= firstChar && + isWidecBase(newLine[n])) { + while (isWidecExt(newLine[n + 1])) { + ++n; + ++oLastChar; /* decrease cost */ + } } #endif GoTo(NCURSES_SP_ARGx lineno, n + 1); @@ -1508,8 +1593,9 @@ TransformLine(NCURSES_SP_DCLx int const lineno) if (DelCharCost(SP_PARM, oLastChar - nLastChar) > SP_PARM->_el_cost + nLastNonblank - (n + 1)) { if (PutRange(NCURSES_SP_ARGx oldLine, newLine, lineno, - n + 1, nLastNonblank)) - GoTo(NCURSES_SP_ARGx lineno, nLastNonblank + 1); + n + 1, nLastNonblank)) { + GoTo(NCURSES_SP_ARGx lineno, nLastNonblank + 1); + } ClrToEOL(NCURSES_SP_ARGx blank, FALSE); } else { /* @@ -1570,7 +1656,7 @@ ClearScreen(NCURSES_SP_DCLx NCURSES_CH_T blank) UpdateAttrs(SP_PARM, blank); NCURSES_PUTP2("clear_screen", clear_screen); SP_PARM->_cursrow = SP_PARM->_curscol = 0; - position_check(SP_PARM, + position_check(NCURSES_SP_ARGx SP_PARM->_cursrow, SP_PARM->_curscol, "ClearScreen"); @@ -1618,7 +1704,7 @@ ClearScreen(NCURSES_SP_DCLx NCURSES_CH_T blank) */ static void -InsStr(NCURSES_SP_DCLx NCURSES_CH_T * line, int count) +InsStr(NCURSES_SP_DCLx NCURSES_CH_T *line, int count) { TR(TRACE_UPDATE, ("InsStr(%p, %p,%d) called", (void *) SP_PARM, @@ -1631,16 +1717,16 @@ InsStr(NCURSES_SP_DCLx NCURSES_CH_T * line, int count) TPUTS_TRACE("parm_ich"); NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx TPARM_1(parm_ich, count), - count, + 1, NCURSES_SP_NAME(_nc_outch)); - while (count) { + while (count > 0) { PutAttrChar(NCURSES_SP_ARGx CHREF(*line)); line++; count--; } } else if (enter_insert_mode && exit_insert_mode) { NCURSES_PUTP2("enter_insert_mode", enter_insert_mode); - while (count) { + while (count > 0) { PutAttrChar(NCURSES_SP_ARGx CHREF(*line)); if (insert_padding) { NCURSES_PUTP2("insert_padding", insert_padding); @@ -1650,7 +1736,7 @@ InsStr(NCURSES_SP_DCLx NCURSES_CH_T * line, int count) } NCURSES_PUTP2("exit_insert_mode", exit_insert_mode); } else { - while (count) { + while (count > 0) { NCURSES_PUTP2("insert_character", insert_character); PutAttrChar(NCURSES_SP_ARGx CHREF(*line)); if (insert_padding) { @@ -1660,7 +1746,9 @@ InsStr(NCURSES_SP_DCLx NCURSES_CH_T * line, int count) count--; } } - position_check(SP_PARM, SP_PARM->_cursrow, SP_PARM->_curscol, "InsStr"); + position_check(NCURSES_SP_ARGx + SP_PARM->_cursrow, + SP_PARM->_curscol, "InsStr"); } /* @@ -1673,8 +1761,6 @@ InsStr(NCURSES_SP_DCLx NCURSES_CH_T * line, int count) static void DelChar(NCURSES_SP_DCLx int count) { - int n; - TR(TRACE_UPDATE, ("DelChar(%p, %d) called, position = (%ld,%ld)", (void *) SP_PARM, count, (long) NewScreen(SP_PARM)->_cury, @@ -1684,9 +1770,11 @@ DelChar(NCURSES_SP_DCLx int count) TPUTS_TRACE("parm_dch"); NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx TPARM_1(parm_dch, count), - count, + 1, NCURSES_SP_NAME(_nc_outch)); } else { + int n; + for (n = 0; n < count; n++) { NCURSES_PUTP2("delete_character", delete_character); } @@ -2065,16 +2153,16 @@ NCURSES_SP_NAME(_nc_screen_resume) (NCURSES_SP_DCL0) NCURSES_SP_NAME(_nc_reset_colors) (NCURSES_SP_ARG); /* restore user-defined colors, if any */ - if (SP_PARM->_color_defs < 0) { + if (SP_PARM->_color_defs < 0 && !SP_PARM->_direct_color.value) { int n; SP_PARM->_color_defs = -(SP_PARM->_color_defs); for (n = 0; n < SP_PARM->_color_defs; ++n) { if (SP_PARM->_color_table[n].init) { - NCURSES_SP_NAME(init_color) (NCURSES_SP_ARGx - (short) n, - SP_PARM->_color_table[n].r, - SP_PARM->_color_table[n].g, - SP_PARM->_color_table[n].b); + _nc_init_color(SP_PARM, + n, + SP_PARM->_color_table[n].r, + SP_PARM->_color_table[n].g, + SP_PARM->_color_table[n].b); } } }