d6f9345542e34427b3a4c061c418b0e0b8fc9934
[ncurses.git] / ncurses / base / lib_addstr.c
1 /****************************************************************************
2  * Copyright (c) 1998-2001,2002 Free Software Foundation, Inc.              *
3  *                                                                          *
4  * Permission is hereby granted, free of charge, to any person obtaining a  *
5  * copy of this software and associated documentation files (the            *
6  * "Software"), to deal in the Software without restriction, including      *
7  * without limitation the rights to use, copy, modify, merge, publish,      *
8  * distribute, distribute with modifications, sublicense, and/or sell       *
9  * copies of the Software, and to permit persons to whom the Software is    *
10  * furnished to do so, subject to the following conditions:                 *
11  *                                                                          *
12  * The above copyright notice and this permission notice shall be included  *
13  * in all copies or substantial portions of the Software.                   *
14  *                                                                          *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
16  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
18  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
19  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
20  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
21  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
22  *                                                                          *
23  * Except as contained in this notice, the name(s) of the above copyright   *
24  * holders shall not be used in advertising or otherwise to promote the     *
25  * sale, use or other dealings in this Software without prior written       *
26  * authorization.                                                           *
27  ****************************************************************************/
28
29 /****************************************************************************
30  *  Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995               *
31  *     and: Eric S. Raymond <esr@snark.thyrsus.com>                         *
32  ****************************************************************************/
33
34 /*
35 **      lib_addstr.c
36 *
37 **      The routines waddnstr(), waddchnstr().
38 **
39 */
40
41 #include <curses.priv.h>
42
43 MODULE_ID("$Id: lib_addstr.c,v 1.34 2002/10/06 00:25:25 tom Exp $")
44
45 #if USE_WIDEC_SUPPORT
46 #define CONV_DATA   mbstate_t state; wchar_t cached; int clen = 0
47 #define CONV_INIT   memset (&state, '\0', sizeof (state)); cached = (wchar_t)WEOF
48 #define NEXT_CHAR(s,ch, n)                                              \
49     {                                                                   \
50         int len, i = 0;                                                 \
51         memset(&ch, 0, sizeof(cchar_t));                                \
52         if (cached != (wchar_t) WEOF) {                                 \
53             ch.chars[i++] = cached;                                     \
54             cached = (wchar_t) WEOF;                                    \
55             n -= clen;                                                  \
56             s += clen;                                                  \
57         }                                                               \
58         for (; i < CCHARW_MAX && n > 0; ++i) {                          \
59             if ((len = mbrtowc(&ch.chars[i], s, n, &state)) < 0) {      \
60                 code = ERR;                                             \
61                 break;                                                  \
62             }                                                           \
63             if (i == 0 || wcwidth(ch.chars[i]) == 0) {                  \
64                 n -= len;                                               \
65                 s += len;                                               \
66             } else {                                                    \
67                 cached = ch.chars[i];                                   \
68                 clen = len;                                             \
69                 ch.chars[i] = L'\0';                                    \
70                 break;                                                  \
71             }                                                           \
72         }                                                               \
73         if (code == ERR)                                                \
74             break;                                                      \
75     }
76 #else
77 #define CONV_DATA
78 #define CONV_INIT
79 #define NEXT_CHAR(s,ch, n)                                              \
80     ch = *s++;                                                          \
81     --n
82 #endif
83
84 NCURSES_EXPORT(int)
85 waddnstr(WINDOW *win, const char *astr, int n)
86 {
87     unsigned const char *str = (unsigned const char *) astr;
88     int code = ERR;
89     CONV_DATA;
90
91     T((T_CALLED("waddnstr(%p,%s,%d)"), win, _nc_visbufn(astr, n), n));
92
93     if (win && (str != 0)) {
94         TR(TRACE_VIRTPUT | TRACE_ATTRS, ("... current %s", _traceattr(win->_attrs)));
95         code = OK;
96         if (n < 0)
97             n = (int) strlen(astr);
98
99         TR(TRACE_VIRTPUT, ("str is not null, length = %d", n));
100         CONV_INIT;
101         while ((n > 0) && (*str != '\0')) {
102             NCURSES_CH_T ch;
103             TR(TRACE_VIRTPUT, ("*str = %#x", *str));
104             NEXT_CHAR(str, ch, n);
105             if (_nc_waddch_nosync(win, ch) == ERR) {
106                 code = ERR;
107                 break;
108             }
109         }
110         _nc_synchook(win);
111     }
112     TR(TRACE_VIRTPUT, ("waddnstr returns %d", code));
113     returnCode(code);
114 }
115
116 NCURSES_EXPORT(int)
117 waddchnstr(WINDOW *win, const chtype * astr, int n)
118 {
119     NCURSES_SIZE_T y = win->_cury;
120     NCURSES_SIZE_T x = win->_curx;
121     int code = OK;
122     struct ldat *line;
123
124     T((T_CALLED("waddchnstr(%p,%p,%d)"), win, astr, n));
125
126     if (!win)
127         returnCode(ERR);
128
129     if (n < 0) {
130         const chtype *str;
131         n = 0;
132         for (str = (const chtype *) astr; *str != 0; str++)
133             n++;
134     }
135     if (n > win->_maxx - x + 1)
136         n = win->_maxx - x + 1;
137     if (n == 0)
138         returnCode(code);
139
140     line = &(win->_line[y]);
141 #if USE_WIDEC_SUPPORT
142     {
143         int i;
144         for (i = 0; i < n; ++i)
145             SetChar(line->text[i + x], ChCharOf(astr[i]), ChAttrOf(astr[i]));
146     }
147 #else
148     memcpy(line->text + x, astr, n * sizeof(*astr));
149 #endif
150     CHANGED_RANGE(line, x, x + n - 1);
151
152     _nc_synchook(win);
153     returnCode(code);
154 }
155
156 #if USE_WIDEC_SUPPORT
157
158 int
159 _nc_wchstrlen(const cchar_t * s)
160 {
161     int result = 0;
162     while (CharOf(s[result]) != L'\0') {
163         result++;
164     }
165     return result;
166 }
167
168 NCURSES_EXPORT(int)
169 wadd_wchnstr(WINDOW *win, const cchar_t * const astr, int n)
170 {
171     NCURSES_SIZE_T y = win->_cury;
172     NCURSES_SIZE_T x = win->_curx;
173     int code = OK;
174     struct ldat *line;
175     int i, start, end;
176
177     T((T_CALLED("wadd_wchnstr(%p,%s,%d)"), win, _nc_viscbuf(astr, n), n));
178
179     if (!win)
180         returnCode(ERR);
181
182     if (n < 0) {
183         n = _nc_wchstrlen(astr);
184     }
185     if (n > win->_maxx - x + 1)
186         n = win->_maxx - x + 1;
187     if (n == 0)
188         returnCode(code);
189
190     line = &(win->_line[y]);
191     start = x;
192     end = x + n - 1;
193     if (isnac(line->text[x])) {
194         line->text[x - 1] = win->_nc_bkgd;
195         --start;
196     }
197     for (i = 0; i < n && x <= win->_maxx; ++i) {
198         line->text[x++] = astr[i];
199         if (wcwidth(CharOf(astr[i])) > 1) {
200             if (x <= win->_maxx)
201                 AddAttr(line->text[x++], WA_NAC);
202             else
203                 line->text[x - 1] = win->_nc_bkgd;
204         }
205     }
206     if (x <= win->_maxx && isnac(line->text[x])) {
207         line->text[x] = win->_nc_bkgd;
208         ++end;
209     }
210     CHANGED_RANGE(line, start, end);
211
212     _nc_synchook(win);
213     returnCode(code);
214 }
215
216 NCURSES_EXPORT(int)
217 waddnwstr(WINDOW *win, const wchar_t * str, int n)
218 {
219     int code = ERR;
220     int i;
221
222     T((T_CALLED("waddnwstr(%p,%s,%d)"), win, _nc_viswbufn(str,n), n));
223
224     if (win && (str != 0)) {
225         TR(TRACE_VIRTPUT | TRACE_ATTRS, ("... current %s", _traceattr(win->_attrs)));
226         code = OK;
227         if (n < 0)
228             n = (int) wcslen(str);
229
230         TR(TRACE_VIRTPUT, ("str is not null, length = %d", n));
231         while ((n-- > 0) && (*str != L('\0'))) {
232             NCURSES_CH_T ch;
233             TR(TRACE_VIRTPUT, ("*str[0] = %#lx", *str));
234             SetChar(ch, *str++, A_NORMAL);
235             i = 1;
236             while (i < CCHARW_MAX && n > 0 && (*str != L('\0'))
237                    && wcwidth(*str) == 0) {
238                 TR(TRACE_VIRTPUT, ("*str[%d] = %#lx", i, *str));
239                 ch.chars[i++] = *str++;
240                 --n;
241             }
242             if (_nc_waddch_nosync(win, ch) == ERR) {
243                 code = ERR;
244                 break;
245             }
246         }
247         _nc_synchook(win);
248     }
249     TR(TRACE_VIRTPUT, ("waddnwstr returns %d", code));
250     returnCode(code);
251 }
252
253 #endif