xref: /netbsd/lib/libcurses/getstr.c (revision bf9ec67e)
1 /*	$NetBSD: getstr.c,v 1.16 2002/01/02 10:38:27 blymn Exp $	*/
2 
3 /*
4  * Copyright (c) 1981, 1993, 1994
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *	This product includes software developed by the University of
18  *	California, Berkeley and its contributors.
19  * 4. Neither the name of the University nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  */
35 
36 #include <assert.h>
37 #include <sys/cdefs.h>
38 #ifndef lint
39 #if 0
40 static char sccsid[] = "@(#)getstr.c	8.2 (Berkeley) 5/4/94";
41 #else
42 __RCSID("$NetBSD: getstr.c,v 1.16 2002/01/02 10:38:27 blymn Exp $");
43 #endif
44 #endif				/* not lint */
45 
46 #include "curses.h"
47 #include "curses_private.h"
48 
49 #ifndef _CURSES_USE_MACROS
50 
51 /*
52  * getnstr --
53  *	Get a string (of maximum n) characters from stdscr starting at
54  *	(cury, curx).
55  */
56 int
57 getnstr(char *str, int n)
58 {
59 	return wgetnstr(stdscr, str, n);
60 }
61 
62 /*
63  * getstr --
64  *	Get a string from stdscr starting at (cury, curx).
65  */
66 __warn_references(getstr,
67     "warning: this program uses getstr(), which is unsafe.")
68 int
69 getstr(char *str)
70 {
71 	return wgetstr(stdscr, str);
72 }
73 
74 /*
75  * mvgetnstr --
76  *      Get a string (of maximum n) characters from stdscr starting at (y, x).
77  */
78 int
79 mvgetnstr(int y, int x, char *str, int n)
80 {
81 	return mvwgetnstr(stdscr, y, x, str, n);
82 }
83 
84 /*
85  * mvgetstr --
86  *      Get a string from stdscr starting at (y, x).
87  */
88 __warn_references(mvgetstr,
89     "warning: this program uses mvgetstr(), which is unsafe.")
90 int
91 mvgetstr(int y, int x, char *str)
92 {
93 	return mvwgetstr(stdscr, y, x, str);
94 }
95 
96 /*
97  * mvwgetnstr --
98  *      Get a string (of maximum n) characters from the given window starting
99  *	at (y, x).
100  */
101 int
102 mvwgetnstr(WINDOW *win, int y, int x, char *str, int n)
103 {
104 	if (wmove(win, y, x) == ERR)
105 		return ERR;
106 
107 	return wgetnstr(win, str, n);
108 }
109 
110 /*
111  * mvwgetstr --
112  *      Get a string from the given window starting at (y, x).
113  */
114 __warn_references(mvgetstr,
115     "warning: this program uses mvgetstr(), which is unsafe.")
116 int
117 mvwgetstr(WINDOW *win, int y, int x, char *str)
118 {
119 	if (wmove(win, y, x) == ERR)
120 		return ERR;
121 
122 	return wgetstr(win, str);
123 }
124 
125 #endif
126 
127 /*
128  * wgetstr --
129  *	Get a string starting at (cury, curx).
130  */
131 __warn_references(wgetstr,
132     "warning: this program uses wgetstr(), which is unsafe.")
133 int
134 wgetstr(WINDOW *win, char *str)
135 {
136 	return __wgetnstr(win, str, -1);
137 }
138 
139 /*
140  * wgetnstr --
141  *	Get a string starting at (cury, curx).
142  *	Note that n <  2 means that we return ERR (SUSv2 specification).
143  */
144 int
145 wgetnstr(WINDOW *win, char *str, int n)
146 {
147 	if (n < 1)
148 		return (ERR);
149 	if (n == 1) {
150 		str[0] = '\0';
151 		return (ERR);
152 	}
153 	return __wgetnstr(win, str, n);
154 }
155 
156 /*
157  * __wgetnstr --
158  *	The actual implementation.
159  *	Note that we include a trailing '\0' for safety, so str will contain
160  *	at most n - 1 other characters.
161  *	XXX: character deletion from screen is based on how the characters
162  *	are displayed by wgetch().
163  */
164 int
165 __wgetnstr(WINDOW *win, char *str, int n)
166 {
167 	char *ostr, ec, kc;
168 	int c, oldx, remain;
169 
170 	ostr = str;
171 	ec = erasechar();
172 	kc = killchar();
173 	oldx = win->curx;
174 	_DIAGASSERT(n == -1 || n > 1);
175 	remain = n - 1;
176 
177 	while ((c = wgetch(win)) != ERR && c != '\n' && c != '\r') {
178 #ifdef DEBUG
179 		__CTRACE("__wgetnstr: win %0.2o, char 0x%x, remain %d\n", win,
180 		    c, remain);
181 #endif
182 		*str = c;
183 		touchline(win, win->cury, 1);
184 		if (c == ec || c == KEY_BACKSPACE || c == KEY_LEFT) {
185 			*str = '\0';
186 			if (str != ostr) {
187 				if ((char) c == ec) {
188 					mvwaddch(win, win->cury, win->curx,
189 					    ' ');
190 					wmove(win, win->cury, win->curx - 1);
191 				}
192 				if (c == KEY_BACKSPACE || c == KEY_LEFT) {
193 					/* getch() displays the key sequence */
194 					mvwaddch(win, win->cury, win->curx - 1,
195 					    ' ');
196 					mvwaddch(win, win->cury, win->curx - 2,
197 					    ' ');
198 					wmove(win, win->cury, win->curx - 1);
199 				}
200 				str--;
201 				if (n != -1) {
202 					/* We're counting chars */
203 					remain++;
204 				}
205 			} else {        /* str == ostr */
206 				if (c == KEY_BACKSPACE || c == KEY_LEFT)
207 					/* getch() displays the other keys */
208 					mvwaddch(win, win->cury, win->curx - 1,
209 					    ' ');
210 				wmove(win, win->cury, oldx);
211 			}
212 		} else if (c == kc) {
213 			*str = '\0';
214 			if (str != ostr) {
215 				/* getch() displays the kill character */
216 				mvwaddch(win, win->cury, win->curx - 1, ' ');
217 				/* Clear the characters from screen and str */
218 				while (str != ostr) {
219 					mvwaddch(win, win->cury, win->curx - 1,
220 					    ' ');
221 					wmove(win, win->cury, win->curx - 1);
222 					str--;
223 					if (n != -1)
224 						/* We're counting chars */
225 						remain++;
226 				}
227 				mvwaddch(win, win->cury, win->curx - 1, ' ');
228 				wmove(win, win->cury, win->curx - 1);
229 			} else
230 				/* getch() displays the kill character */
231 				mvwaddch(win, win->cury, oldx, ' ');
232 			wmove(win, win->cury, oldx);
233 		} else if (c >= KEY_MIN && c <= KEY_MAX) {
234 			/* getch() displays these characters */
235 			mvwaddch(win, win->cury, win->curx - 1, ' ');
236 			wmove(win, win->cury, win->curx - 1);
237 		} else {
238 			if (remain) {
239 				str++;
240 				remain--;
241 			} else {
242 				mvwaddch(win, win->cury, win->curx - 1, ' ');
243 				wmove(win, win->cury, win->curx - 1);
244 			}
245 		}
246 	}
247 
248 	if (c == ERR) {
249 		*str = '\0';
250 		return (ERR);
251 	}
252 	*str = '\0';
253 	return (OK);
254 }
255