1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright 1997 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /* Copyright (c) 1988 AT&T */
28 /* All Rights Reserved */
29
30 /*
31 * University Copyright- Copyright (c) 1982, 1986, 1988
32 * The Regents of the University of California
33 * All Rights Reserved
34 *
35 * University Acknowledgment- Portions of this document are derived from
36 * software developed by the University of California, Berkeley, and its
37 * contributors.
38 */
39
40 #pragma ident "%Z%%M% %I% %E% SMI"
41
42 /*LINTLIBRARY*/
43
44 #include <sys/types.h>
45 #include "curses_inc.h"
46
47 /*
48 * Insert to 'win' at most n chars of a string
49 * starting at (cury, curx). However, if n <= 0,
50 * insert the entire string.
51 * \n, \t, \r, \b are treated in the same way
52 * as other control chars.
53 */
54
55 int
winsnstr(WINDOW * win,char * tsp,int n)56 winsnstr(WINDOW *win, char *tsp, int n)
57 {
58 chtype *wcp;
59 int x, cury, endx, maxx, len;
60 bool savscrl, savsync, savimmed;
61 short savx, savy;
62 unsigned char *sp = (unsigned char *)tsp;
63
64 /* only insert at the start of a character */
65 win->_nbyte = -1;
66 win->_insmode = TRUE;
67 if (_scrmax > 1 && _mbvalid(win) == ERR)
68 return (ERR);
69
70 if (n < 0)
71 n = MAXINT;
72
73 /* compute total length of the insertion */
74 endx = win->_curx;
75 maxx = win->_maxx;
76 for (x = 0; sp[x] != '\0' && x < n && endx < maxx; ++x) {
77 len = (sp[x] < ' '|| sp[x] == _CTRL('?')) ? 2 : 1;
78
79 if (ISMBIT(sp[x])) {
80 int m, k, ty;
81 chtype c;
82
83 /* see if the entire character is defined */
84 c = RBYTE(sp[x]);
85 ty = TYPE(c);
86 m = x + cswidth[ty] - (ty == 0 ? 1 : 0);
87 for (k = x + 1; sp[k] != '\0' && k <= m; ++k) {
88 c = RBYTE(sp[k]);
89 if (TYPE(c) != 0)
90 break;
91 }
92 if (k <= m)
93 break;
94 /* recompute # of columns used */
95 len = _curs_scrwidth[ty];
96 /* skip an appropriate number of bytes */
97 x = m;
98 }
99
100 if ((endx += len) > maxx) {
101 endx -= len;
102 break;
103 }
104 }
105
106 /* length of chars to be shifted */
107 if ((len = endx - win->_curx) <= 0)
108 return (ERR);
109
110 /* number of chars insertible */
111 n = x;
112
113 /* shift data */
114 cury = win->_cury;
115
116 if (_mbinsshift(win, len) == ERR)
117 return (ERR);
118
119 /* insert new data */
120 wcp = win->_y[cury] + win->_curx;
121
122 /* act as if we are adding characters */
123 savx = win->_curx;
124 savy = win->_cury;
125 win->_insmode = FALSE;
126 savscrl = win->_scroll;
127 savimmed = win->_immed;
128 savsync = win->_sync;
129 win->_scroll = win->_sync;
130
131 for (; n > 0; --n, ++sp) {
132 /* multi-byte characters */
133 if (_mbtrue && ISMBIT(*sp)) {
134 (void) _mbaddch(win, A_NORMAL, RBYTE(*sp));
135 wcp = win->_y[cury] + win->_curx;
136 continue;
137 }
138 if (_scrmax > 1 && ISMBIT(*wcp))
139 (void) _mbclrch(win, cury, win->_curx);
140 /* single byte character */
141 win->_nbyte = -1;
142
143 if (*sp < ' ' || *sp == _CTRL('?')) {
144 *wcp++ = _CHAR('^') | win->_attrs;
145 *wcp = _CHAR(_UNCTRL(*sp)) | win->_attrs;
146 } else
147 *wcp = _CHAR(*sp) | win->_attrs;
148 win->_curx += (*sp < ' ' || *sp == _CTRL('?')) ? 2 : 1;
149 ++wcp;
150 }
151 win->_curx = savx;
152 win->_cury = savy;
153
154 /* update the change structure */
155 if (win->_firstch[cury] > win->_curx)
156 win->_firstch[cury] = win->_curx;
157 win->_lastch[cury] = maxx - 1;
158
159 win->_flags |= _WINCHANGED;
160
161 win->_scroll = savscrl;
162 win->_sync = savsync;
163 win->_immed = savimmed;
164
165 if (win->_sync)
166 wsyncup(win);
167 return (win->_immed ? wrefresh(win) : OK);
168 }
169