X-Git-Url: http://ncurses.scripts.mit.edu/?a=blobdiff_plain;f=ncurses%2Fbase%2Flib_addch.c;h=63b63bdd20e63dbcf27d96aebbbdc0b683c85627;hb=a8987e73ec254703634802b4f7ee30d3a485524d;hp=5b41fedf3a2c851bfb3b47b0b881531104804fe0;hpb=46722468f47c2b77b3987729b4bcf2321cccfd01;p=ncurses.git diff --git a/ncurses/base/lib_addch.c b/ncurses/base/lib_addch.c index 5b41fedf..63b63bdd 100644 --- a/ncurses/base/lib_addch.c +++ b/ncurses/base/lib_addch.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2001,2002 Free Software Foundation, Inc. * + * Copyright (c) 1998-2003,2004 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 * @@ -36,7 +36,7 @@ #include #include -MODULE_ID("$Id: lib_addch.c,v 1.68 2002/09/28 17:48:13 tom Exp $") +MODULE_ID("$Id: lib_addch.c,v 1.80 2004/02/07 18:20:46 tom Exp $") /* * Ugly microtweaking alert. Everything from here to end of module is @@ -68,7 +68,7 @@ render_char(WINDOW *win, NCURSES_CH_T ch) AddAttr(ch, (a & COLOR_MASK(AttrOf(ch)))); } - TR(TRACE_VIRTPUT, ("bkg = %s, attrs = %s -> ch = %s", + TR(TRACE_VIRTPUT, ("render_char bkg %s, attrs %s -> ch %s", _tracech_t2(1, CHREF(win->_nc_bkgd)), _traceattr(win->_attrs), _tracech_t2(3, CHREF(ch)))); @@ -99,15 +99,21 @@ _nc_render(WINDOW *win, NCURSES_CH_T ch) #define CHECK_POSITION(win, x, y) /* nothing */ #endif -static inline int +static +#if !USE_WIDEC_SUPPORT /* cannot be inline if it is recursive */ + inline +#endif +int waddch_literal(WINDOW *win, NCURSES_CH_T ch) { int x; + int y; struct ldat *line; x = win->_curx; + y = win->_cury; - CHECK_POSITION(win, x, win->_cury); + CHECK_POSITION(win, x, y); /* * If we're trying to add a character at the lower-right corner more @@ -122,20 +128,71 @@ waddch_literal(WINDOW *win, NCURSES_CH_T ch) #endif ch = render_char(win, ch); - TR(TRACE_VIRTPUT, ("win attr = %s", _traceattr(win->_attrs))); - line = win->_line + win->_cury; + line = win->_line + y; CHANGED_CELL(line, x); + /* + * Build up multibyte characters until we have a wide-character. + */ + if_WIDEC({ + if (WINDOW_EXT(win, addch_used) == 0 && Charable(ch)) { + WINDOW_EXT(win, addch_used) = 0; + } else { + char *buffer = WINDOW_EXT(win, addch_work); + int len; + mbstate_t state; + wchar_t result; + + if ((WINDOW_EXT(win, addch_used) != 0) && + (WINDOW_EXT(win, addch_x) != x || + WINDOW_EXT(win, addch_y) != y)) { + /* discard the incomplete multibyte character */ + WINDOW_EXT(win, addch_used) = 0; + } + WINDOW_EXT(win, addch_x) = x; + WINDOW_EXT(win, addch_y) = y; + + memset(&state, 0, sizeof(state)); + buffer[WINDOW_EXT(win, addch_used)] = CharOf(ch); + WINDOW_EXT(win, addch_used) += 1; + buffer[WINDOW_EXT(win, addch_used)] = '\0'; + if ((len = mbrtowc(&result, + buffer, + WINDOW_EXT(win, addch_used), &state)) > 0) { + attr_t attrs = AttrOf(ch); + SetChar(ch, result, attrs); + WINDOW_EXT(win, addch_used) = 0; + if (CharOf(ch) < 256) { + const char *s = unctrl(CharOf(ch)); + if (s[1] != 0) { + return waddstr(win, s); + } + } + } else { + if (len == -1) { + /* + * An error occurred. We could either discard everything, + * or assume that the error was in the previous input. + * Try the latter. + */ + TR(TRACE_VIRTPUT, ("Alert! mbrtowc returns error")); + buffer[0] = CharOf(ch); + WINDOW_EXT(win, addch_used) = 1; + } + return OK; + } + } + }); + /* * Handle non-spacing characters */ if_WIDEC({ if (wcwidth(CharOf(ch)) == 0) { int i; - int y; - if ((x > 0 && ((y = win->_cury) >= 0)) + if ((x > 0 && y >= 0) || ((y = win->_cury - 1) >= 0 && (x = win->_maxx) > 0)) { wchar_t *chars = (win->_line[y].text[x - 1].chars); @@ -154,8 +211,18 @@ waddch_literal(WINDOW *win, NCURSES_CH_T ch) * Provide for multi-column characters */ if_WIDEC({ - if (wcwidth(CharOf(ch)) > 1) + int len = wcwidth(CharOf(ch)); + while (len-- > 1) { + if (x + (len - 1) > win->_maxx) { + NCURSES_CH_T blank = NewChar2(BLANK_TEXT, BLANK_ATTR); + AddAttr(blank, AttrOf(ch)); + if (waddch_literal(win, blank) != ERR) + return waddch_literal(win, ch); + return ERR; + } AddAttr(line->text[x++], WA_NAC); + TR(TRACE_VIRTPUT, ("added NAC %d", x - 1)); + } } testwrapping: ); @@ -192,14 +259,28 @@ waddch_nosync(WINDOW *win, const NCURSES_CH_T ch) /* the workhorse function -- add a character to the given window */ { int x, y; - chtype t = 0; + chtype t = CharOf(ch); const char *s = 0; + /* + * If we are using the alternate character set, forget about locale. + * Otherwise, if unctrl() returns a single-character or the locale + * claims the code is printable, treat it that way. + */ if ((AttrOf(ch) & A_ALTCHARSET) - || ((t = CharOf(ch)) > 127) - || ((s = unctrl(t))[1] == 0)) + || ((s = unctrl(t))[1] == 0 || + ( + isprint(t) +#if USE_WIDEC_SUPPORT + || WINDOW_EXT(win, addch_used) +#endif + ))) return waddch_literal(win, ch); + /* + * Handle carriage control and other codes that are not printable, or are + * known to expand to more than one character according to unctrl(). + */ x = win->_curx; y = win->_cury; @@ -325,41 +406,3 @@ wechochar(WINDOW *win, const chtype ch) TR(TRACE_VIRTPUT | TRACE_CCALLS, (T_RETURN("%d"), code)); return (code); } - -#if USE_WIDEC_SUPPORT -NCURSES_EXPORT(int) -wadd_wch(WINDOW *win, const cchar_t * wch) -{ - int code = ERR; - - TR(TRACE_VIRTPUT | TRACE_CCALLS, (T_CALLED("wadd_wch(%p, %s)"), win, - _tracech_t(wch))); - - if (win && (waddch_nosync(win, *wch) != ERR)) { - _nc_synchook(win); - code = OK; - } - - TR(TRACE_VIRTPUT | TRACE_CCALLS, (T_RETURN("%d"), code)); - return (code); -} - -NCURSES_EXPORT(int) -wecho_wchar(WINDOW *win, const cchar_t * wch) -{ - int code = ERR; - - TR(TRACE_VIRTPUT | TRACE_CCALLS, (T_CALLED("wecho_wchar(%p, %s)"), win, - _tracech_t(wch))); - - if (win && (waddch_nosync(win, *wch) != ERR)) { - bool save_immed = win->_immed; - win->_immed = TRUE; - _nc_synchook(win); - win->_immed = save_immed; - code = OK; - } - TR(TRACE_VIRTPUT | TRACE_CCALLS, (T_RETURN("%d"), code)); - return (code); -} -#endif /* USE_WIDEC_SUPPORT */