1*6348e3f3Sblymn /* $NetBSD: get_wstr.c,v 1.12 2024/12/23 02:58:03 blymn Exp $ */ 2fa0b432bSblymn 3fa0b432bSblymn /* 4fa0b432bSblymn * Copyright (c) 2005 The NetBSD Foundation Inc. 5fa0b432bSblymn * All rights reserved. 6fa0b432bSblymn * 7fa0b432bSblymn * This code is derived from code donated to the NetBSD Foundation 8fa0b432bSblymn * by Ruibiao Qiu <ruibiao@arl.wustl.edu,ruibiao@gmail.com>. 9fa0b432bSblymn * 10fa0b432bSblymn * 11fa0b432bSblymn * Redistribution and use in source and binary forms, with or without 12fa0b432bSblymn * modification, are permitted provided that the following conditions 13fa0b432bSblymn * are met: 14fa0b432bSblymn * 1. Redistributions of source code must retain the above copyright 15fa0b432bSblymn * notice, this list of conditions and the following disclaimer. 16fa0b432bSblymn * 2. Redistributions in binary form must reproduce the above copyright 17fa0b432bSblymn * notice, this list of conditions and the following disclaimer in the 18fa0b432bSblymn * documentation and/or other materials provided with the distribution. 19fa0b432bSblymn * 3. Neither the name of the NetBSD Foundation nor the names of its 20fa0b432bSblymn * contributors may be used to endorse or promote products derived 21fa0b432bSblymn * from this software without specific prior written permission. 22fa0b432bSblymn * 23fa0b432bSblymn * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND 24fa0b432bSblymn * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 25fa0b432bSblymn * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 26fa0b432bSblymn * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27fa0b432bSblymn * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28fa0b432bSblymn * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29fa0b432bSblymn * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30fa0b432bSblymn * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31fa0b432bSblymn * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32fa0b432bSblymn * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33fa0b432bSblymn * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34fa0b432bSblymn * SUCH DAMAGE. 35fa0b432bSblymn */ 36fa0b432bSblymn 37fa0b432bSblymn #include <sys/cdefs.h> 38fa0b432bSblymn #ifndef lint 39*6348e3f3Sblymn __RCSID("$NetBSD: get_wstr.c,v 1.12 2024/12/23 02:58:03 blymn Exp $"); 40fa0b432bSblymn #endif /* not lint */ 41fa0b432bSblymn 42fa0b432bSblymn #include "curses.h" 43fa0b432bSblymn #include "curses_private.h" 44fa0b432bSblymn 45619b7f0eSjdc /* prototypes for private functions */ 46619b7f0eSjdc static int __wgetn_wstr(WINDOW *, wchar_t *, int); 47619b7f0eSjdc 48fa0b432bSblymn /* 49fa0b432bSblymn * getn_wstr -- 50fa0b432bSblymn * Get a string (of maximum n) characters from stdscr starting at 51fa0b432bSblymn * (cury, curx). 52fa0b432bSblymn */ 53fa0b432bSblymn int 54fa0b432bSblymn getn_wstr(wchar_t *wstr, int n) 55fa0b432bSblymn { 56fa0b432bSblymn return wgetn_wstr(stdscr, wstr, n); 57fa0b432bSblymn } 58fa0b432bSblymn 59fa0b432bSblymn /* 60fa0b432bSblymn * get_wstr -- 61fa0b432bSblymn * Get a string from stdscr starting at (cury, curx). 62fa0b432bSblymn */ 63fa0b432bSblymn __warn_references(get_wstr, 6454391ee9Srillig "warning: this program uses get_wstr(), which is unsafe.") 65fa0b432bSblymn int 66fa0b432bSblymn get_wstr(wchar_t *wstr) 67fa0b432bSblymn { 68fa0b432bSblymn return wget_wstr(stdscr, wstr); 69fa0b432bSblymn } 70fa0b432bSblymn 71fa0b432bSblymn /* 72fa0b432bSblymn * mvgetn_wstr -- 73fa0b432bSblymn * Get a string (of maximum n) characters from stdscr starting at (y, x). 74fa0b432bSblymn */ 75fa0b432bSblymn int 76fa0b432bSblymn mvgetn_wstr(int y, int x, wchar_t *wstr, int n) 77fa0b432bSblymn { 78fa0b432bSblymn return mvwgetn_wstr(stdscr, y, x, wstr, n); 79fa0b432bSblymn } 80fa0b432bSblymn 81fa0b432bSblymn /* 82fa0b432bSblymn * mvget_wstr -- 83fa0b432bSblymn * Get a string from stdscr starting at (y, x). 84fa0b432bSblymn */ 85fa0b432bSblymn __warn_references(mvget_wstr, 8654391ee9Srillig "warning: this program uses mvget_wstr(), which is unsafe.") 87fa0b432bSblymn int 88fa0b432bSblymn mvget_wstr(int y, int x, wchar_t *wstr) 89fa0b432bSblymn { 90fa0b432bSblymn return mvwget_wstr(stdscr, y, x, wstr); 91fa0b432bSblymn } 92fa0b432bSblymn 93fa0b432bSblymn /* 94fa0b432bSblymn * mvwgetn_wstr -- 95fa0b432bSblymn * Get a string (of maximum n) characters from the given window starting 96fa0b432bSblymn * at (y, x). 97fa0b432bSblymn */ 98fa0b432bSblymn int 99fa0b432bSblymn mvwgetn_wstr(WINDOW *win, int y, int x, wchar_t *wstr, int n) 100fa0b432bSblymn { 1012a780e62Sblymn if (wmove(win, y, x) == ERR) 102fa0b432bSblymn return ERR; 103fa0b432bSblymn 104fa0b432bSblymn return wgetn_wstr(win, wstr, n); 105fa0b432bSblymn } 106fa0b432bSblymn 107fa0b432bSblymn /* 108fa0b432bSblymn * mvwget_wstr -- 109fa0b432bSblymn * Get a string from the given window starting at (y, x). 110fa0b432bSblymn */ 111fa0b432bSblymn __warn_references(mvget_wstr, 11254391ee9Srillig "warning: this program uses mvget_wstr(), which is unsafe.") 113fa0b432bSblymn int 114fa0b432bSblymn mvwget_wstr(WINDOW *win, int y, int x, wchar_t *wstr) 115fa0b432bSblymn { 1162a780e62Sblymn if (wmove(win, y, x) == ERR) 117fa0b432bSblymn return ERR; 118fa0b432bSblymn 119fa0b432bSblymn return wget_wstr(win, wstr); 120fa0b432bSblymn } 121fa0b432bSblymn 122fa0b432bSblymn /* 123fa0b432bSblymn * wget_wstr -- 124fa0b432bSblymn * Get a string starting at (cury, curx). 125fa0b432bSblymn */ 126fa0b432bSblymn __warn_references(wget_wstr, 12754391ee9Srillig "warning: this program uses wget_wstr(), which is unsafe.") 128fa0b432bSblymn int 129fa0b432bSblymn wget_wstr(WINDOW *win, wchar_t *wstr) 130fa0b432bSblymn { 131fa0b432bSblymn return __wgetn_wstr(win, wstr, -1); 132fa0b432bSblymn } 133fa0b432bSblymn 134fa0b432bSblymn /* 135fa0b432bSblymn * wgetn_wstr -- 136fa0b432bSblymn * Get a string starting at (cury, curx). 137fa0b432bSblymn * Note that n < 2 means that we return ERR (SUSv2 specification). 138fa0b432bSblymn */ 139fa0b432bSblymn int 140fa0b432bSblymn wgetn_wstr(WINDOW *win, wchar_t *wstr, int n) 141fa0b432bSblymn { 142fa0b432bSblymn if (n < 1) 14350a63ac8Sroy return ERR; 144fa0b432bSblymn if (n == 1) { 145fa0b432bSblymn wstr[0] = L'\0'; 14650a63ac8Sroy return ERR; 147fa0b432bSblymn } 148fa0b432bSblymn return __wgetn_wstr(win, wstr, n); 149fa0b432bSblymn } 150fa0b432bSblymn 151fa0b432bSblymn /* 152fa0b432bSblymn * __wgetn_wstr -- 153fa0b432bSblymn * The actual implementation. 154fa0b432bSblymn * Note that we include a trailing L'\0' for safety, so str will contain 155fa0b432bSblymn * at most n - 1 other characters. 156fa0b432bSblymn */ 157fa0b432bSblymn int 158fa0b432bSblymn __wgetn_wstr(WINDOW *win, wchar_t *wstr, int n) 159fa0b432bSblymn { 160fa0b432bSblymn wchar_t *ostr, ec, kc, sc[ 2 ]; 161e124de36Sblymn int oldx, remain; 162fa0b432bSblymn wint_t wc; 163fa0b432bSblymn cchar_t cc; 164fa0b432bSblymn 165*6348e3f3Sblymn if (__predict_false(win == NULL)) 166*6348e3f3Sblymn return ERR; 167*6348e3f3Sblymn 168fa0b432bSblymn ostr = wstr; 169fa0b432bSblymn if (erasewchar(&ec) == ERR) 170fa0b432bSblymn return ERR; 171fa0b432bSblymn if (killwchar(&kc) == ERR) 172fa0b432bSblymn return ERR; 173301bf8ccSblymn sc[0] = win->bch; 174fa0b432bSblymn sc[1] = L'\0'; 175fa0b432bSblymn setcchar(&cc, sc, win->wattr, 0, NULL); 176fa0b432bSblymn oldx = win->curx; 177fa0b432bSblymn remain = n - 1; 178fa0b432bSblymn 179e124de36Sblymn while (wget_wch(win, &wc) != ERR 180fa0b432bSblymn && wc != L'\n' && wc != L'\r') { 181e124de36Sblymn __CTRACE(__CTRACE_INPUT, 182e124de36Sblymn "__wgetn_wstr: win %p, char 0x%x, remain %d\n", 183fa0b432bSblymn win, wc, remain); 184fa0b432bSblymn *wstr = wc; 185fa0b432bSblymn touchline(win, win->cury, 1); 186fa0b432bSblymn if (wc == ec || wc == KEY_BACKSPACE || wc == KEY_LEFT) { 187fa0b432bSblymn *wstr = L'\0'; 188fa0b432bSblymn if (wstr != ostr) { 189fa0b432bSblymn if ((wchar_t)wc == ec) { 190fa0b432bSblymn mvwadd_wch(win, win->cury, 191fa0b432bSblymn win->curx, &cc); 1922a780e62Sblymn wmove(win, win->cury, win->curx - 1); 193fa0b432bSblymn } 194fa0b432bSblymn if (wc == KEY_BACKSPACE || wc == KEY_LEFT) { 195fa0b432bSblymn /* getch() displays the key sequence */ 196fa0b432bSblymn mvwadd_wch(win, win->cury, 197fa0b432bSblymn win->curx - 1, &cc); 198fa0b432bSblymn mvwadd_wch(win, win->cury, 199fa0b432bSblymn win->curx - 2, &cc); 2002a780e62Sblymn wmove(win, win->cury, win->curx - 1); 201fa0b432bSblymn } 202fa0b432bSblymn wstr--; 203fa0b432bSblymn if (n != -1) { 204fa0b432bSblymn /* We're counting chars */ 205fa0b432bSblymn remain++; 206fa0b432bSblymn } 207fa0b432bSblymn } else { /* str == ostr */ 208fa0b432bSblymn if (wc == KEY_BACKSPACE || wc == KEY_LEFT) 209fa0b432bSblymn /* getch() displays the other keys */ 210fa0b432bSblymn mvwadd_wch(win, win->cury, 211fa0b432bSblymn win->curx - 1, &cc); 2122a780e62Sblymn wmove(win, win->cury, oldx); 213fa0b432bSblymn } 214fa0b432bSblymn } else if (wc == kc) { 215fa0b432bSblymn *wstr = L'\0'; 216fa0b432bSblymn if (wstr != ostr) { 217fa0b432bSblymn /* getch() displays the kill character */ 218fa0b432bSblymn mvwadd_wch(win, win->cury, win->curx - 1, &cc); 219fa0b432bSblymn /* Clear the characters from screen and str */ 220fa0b432bSblymn while (wstr != ostr) { 221fa0b432bSblymn mvwadd_wch(win, win->cury, 222fa0b432bSblymn win->curx - 1, &cc); 2232a780e62Sblymn wmove(win, win->cury, win->curx - 1); 224fa0b432bSblymn wstr--; 225fa0b432bSblymn if (n != -1) 226fa0b432bSblymn /* We're counting chars */ 227fa0b432bSblymn remain++; 228fa0b432bSblymn } 229fa0b432bSblymn mvwadd_wch(win, win->cury, win->curx - 1, &cc); 2302a780e62Sblymn wmove(win, win->cury, win->curx - 1); 231fa0b432bSblymn } else 232fa0b432bSblymn /* getch() displays the kill character */ 233fa0b432bSblymn mvwadd_wch( win, win->cury, oldx, &cc ); 2342a780e62Sblymn wmove(win, win->cury, oldx); 235fa0b432bSblymn } else if (wc >= KEY_MIN && wc <= KEY_MAX) { 236fa0b432bSblymn /* get_wch() displays these characters */ 237fa0b432bSblymn mvwadd_wch( win, win->cury, win->curx - 1, &cc ); 2382a780e62Sblymn wmove(win, win->cury, win->curx - 1); 239fa0b432bSblymn } else { 240fa0b432bSblymn if (remain) { 241fa0b432bSblymn wstr++; 242fa0b432bSblymn remain--; 243fa0b432bSblymn } else { 244fa0b432bSblymn mvwadd_wch(win, win->cury, win->curx - 1, &cc); 2452a780e62Sblymn wmove(win, win->cury, win->curx - 1); 246fa0b432bSblymn } 247fa0b432bSblymn } 248fa0b432bSblymn } 249fa0b432bSblymn 250fa0b432bSblymn if (wc == ERR) { 251fa0b432bSblymn *wstr = L'\0'; 252fa0b432bSblymn return ERR; 253fa0b432bSblymn } 254fa0b432bSblymn *wstr = L'\0'; 255fa0b432bSblymn return OK; 256fa0b432bSblymn } 257