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