LINUX.ORG.RU

Реализация окна ввода пароля на ncurses

 , ,


1

1

Всем привет!

В рамках своей разработки вынес отдельно пример кода, который реализует форму ввода. Хочу сделать ввод пароля в виде скрытых символов. Разобрался, что можно использовать регулярку в данном случае. В общем, попытался с простого примера:

#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) {
            form_driver(form, REQ_DEL_PREV);
        } else if (status == E_OK) {
            wrefresh(win);
        }
    }

    unpost_form(form);
    free_form(form);
    free_field(fields[0]);
    endwin();

    return 0;
}

Вводим пока что любые цифры. Не разобрался, как обойти ввод пробелов. Также при вводе некорректного символа пытаюсь его удалить, но form_driver удаляет его в бэке, а на фронте оставляет символ под курсором. Не думаю, что похоже на баг. Скорее всего необходима правильная реализация по удалению.

В общем, гуглил примеры работы с формами ввода, ничего толкового не удалось найти. Прошу помощи гуру. Спасибо!

Ответ на: комментарий от beastie

Как нибудь.

В общем, разобрался.

#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[1], 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;
}
azhirov1991
() автор топика
Ответ на: комментарий от azhirov1991

Реализация на D (с поддержкой широких символов, юникода). Вдруг кому пригодится на просторах интернета, потому что я ничего не находил.

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;
}
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;
}
azhirov1991
() автор топика