Reputation: 198
Cannot implement character input validation. I have sketched out the code of a simple program for input validation. Various characters are displayed in the field.
#include <form.h>
int main() {
initscr();
curs_set(1);
WINDOW *win = newwin(5, 40, 10, 10);
keypad(win, TRUE);
box(win, 0, 0);
wrefresh(win);
FIELD *fields[2];
fields[0] = new_field(1, 20, 2, 2, 0, 0);
fields[1] = NULL;
set_field_type(fields[0], TYPE_REGEXP, "^[0-9]*$");
set_field_opts(fields[0], O_VISIBLE | O_ACTIVE | O_EDIT);
FORM *form = new_form(fields);
set_form_win(form, win);
set_form_sub(form, derwin(win, 3, 38, 1, 1));
post_form(form);
wrefresh(win);
int ch;
while ((ch = wgetch(win)) != KEY_F(1)) {
int status = form_driver(form, ch);
if (status == E_INVALID_FIELD) {
form_driver(form, REQ_VALIDATION);
} else if (status == E_OK) {
wrefresh(win);
}
}
unpost_form(form);
free_form(form);
free_field(fields[0]);
endwin();
return 0;
}
UPD 1:
while ((ch = wgetch(win)) != KEY_F(1)) {
int status = form_driver(form, ch);
if( status == E_OK ) {
status = form_driver(form, REQ_VALIDATION);
}
if (status == E_INVALID_FIELD) {
frefresh(form);
} else if (status == E_OK) {
wrefresh(win);
}
}
void frefresh(FORM *form) {
form_driver(form, REQ_DEL_PREV);
}
Moved the cleaning code to a separate function. The cursor returns to the incorrectly entered character.
Upvotes: 0
Views: 75
Reputation: 198
It was possible to implement processing of spaces and hiding passwords behind spaces. Thus, it was possible to check data during input and hide the entered data.
In the future, correction of incorrect input using other keys is necessary.
C language:
#include <form.h>
#include <stdio.h>
#define SIZEPASS 20
int main() {
initscr();
raw();
noecho();
curs_set(2);
WINDOW *win = newwin(5, 40, 10, 10);
keypad(win, TRUE);
box(win, 0, 0);
wrefresh(win);
FIELD *fields[2];
fields[0] = new_field(1, SIZEPASS, 2, 2, 0, 0);
fields[1] = NULL;
set_field_type(fields[0], TYPE_REGEXP, "^\\\\*[0-9A-Za-z*]* *$");
set_field_opts(fields[0], O_VISIBLE | O_PUBLIC | O_EDIT | O_ACTIVE);
set_field_back(fields[0], A_UNDERLINE);
FORM *form = new_form(fields);
set_form_win(form, win);
set_form_sub(form, derwin(win, 3, 38, 1, 1));
post_form(form);
wrefresh(win);
char password[SIZEPASS] = {};
int ch, status, count = 0, stop = 0;
while (!stop && (ch = wgetch(win)) != KEY_F(2)) {
switch (ch) {
case KEY_BACKSPACE:
form_driver(form, REQ_DEL_PREV);
if (count)
password[--count] = '\0';
break;
case 32:
break;
case 10:
case KEY_ENTER:
stop = 1;
break;
default:
status = form_driver(form, ch);
if( status == E_OK ) {
status = form_driver(form, REQ_VALIDATION);
}
if (status == E_INVALID_FIELD) {
form_driver(form, REQ_DEL_PREV);
} else {
password[count++] = (char)ch;
password[count] = '\0';
form_driver(form, REQ_DEL_PREV);
form_driver(form, '*');
}
}
}
unpost_form(form);
free_form(form);
free_field(fields[0]);
endwin();
printf("Password: %s\n", password);
return 0;
}
D language:
module source.app;
import std.conv;
import std.string;
import std.stdio;
public import deimos.ncurses;
public import deimos.form;
public import core.stdc.locale;
int main(string[] args) {
setlocale(LC_CTYPE,"");
initscr();
raw();
noecho();
curs_set(2);
WINDOW *win = newwin(5, 40, 10, 10);
keypad(win, TRUE);
box(win, 0, 0);
wrefresh(win);
FIELD*[2] fields;
fields[0] = new_field(1, 20, 2, 2, 0, 0);
fields[1] = null;
set_field_type(fields[0], TYPE_REGEXP, `^\**[0-9A-Za-z*]* *$`.ptr);
set_field_opts(fields[0], O_VISIBLE | O_PUBLIC | O_EDIT | O_ACTIVE);
set_field_back(fields[0], A_UNDERLINE);
FORM *form = new_form(cast(FIELD**)fields);
set_form_win(form, win);
set_form_sub(form, derwin(win, 3, 38, 1, 1));
post_form(form);
wrefresh(win);
string password;
bool stop = false;
int ch, status;
while (!stop && (ch = wgetch(win)) != KEY_F(2)) {
switch (ch) {
case KEY_BACKSPACE:
form_driver(form, REQ_DEL_PREV);
if (password.length)
password = password[0 .. $ - 1];
break;
case 32:
break;
case 10:
case KEY_ENTER:
stop = true;
break;
default:
status = form_driver(form, ch);
if( status == E_OK ) {
status = form_driver(form, REQ_VALIDATION);
}
if (status == E_INVALID_FIELD) {
form_driver(form, REQ_DEL_PREV);
} else {
password ~= ch.to!char;
form_driver(form, REQ_DEL_PREV);
form_driver(form, '*'.to!int);
}
break;
}
}
unpost_form(form);
free_form(form);
free_field(fields[0]);
endwin();
writeln("Password: " ~ password);
return 0;
}
Implementation of wide characters in C (maybe it will be useful for someone searching).
D language (wide char, unicode):
module source.app;
import std.conv;
import std.string;
import std.stdio;
public import deimos.ncurses;
public import deimos.form;
public import core.stdc.locale;
int main(string[] args) {
setlocale(LC_ALL,"");
initscr();
raw();
noecho();
curs_set(2);
WINDOW *win = newwin(5, 40, 10, 10);
keypad(win, TRUE);
box(win, 0, 0);
wrefresh(win);
FIELD*[2] fields;
fields[0] = new_field(1, 20, 2, 2, 0, 0);
fields[1] = null;
set_field_type(fields[0], TYPE_REGEXP, `^\**[0-9A-Za-zА-Яа-я*]* *$`.ptr);
set_field_opts(fields[0], O_VISIBLE | O_PUBLIC | O_EDIT | O_ACTIVE);
set_field_back(fields[0], A_UNDERLINE);
FORM *form = new_form(cast(FIELD**)fields);
set_form_win(form, win);
set_form_sub(form, derwin(win, 3, 38, 1, 1));
post_form(form);
wrefresh(win);
dstring password;
bool stop = false;
int status;
dchar ch;
int ret;
while (!stop) {
ret = wget_wch(win, &ch);
switch (ret) {
case KEY_CODE_YES:
break;
case OK:
switch (ch) {
case KEY_BACKSPACE:
form_driver_w(form, KEY_CODE_YES, REQ_DEL_PREV);
if (password.length)
password = password[0 .. $ - 1];
break;
case 32:
break;
case 10:
case KEY_ENTER:
stop = true;
break;
default:
status = form_driver_w(form, OK, ch);
if( status == OK ) {
status = form_driver_w(form, KEY_CODE_YES, REQ_VALIDATION);
if (status == OK) {
password ~= ch.to!dchar;
form_driver_w(form, KEY_CODE_YES, REQ_DEL_PREV);
form_driver_w(form, OK, '*'.to!int);
} else {
status = form_driver_w(form, KEY_CODE_YES, REQ_DEL_PREV);
}
}
}
break;
default:
break;
}
}
unpost_form(form);
free_form(form);
free_field(fields[0]);
endwin();
writefln("Password: %s\n", password);
return 0;
}
Upvotes: 0
Reputation: 9894
two issues:
form_driver(form, ch)
doesn't validate the fields, only form_driver(form, REQ_VALIDATION);
doesfield[0}
must be completely filled with digits, so validation would cause an error as long as you haven't typed 20 digits. From man set_field_optsPlease notice that the regular expression must match the whole field. If you have for example an eight character wide field, a regular expression "^[0-9]$" always means that you have to fill all eight positions with digits. If you want to allow fewer digits, you may use for example "^[0-9] *$" which is good for trailing spaces (up to an empty field), or "^ [0-9] *$" which is good for leading and trailing spaces around the digits.
Regarding these points I have modifield your code like that:
#include <form.h>
int main() {
initscr();
curs_set(1);
WINDOW *win = newwin(5, 40, 10, 10);
keypad(win, TRUE);
box(win, 0, 0);
wrefresh(win);
FIELD *fields[2];
fields[0] = new_field(1, 20, 2, 2, 0, 0);
fields[1] = NULL;
set_field_type(fields[0], TYPE_REGEXP, "^[0-9]* *$");
set_field_opts(fields[0], O_VISIBLE | O_ACTIVE | O_EDIT);
FORM *form = new_form(fields);
set_form_win(form, win);
set_form_sub(form, derwin(win, 3, 38, 1, 1));
post_form(form);
wrefresh(win);
int ch;
while ((ch = wgetch(win)) != KEY_F(1)) {
int status = form_driver(form, ch);
if( status == E_OK ) {
status = form_driver(form, REQ_VALIDATION);
}
if (status == E_INVALID_FIELD) {
// handle invalid input
fprintf( stderr, "invalid input: %c\n", ch );
} else if (status == E_OK) {
wrefresh(win);
}
}
unpost_form(form);
free_form(form);
free_field(fields[0]);
endwin();
return 0;
}
When you run that and type 31K you will get on stderr
invalid input: K
Upvotes: 1