ncurses 5.9 - patch 20110917
[ncurses.git] / ncurses / base / lib_addstr.c
index 9ac55e42aba7051daa4cf8cc5df3c1f36e981962..a1a55cb8bfd8b9bfa88ec7e11202beedfeb802b0 100644 (file)
@@ -1,5 +1,5 @@
 /****************************************************************************
- * Copyright (c) 1998 Free Software Foundation, Inc.                        *
+ * Copyright (c) 1998-2010,2011 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            *
 /****************************************************************************
  *  Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995               *
  *     and: Eric S. Raymond <esr@snark.thyrsus.com>                         *
+ *                                                                          *
+ *  Rewritten 2001-2004 to support wide-characters by                       *
+ *     Sven Verdoolaege                                                    *
+ *     Thomas Dickey                                                       *
  ****************************************************************************/
 
 /*
 
 #include <curses.priv.h>
 
-MODULE_ID("$Id: lib_addstr.c,v 1.16 1998/06/28 00:38:29 tom Exp $")
+MODULE_ID("$Id: lib_addstr.c,v 1.52 2011/05/28 23:02:09 tom Exp $")
 
-int
-waddnstr(WINDOW *win, const char *const astr, int n)
+NCURSES_EXPORT(int)
+waddnstr(WINDOW *win, const char *astr, int n)
 {
-unsigned const char *str = (unsigned const char *)astr;
-int code = ERR;
-
-       T((T_CALLED("waddnstr(%p,%s,%d)"), win, _nc_visbuf(astr), n));
-         
-       if (win && (str != 0)) {            
-         T(("... current %s", _traceattr(win->_attrs)));
-         TR(TRACE_VIRTPUT, ("str is not null"));
-         code = OK;
-         if (n < 0)
-           n = (int)strlen(astr);
-         
-         while((n-- > 0) && (*str != '\0')) {
-           TR(TRACE_VIRTPUT, ("*str = %#x", *str));
-           if (_nc_waddch_nosync(win, (chtype)*str++) == ERR) {
-             code = ERR;
-             break;
+    const char *str = astr;
+    int code = ERR;
+
+    T((T_CALLED("waddnstr(%p,%s,%d)"), (void *) win, _nc_visbufn(astr, n), n));
+
+    if (win && (str != 0)) {
+       TR(TRACE_VIRTPUT | TRACE_ATTRS,
+          ("... current %s", _traceattr(WINDOW_ATTRS(win))));
+       code = OK;
+       if (n < 0)
+           n = (int) strlen(astr);
+
+       TR(TRACE_VIRTPUT, ("str is not null, length = %d", n));
+       while ((n-- > 0) && (*str != '\0')) {
+           NCURSES_CH_T ch;
+           TR(TRACE_VIRTPUT, ("*str = %#o", UChar(*str)));
+           SetChar(ch, UChar(*str++), A_NORMAL);
+           if (_nc_waddch_nosync(win, ch) == ERR) {
+               code = ERR;
+               break;
            }
-         }
-         _nc_synchook(win);
        }
-       TR(TRACE_VIRTPUT, ("waddnstr returns %d", code));
+       _nc_synchook(win);
+    }
+    TR(TRACE_VIRTPUT, ("waddnstr returns %d", code));
+    returnCode(code);
+}
+
+NCURSES_EXPORT(int)
+waddchnstr(WINDOW *win, const chtype *astr, int n)
+{
+    NCURSES_SIZE_T y, x;
+    int code = OK;
+    int i;
+    struct ldat *line;
+
+    T((T_CALLED("waddchnstr(%p,%p,%d)"), (void *) win, (const void *) astr, n));
+
+    if (!win)
+       returnCode(ERR);
+
+    y = win->_cury;
+    x = win->_curx;
+    if (n < 0) {
+       const chtype *str;
+       n = 0;
+       for (str = (const chtype *) astr; *str != 0; str++)
+           n++;
+    }
+    if (n > win->_maxx - x + 1)
+       n = win->_maxx - x + 1;
+    if (n == 0)
        returnCode(code);
+
+    line = &(win->_line[y]);
+    for (i = 0; i < n && ChCharOf(astr[i]) != '\0'; ++i) {
+       SetChar2(line->text[i + x], astr[i]);
+    }
+    CHANGED_RANGE(line, x, (NCURSES_SIZE_T) (x + n - 1));
+
+    _nc_synchook(win);
+    returnCode(code);
 }
 
-int
-waddchnstr(WINDOW *win, const chtype *const astr, int n)
+#if USE_WIDEC_SUPPORT
+
+NCURSES_EXPORT(int)
+_nc_wchstrlen(const cchar_t *s)
 {
-short y = win->_cury;
-short x = win->_curx;
-int code = OK;
-struct ldat *line;
+    int result = 0;
+    if (s != 0) {
+       while (CharOf(s[result]) != L'\0') {
+           result++;
+       }
+    }
+    return result;
+}
+
+NCURSES_EXPORT(int)
+wadd_wchnstr(WINDOW *win, const cchar_t *astr, int n)
+{
+    static const NCURSES_CH_T blank = NewChar(BLANK_TEXT);
+    NCURSES_SIZE_T y;
+    NCURSES_SIZE_T x;
+    int code = OK;
+    struct ldat *line;
+    int i, j, start, len, end;
 
-       T((T_CALLED("waddchnstr(%p,%p,%d)"), win, astr, n));
+    T((T_CALLED("wadd_wchnstr(%p,%s,%d)"),
+       (void *) win,
+       _nc_viscbuf(astr, n),
+       n));
 
-       if (!win)
-               returnCode(ERR);
+    if (!win)
+       returnCode(ERR);
 
-       if (n < 0) {
-               const chtype *str;
-               n = 0;
-               for (str=(const chtype *)astr; *str!=0; str++)
-                       n++;
+    y = win->_cury;
+    x = win->_curx;
+    if (n < 0) {
+       n = _nc_wchstrlen(astr);
+    }
+    if (n > win->_maxx - x + 1)
+       n = win->_maxx - x + 1;
+    if (n == 0)
+       returnCode(code);
+
+    line = &(win->_line[y]);
+    start = x;
+    end = x + n - 1;
+
+    /*
+     * Reset orphaned cells of multi-column characters that extend up to the
+     * new string's location to blanks.
+     */
+    if (x > 0 && isWidecExt(line->text[x])) {
+       for (i = 0; i <= x; ++i) {
+           if (!isWidecExt(line->text[x - i])) {
+               /* must be isWidecBase() */
+               start -= i;
+               while (i > 0) {
+                   line->text[x - i--] = _nc_render(win, blank);
+               }
+               break;
+           }
        }
-       if (n > win->_maxx - x + 1)
-               n = win->_maxx - x + 1;
-       if (n == 0)
-               returnCode(code);
+    }
+
+    /*
+     * Copy the new string to the window.
+     */
+    for (i = 0; i < n && CharOf(astr[i]) != L'\0' && x <= win->_maxx; ++i) {
+       if (isWidecExt(astr[i]))
+           continue;
+
+       len = wcwidth(CharOf(astr[i]));
+
+       if (x + len - 1 <= win->_maxx) {
+           line->text[x] = _nc_render(win, astr[i]);
+           if (len > 1) {
+               for (j = 0; j < len; ++j) {
+                   if (j != 0) {
+                       line->text[x + j] = line->text[x];
+                   }
+                   SetWidecExt(line->text[x + j], j);
+               }
+           }
+           x = (NCURSES_SIZE_T) (x + len);
+           end += len - 1;
+       } else {
+           break;
+       }
+    }
+
+    /*
+     * Set orphaned cells of multi-column characters which lie after the new
+     * string to blanks.
+     */
+    while (x <= win->_maxx && isWidecExt(line->text[x])) {
+       line->text[x] = _nc_render(win, blank);
+       ++end;
+       ++x;
+    }
+    CHANGED_RANGE(line, start, end);
 
-       line = &(win->_line[y]);
-       memcpy(line->text+x, astr, n*sizeof(*astr));
-       CHANGED_RANGE(line, x, x+n-1);
+    _nc_synchook(win);
+    returnCode(code);
+}
+
+NCURSES_EXPORT(int)
+waddnwstr(WINDOW *win, const wchar_t *str, int n)
+{
+    int code = ERR;
+
+    T((T_CALLED("waddnwstr(%p,%s,%d)"), (void *) win, _nc_viswbufn(str, n), n));
+
+    if (win && (str != 0)) {
+       TR(TRACE_VIRTPUT | TRACE_ATTRS,
+          ("... current %s", _traceattr(WINDOW_ATTRS(win))));
+       code = OK;
+       if (n < 0)
+           n = (int) wcslen(str);
 
+       TR(TRACE_VIRTPUT, ("str is not null, length = %d", n));
+       while ((n-- > 0) && (*str != L('\0'))) {
+           NCURSES_CH_T ch;
+           TR(TRACE_VIRTPUT, ("*str[0] = %#lx", (unsigned long) *str));
+           SetChar(ch, *str++, A_NORMAL);
+           if (wadd_wch(win, &ch) == ERR) {
+               code = ERR;
+               break;
+           }
+       }
        _nc_synchook(win);
-       returnCode(code);
+    }
+    TR(TRACE_VIRTPUT, ("waddnwstr returns %d", code));
+    returnCode(code);
 }
+
+#endif