#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: get_wstr.c,v 1.12 2024/12/23 02:58:03 blymn Exp $");
#endif
#include "curses.h"
#include "curses_private.h"
static int __wgetn_wstr(WINDOW *, wchar_t *, int);
int
getn_wstr(wchar_t *wstr, int n)
{
return wgetn_wstr(stdscr, wstr, n);
}
__warn_references(get_wstr,
"warning: this program uses get_wstr(), which is unsafe.")
int
get_wstr(wchar_t *wstr)
{
return wget_wstr(stdscr, wstr);
}
int
mvgetn_wstr(int y, int x, wchar_t *wstr, int n)
{
return mvwgetn_wstr(stdscr, y, x, wstr, n);
}
__warn_references(mvget_wstr,
"warning: this program uses mvget_wstr(), which is unsafe.")
int
mvget_wstr(int y, int x, wchar_t *wstr)
{
return mvwget_wstr(stdscr, y, x, wstr);
}
int
mvwgetn_wstr(WINDOW *win, int y, int x, wchar_t *wstr, int n)
{
if (wmove(win, y, x) == ERR)
return ERR;
return wgetn_wstr(win, wstr, n);
}
__warn_references(mvget_wstr,
"warning: this program uses mvget_wstr(), which is unsafe.")
int
mvwget_wstr(WINDOW *win, int y, int x, wchar_t *wstr)
{
if (wmove(win, y, x) == ERR)
return ERR;
return wget_wstr(win, wstr);
}
__warn_references(wget_wstr,
"warning: this program uses wget_wstr(), which is unsafe.")
int
wget_wstr(WINDOW *win, wchar_t *wstr)
{
return __wgetn_wstr(win, wstr, -1);
}
int
wgetn_wstr(WINDOW *win, wchar_t *wstr, int n)
{
if (n < 1)
return ERR;
if (n == 1) {
wstr[0] = L'\0';
return ERR;
}
return __wgetn_wstr(win, wstr, n);
}
int
__wgetn_wstr(WINDOW *win, wchar_t *wstr, int n)
{
wchar_t *ostr, ec, kc, sc[ 2 ];
int oldx, remain;
wint_t wc;
cchar_t cc;
if (__predict_false(win == NULL))
return ERR;
ostr = wstr;
if (erasewchar(&ec) == ERR)
return ERR;
if (killwchar(&kc) == ERR)
return ERR;
sc[0] = win->bch;
sc[1] = L'\0';
setcchar(&cc, sc, win->wattr, 0, NULL);
oldx = win->curx;
remain = n - 1;
while (wget_wch(win, &wc) != ERR
&& wc != L'\n' && wc != L'\r') {
__CTRACE(__CTRACE_INPUT,
"__wgetn_wstr: win %p, char 0x%x, remain %d\n",
win, wc, remain);
*wstr = wc;
touchline(win, win->cury, 1);
if (wc == ec || wc == KEY_BACKSPACE || wc == KEY_LEFT) {
*wstr = L'\0';
if (wstr != ostr) {
if ((wchar_t)wc == ec) {
mvwadd_wch(win, win->cury,
win->curx, &cc);
wmove(win, win->cury, win->curx - 1);
}
if (wc == KEY_BACKSPACE || wc == KEY_LEFT) {
mvwadd_wch(win, win->cury,
win->curx - 1, &cc);
mvwadd_wch(win, win->cury,
win->curx - 2, &cc);
wmove(win, win->cury, win->curx - 1);
}
wstr--;
if (n != -1) {
remain++;
}
} else {
if (wc == KEY_BACKSPACE || wc == KEY_LEFT)
mvwadd_wch(win, win->cury,
win->curx - 1, &cc);
wmove(win, win->cury, oldx);
}
} else if (wc == kc) {
*wstr = L'\0';
if (wstr != ostr) {
mvwadd_wch(win, win->cury, win->curx - 1, &cc);
while (wstr != ostr) {
mvwadd_wch(win, win->cury,
win->curx - 1, &cc);
wmove(win, win->cury, win->curx - 1);
wstr--;
if (n != -1)
remain++;
}
mvwadd_wch(win, win->cury, win->curx - 1, &cc);
wmove(win, win->cury, win->curx - 1);
} else
mvwadd_wch( win, win->cury, oldx, &cc );
wmove(win, win->cury, oldx);
} else if (wc >= KEY_MIN && wc <= KEY_MAX) {
mvwadd_wch( win, win->cury, win->curx - 1, &cc );
wmove(win, win->cury, win->curx - 1);
} else {
if (remain) {
wstr++;
remain--;
} else {
mvwadd_wch(win, win->cury, win->curx - 1, &cc);
wmove(win, win->cury, win->curx - 1);
}
}
}
if (wc == ERR) {
*wstr = L'\0';
return ERR;
}
*wstr = L'\0';
return OK;
}