#include <curses.priv.h>
#include <ctype.h>
MODULE_ID("$Id: lib_addch.c,v 1.1.1.2 2002/01/03 23:53:36 jevans Exp $")
#define COLOR_MASK(ch) (~(attr_t)((ch)&A_COLOR?A_COLOR:0))
static inline NCURSES_CH_T
render_char(WINDOW *win, NCURSES_CH_T ch)
{
attr_t a = win->_attrs;
if (ISBLANK(ch) && AttrOf(ch) == A_NORMAL) {
ch = win->_nc_bkgd;
SetAttr(ch, a | (AttrOf(win->_nc_bkgd) & COLOR_MASK(a)));
} else {
a |= (AttrOf(win->_nc_bkgd) & A_ATTRIBUTES) & COLOR_MASK(a);
AddAttr(ch, (a & COLOR_MASK(AttrOf(ch))));
}
TR(TRACE_VIRTPUT, ("bkg = %s, attrs = %s -> ch = %s",
_tracech_t2(1, CHREF(win->_nc_bkgd)),
_traceattr(win->_attrs),
_tracech_t2(3, CHREF(ch))));
return (ch);
}
NCURSES_EXPORT(NCURSES_CH_T)
_nc_render(WINDOW *win, NCURSES_CH_T ch)
{
return render_char(win, ch);
}
#ifndef NDEBUG
#define CHECK_POSITION(win, x, y) \
if (y > win->_maxy \
|| x > win->_maxx \
|| y < 0 \
|| x < 0) { \
TR(TRACE_VIRTPUT, ("Alert! Win=%p _curx = %d, _cury = %d " \
"(_maxx = %d, _maxy = %d)", win, x, y, \
win->_maxx, win->_maxy)); \
return(ERR); \
}
#else
#define CHECK_POSITION(win, x, y)
#endif
static inline int
waddch_literal(WINDOW *win, NCURSES_CH_T ch)
{
int x;
struct ldat *line;
x = win->_curx;
CHECK_POSITION(win, x, win->_cury);
#if 0
if (win->_flags & _WRAPPED) {
if (x >= win->_maxx)
return (ERR);
win->_flags &= ~_WRAPPED;
}
#endif
ch = render_char(win, ch);
TR(TRACE_VIRTPUT, ("win attr = %s", _traceattr(win->_attrs)));
line = win->_line + win->_cury;
CHANGED_CELL(line, x);
line->text[x++] = ch;
if_WIDEC( {
if (wcwidth(CharOf(ch)) > 1)
AddAttr(line->text[x++], WA_NAC);
}
)
TR(TRACE_VIRTPUT, ("(%d, %d) = %s", win->_cury, x, _tracech_t(CHREF(ch))));
if (x > win->_maxx) {
win->_flags |= _WRAPPED;
if (++win->_cury > win->_regbottom) {
win->_cury = win->_regbottom;
win->_curx = win->_maxx;
if (!win->_scroll)
return (ERR);
scroll(win);
}
win->_curx = 0;
return (OK);
}
win->_curx = x;
return OK;
}
static inline int
waddch_nosync(WINDOW *win, const NCURSES_CH_T ch)
{
int x, y;
chtype t = 0;
const char *s = 0;
if ((AttrOf(ch) & A_ALTCHARSET)
|| ((t = CharOf(ch)) > 127)
|| ((s = unctrl(t))[1] == 0))
return waddch_literal(win, ch);
x = win->_curx;
y = win->_cury;
switch (t) {
case '\t':
x += (TABSIZE - (x % TABSIZE));
if ((!win->_scroll && (y == win->_regbottom))
|| (x <= win->_maxx)) {
NCURSES_CH_T blank = NewChar2(BLANK_TEXT, BLANK_ATTR);
AddAttr(blank, AttrOf(ch));
while (win->_curx < x) {
if (waddch_literal(win, blank) == ERR)
return (ERR);
}
break;
} else {
wclrtoeol(win);
win->_flags |= _WRAPPED;
if (++y > win->_regbottom) {
x = win->_maxx;
y--;
if (win->_scroll) {
scroll(win);
x = 0;
}
} else {
x = 0;
}
}
break;
case '\n':
wclrtoeol(win);
if (++y > win->_regbottom) {
y--;
if (win->_scroll)
scroll(win);
else
return (ERR);
}
case '\r':
x = 0;
win->_flags &= ~_WRAPPED;
break;
case '\b':
if (x == 0)
return (OK);
x--;
win->_flags &= ~_WRAPPED;
break;
default:
while (*s) {
NCURSES_CH_T sch;
SetChar(sch, *s++, AttrOf(ch));
if (waddch_literal(win, sch) == ERR)
return ERR;
}
return (OK);
}
win->_curx = x;
win->_cury = y;
return (OK);
}
NCURSES_EXPORT(int)
_nc_waddch_nosync(WINDOW *win, const NCURSES_CH_T c)
{
return (waddch_nosync(win, c));
}
NCURSES_EXPORT(int)
waddch(WINDOW *win, const chtype ch)
{
int code = ERR;
NCURSES_CH_T wch;
SetChar2(wch, ch);
TR(TRACE_VIRTPUT | TRACE_CCALLS, (T_CALLED("waddch(%p, %s)"), win,
_tracechtype(ch)));
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)
wechochar(WINDOW *win, const chtype ch)
{
int code = ERR;
NCURSES_CH_T wch;
SetChar2(wch, ch);
TR(TRACE_VIRTPUT | TRACE_CCALLS, (T_CALLED("wechochar(%p, %s)"), win,
_tracechtype(ch)));
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);
}
#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