xref: /illumos-gate/usr/src/lib/libcurses/screen/wgetstr.c (revision 4de2612967d06c4fdbf524a62556a1e8118a006f)
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 #define		LENGTH	256
48 
49 /* This routine gets a string starting at (_cury, _curx) */
50 
51 int
52 wgetstr(WINDOW *win, char *str)
53 {
54 	return ((wgetnstr(win, str, LENGTH) == ERR) ? ERR : OK);
55 }
56 
57 int
58 wgetnstr(WINDOW *win, char *str, int n)
59 {
60 	int	cpos = 0, ch;
61 	int	nbyte = 0;
62 	int	tbyte = 0;
63 	int	byte[LENGTH];
64 	int	eucw, scrw;
65 	int	docont = 0;
66 	char	*cp = str;
67 	int	i = 0;
68 	int	total = 0;
69 	char	myerase, mykill;
70 	char	rownum[LENGTH], colnum[LENGTH], length[LENGTH];
71 	int	doecho = SP->fl_echoit;
72 	int	savecb = cur_term->_fl_rawmode;
73 	bool	savsync, savimmed, savleave;
74 
75 #ifdef	DEBUG
76 	if (outf)
77 		fprintf(outf, "doecho %d, savecb %d\n", doecho, savecb);
78 #endif	/* DEBUG */
79 
80 	myerase = erasechar();
81 	mykill = killchar();
82 	if (!savecb)
83 		(void) cbreak();
84 
85 	if (doecho) {
86 		SP->fl_echoit = FALSE;
87 		savsync = win->_sync;
88 		savimmed = win->_immed;
89 		savleave = win->_leave;
90 		win->_immed = win->_sync = win->_leave = FALSE;
91 		(void) wrefresh(win);
92 		if (n > LENGTH)
93 			n = LENGTH;
94 	}
95 	n--;
96 
97 	while (nbyte < n) {
98 		if (doecho && !docont) {
99 			rownum[cpos] = win->_cury;
100 			colnum[cpos] = win->_curx;
101 		}
102 
103 		ch = wgetch(win);
104 		if (docont)
105 			goto cont;
106 
107 		if ((ch == ERR) || (ch == '\n') || (ch == '\r') ||
108 		    (ch == KEY_ENTER))
109 			break;
110 		if ((ch == myerase) || (ch == KEY_LEFT) ||
111 		    (ch == KEY_BACKSPACE) || (ch == mykill)) {
112 			if (cpos > 0) {
113 				if (ch == mykill) {
114 					i = total;
115 					total = cpos = 0;
116 					nbyte = 0;
117 					cp = str;
118 				} else {
119 					cpos--;
120 					cp -= byte[cpos];
121 					if (doecho)
122 						total -= (i = length[cpos]);
123 				}
124 				if (doecho) {
125 					(void) wmove(win, rownum[cpos],
126 					    colnum[cpos]);
127 					/* Add the correct amount of blanks. */
128 					for (; i > 0; i--)
129 						(void) waddch(win, ' ');
130 					/* Move back after the blanks are */
131 					/* put in. */
132 					(void) wmove(win, rownum[cpos],
133 					    colnum[cpos]);
134 					/* Update total. */
135 					(void) wrefresh(win);
136 				}
137 			} else
138 				if (doecho)
139 					(void) beep();
140 		} else if ((KEY_MIN <= ch) && (ch <= KEY_MAX))
141 				(void) beep();
142 			else {
143 cont:
144 				/* LINTED */
145 				*cp++ = (char)ch;
146 				if (docont) {
147 					tbyte++;
148 				} else if (ISMBIT(ch)) {
149 					docont = 1;
150 					tbyte = 1;
151 					scrw = mbscrw(ch);
152 					eucw = mbeucw(ch);
153 				}
154 
155 				if (docont && (tbyte >= eucw)) {
156 					docont = 0;
157 					tbyte = 0;
158 					if (doecho) {
159 						byte[cpos] = eucw;
160 						/* LINTED */
161 						length[cpos] = (char)scrw;
162 						(void) wechochar(win,
163 						    (chtype) ch);
164 					}
165 				} else if (doecho) {
166 					/* Add the length of the */
167 					/* character to total. */
168 					byte[cpos] = 1;
169 					if (ch >= ' ')
170 						length[cpos] = 1;
171 					else
172 						if (ch == '\t')
173 							length[cpos] = TABSIZE-
174 							    (colnum[cpos] %
175 							    TABSIZE);
176 						else
177 							length[cpos] = 2;
178 					total += length[cpos];
179 					(void) wechochar(win, (chtype) ch);
180 				}
181 				if (!docont)
182 					cpos++;
183 				nbyte++;
184 			}
185 	}
186 
187 	*cp = '\0';
188 
189 	if (!savecb)
190 		(void) nocbreak();
191 	/*
192 	 * The following code is equivalent to waddch(win, '\n')
193 	 * except that it does not do a wclrtoeol.
194 	 */
195 	if (doecho) {
196 		SP->fl_echoit = TRUE;
197 		win->_curx = 0;
198 		if (win->_cury + 1 > win->_bmarg)
199 			(void) wscrl(win, 1);
200 		else
201 			win->_cury++;
202 
203 		win->_sync = savsync;
204 		win->_immed = savimmed;
205 		win->_leave = savleave;
206 		(void) wrefresh(win);
207 	}
208 	return (ch);
209 }
210