+ /*
+ * Build up multibyte characters until we have a wide-character.
+ */
+#if NCURSES_SP_FUNCS
+#define DeriveSP() SCREEN *sp = _nc_screen_of(win);
+#else
+#define DeriveSP() /*nothing */
+#endif
+ if_WIDEC({
+ DeriveSP();
+ if (WINDOW_EXT(win, addch_used) != 0 || !Charable(ch)) {
+ int len = _nc_build_wch(win, CHREF(ch));
+
+ if (len >= -1) {
+ attr_t attr = AttrOf(ch);
+
+ /* handle EILSEQ (i.e., when len >= -1) */
+ if (len == -1 && is8bits(CharOf(ch))) {
+ const char *s = NCURSES_SP_NAME(unctrl)
+ (NCURSES_SP_ARGx (chtype) CharOf(ch));
+
+ if (s[1] != '\0') {
+ int rc = OK;
+ while (*s != '\0') {
+ rc = waddch(win, UChar(*s) | attr);
+ if (rc != OK)
+ break;
+ ++s;
+ }
+ return rc;
+ }
+ }
+ if (len == -1)
+ return waddch(win, ' ' | attr);
+ } else {
+ return OK;
+ }
+ }
+ });
+
+ /*
+ * Non-spacing characters are added to the current cell.
+ *
+ * Spacing characters that are wider than one column require some display
+ * adjustments.
+ */
+ if_WIDEC({
+ int len = _nc_wacs_width(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;
+ }
+ }
+ }
+ goto testwrapping;
+ } else if (len > 1) { /* multi-column characters */
+ /*
+ * Check if the character will fit on the current line. If it does
+ * not fit, fill in the remainder of the line with blanks. and
+ * move to the next line.
+ */
+ if (len > win->_maxx + 1) {
+ TR(TRACE_VIRTPUT, ("character will not fit"));
+ return ERR;
+ } else if (x + len > win->_maxx) {
+ int count = win->_maxx + 1 - x;
+ TR(TRACE_VIRTPUT, ("fill %d remaining cells", count));
+ fill_cells(win, count);
+ if (wrap_to_next_line(win) == ERR)
+ return ERR;
+ x = win->_curx;
+ y = win->_cury;
+ CHECK_POSITION(win, x, y);
+ line = win->_line + y;
+ }
+ /*
+ * Check for cells which are orphaned by adding this character, set
+ * those to blanks.
+ *
+ * FIXME: this actually could fill j-i cells, more complicated to
+ * setup though.
+ */
+ for (i = 0; i < len; ++i) {
+ if (isWidecBase(win->_line[y].text[x + i])) {
+ break;
+ } else if (isWidecExt(win->_line[y].text[x + i])) {
+ for (j = i; x + j <= win->_maxx; ++j) {
+ if (!isWidecExt(win->_line[y].text[x + j])) {
+ TR(TRACE_VIRTPUT, ("fill %d orphan cells", j));
+ fill_cells(win, j);
+ break;
+ }
+ }
+ break;
+ }
+ }
+ /*
+ * Finally, add the cells for this character.
+ */
+ for (i = 0; i < len; ++i) {
+ NCURSES_CH_T value = ch;
+ SetWidecExt(value, i);
+ TR(TRACE_VIRTPUT, ("multicolumn %d:%d (%d,%d)",
+ i + 1, len,
+ win->_begy + y, win->_begx + x));
+ line->text[x] = value;
+ CHANGED_CELL(line, x);
+ ++x;
+ }
+ goto testwrapping;
+ }
+ });
+
+ /*
+ * Single-column characters.
+ */