+ if (ISBLANK(ch)
+ && AttrOf(ch) == A_NORMAL
+ && pair == 0) {
+ /* color/pair in attrs has precedence over bkgrnd */
+ ch = win->_nc_bkgd;
+ SetAttr(ch, a | AttrOf(win->_nc_bkgd));
+ if ((pair = GET_WINDOW_PAIR(win)) == 0)
+ pair = GetPair(win->_nc_bkgd);
+ SetPair(ch, pair);
+ } else {
+ /* color in attrs has precedence over bkgrnd */
+ a |= AttrOf(win->_nc_bkgd) & COLOR_MASK(a);
+ /* color in ch has precedence */
+ if (pair == 0) {
+ if ((pair = GET_WINDOW_PAIR(win)) == 0)
+ pair = GetPair(win->_nc_bkgd);
+ }
+#if 0
+ if (pair > 255) {
+ cchar_t fixme = ch;
+ SetPair(fixme, pair);
+ }
+#endif
+ AddAttr(ch, (a & COLOR_MASK(AttrOf(ch))));
+ SetPair(ch, pair);
+ }
+
+ TR(TRACE_VIRTPUT,
+ ("render_char bkg %s (%d), attrs %s (%d) -> ch %s (%d)",
+ _tracech_t2(1, CHREF(win->_nc_bkgd)),
+ GetPair(win->_nc_bkgd),
+ _traceattr(WINDOW_ATTRS(win)),
+ GET_WINDOW_PAIR(win),
+ _tracech_t2(3, CHREF(ch)),
+ GetPair(ch)));
+
+ return (ch);
+}
+
+/* check if position is legal; if not, return error */
+#ifndef NDEBUG /* treat this like an assertion */
+#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) /* nothing */
+#endif
+
+static bool
+newline_forces_scroll(WINDOW *win, NCURSES_SIZE_T * ypos)
+{
+ bool result = FALSE;
+
+ if (*ypos >= win->_regtop && *ypos == win->_regbottom) {
+ *ypos = win->_regbottom;
+ result = TRUE;
+ } else {
+ *ypos += 1;
+ }
+ return result;
+}
+
+/*
+ * The _WRAPPED flag is useful only for telling an application that we've just
+ * wrapped the cursor. We don't do anything with this flag except set it when
+ * wrapping, and clear it whenever we move the cursor. If we try to wrap at
+ * the lower-right corner of a window, we cannot move the cursor (since that
+ * wouldn't be legal). So we return an error (which is what SVr4 does).
+ * Unlike SVr4, we can successfully add a character to the lower-right corner
+ * (Solaris 2.6 does this also, however).
+ */
+static int
+wrap_to_next_line(WINDOW *win)
+{
+ win->_flags |= _WRAPPED;
+ if (newline_forces_scroll(win, &(win->_cury))) {
+ win->_curx = win->_maxx;
+ if (!win->_scroll)
+ return (ERR);
+ scroll(win);
+ }
+ win->_curx = 0;
+ return (OK);
+}
+
+static int wadd_wch_literal(WINDOW *, cchar_t);
+/*
+ * Fill the given number of cells with blanks using the current background
+ * rendition. This saves/restores the current x-position.
+ */
+static void
+fill_cells(WINDOW *win, int count)
+{
+ cchar_t blank = blankchar;
+ int save_x = win->_curx;
+ int save_y = win->_cury;
+
+ while (count-- > 0) {
+ if (wadd_wch_literal(win, blank) == ERR)
+ break;
+ }
+ win->_curx = save_x;
+ win->_cury = save_y;
+}
+
+static int
+wadd_wch_literal(WINDOW *win, cchar_t ch)
+{
+ int x;
+ int y;
+ struct ldat *line;
+
+ x = win->_curx;
+ y = win->_cury;
+
+ CHECK_POSITION(win, x, y);
+
+ ch = render_char(win, ch);
+
+ line = win->_line + y;
+
+ CHANGED_CELL(line, x);
+
+ /*
+ * Non-spacing characters are added to the current cell.
+ *
+ * Spacing characters that are wider than one column require some display
+ * adjustments.
+ */
+ {
+ int len = wcwidth(CharOf(ch));
+ int i;
+ int j;
+ wchar_t *chars;
+
+ if (len == 0) { /* non-spacing */
+ if ((x > 0 && y >= 0)
+ || (win->_maxx >= 0 && win->_cury >= 1)) {
+ if (x > 0 && y >= 0)
+ chars = (win->_line[y].text[x - 1].chars);
+ else
+ chars = (win->_line[y - 1].text[win->_maxx].chars);
+ for (i = 0; i < CCHARW_MAX; ++i) {
+ if (chars[i] == 0) {
+ TR(TRACE_VIRTPUT,
+ ("added non-spacing %d: %x",
+ x, (int) CharOf(ch)));
+ chars[i] = CharOf(ch);
+ break;
+ }
+ }