module examples.ncurses.password; import std.conv; // Импорт модуля для преобразования типов import std.string; // Импорт модуля для работы со строками import std.stdio; // Импорт модуля для ввода-вывода import deimos.ncurses; // Импорт библиотеки ncurses для работы с терминалом import deimos.form; // Импорт библиотеки форм ncurses для создания полей ввода import core.stdc.locale; // Импорт для работы с локализацией // Определение констант для цветовых пар enum { COLOR_WINDOW = 1, // Идентификатор цветовой пары для окна COLOR_BACKGROUND = 2 // Идентификатор цветовой пары для фона } void passwordNcurses() { // Установка локали для корректного отображения символов (например, кириллицы) setlocale(LC_ALL, ""); // Инициализация ncurses initscr(); // Включение режима raw (сырой ввод, без обработки специальных символов) raw(); // Отключение эха ввода (символы не отображаются при вводе) noecho(); // Установка видимости курсора (2 — полностью видимый курсор) curs_set(2); // Инициализация цветового режима start_color(); // Определение цветовых пар: текст/фон init_pair(COLOR_WINDOW, COLOR_WHITE, COLOR_RED); // Белый текст на красном фоне init_pair(COLOR_BACKGROUND, COLOR_WHITE, COLOR_BLUE); // Белый текст на синем фоне // Получение размеров терминала (высота и ширина) int width, height; getmaxyx(stdscr, height, width); // Установка фона для основного окна (stdscr) с использованием цветовой пары COLOR_BACKGROUND bkgd(COLOR_PAIR(COLOR_BACKGROUND)); // Обновление экрана для отображения изменений refresh(); // Создание нового окна размером 5x44, центрированного на экране WINDOW* win = newwin(5, 44, height / 2 - 3, width / 2 - 22); // Включение обработки специальных клавиш (например, Backspace) для окна keypad(win, TRUE); // Отрисовка рамки вокруг окна box(win, 0, 0); // Установка фона окна с использованием цветовой пары COLOR_WINDOW wbkgd(win, COLOR_PAIR(COLOR_WINDOW)); // Обновление окна для отображения изменений wrefresh(win); // Создание массива полей формы (два поля: метка и поле ввода пароля) FIELD*[3] fields; // Поле для статической метки "Введите пароль:" fields[0] = new_field(1, 16, 0, 2, 0, 0); // Поле для ввода пароля fields[1] = new_field(1, 20, 0, 18, 0, 0); // Завершающий нулевой указатель для массива полей fields[2] = null; // Установка текста метки в первом поле set_field_buffer(fields[0], 0, "Введите пароль:"); // Настройка первого поля: видимое, публичное, автопропуск (нельзя редактировать) set_field_opts(fields[0], O_VISIBLE | O_PUBLIC | O_AUTOSKIP); // Установка типа второго поля: регулярное выражение для валидации ввода // Разрешены буквы, цифры, некоторые символы и пробелы set_field_type(fields[1], TYPE_REGEXP, `^\**[-0-9A-Za-zА-Яа-я*,./!?%&#:$^_=+@~\]* *$`.ptr); // Настройка второго поля: видимое, публичное, редактируемое, активно set_field_opts(fields[1], O_VISIBLE | O_PUBLIC | O_EDIT | O_ACTIVE); // Установка фона для первого поля (цветовая пара COLOR_WINDOW) set_field_back(fields[0], COLOR_PAIR(COLOR_WINDOW)); // Установка фона и подчеркивания для второго поля set_field_back(fields[1], COLOR_PAIR(COLOR_WINDOW) | A_UNDERLINE); // Создание формы на основе массива полей FORM* form = new_form(cast(FIELD**) fields); // Установка основного окна для формы set_form_win(form, win); // Установка подокна для формы (область внутри окна для ввода) set_form_sub(form, derwin(win, 1, 38, 2, 2)); // Отображение формы на экране post_form(form); // Обновление окна для отображения изменений wrefresh(win); // Переменная для хранения введенного пароля (в формате dstring для поддержки Unicode) dstring password; // Флаг для выхода из цикла ввода bool stop = false; // Переменная для хранения статуса операций с формой int status; // Переменная для хранения введенного символа dchar ch; // Переменная для хранения результата ввода int ret; // Основной цикл обработки ввода while (!stop) { // Получение символа или кода клавиши из окна ret = wget_wch(win, &ch); switch (ret) { case KEY_CODE_YES: // Обработка специальных клавиш (например, Backspace) switch (ch) { case KEY_BACKSPACE: // Нажата клавиша Backspace // Удаление предыдущего символа из формы form_driver_w(form, KEY_CODE_YES, REQ_DEL_PREV); // Удаление последнего символа из строки пароля, если она не пуста if (password.length) password = password[0 .. $ - 1]; break; default: // Игнорирование других специальных клавиш break; } break; case OK: // Обработка обычных символов switch (ch) { case KEY_BACKSPACE: // Нажата клавиша Backspace (альтернативный код) // Удаление предыдущего символа из формы form_driver_w(form, KEY_CODE_YES, REQ_DEL_PREV); // Удаление последнего символа из строки пароля, если она не пуста if (password.length) password = password[0 .. $ - 1]; break; case 32: // Пробел (игнорируется) break; case 10: // Нажата клавиша Enter case KEY_ENTER: // Альтернативный код для 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; } break; default: // Игнорирование других случаев break; } } // Снятие формы с экрана unpost_form(form); // Освобождение памяти, занятой формой free_form(form); // Освобождение памяти, занятой полями free_field(fields[0]); free_field(fields[1]); // Завершение работы ncurses и очистка экрана endwin(); // Вывод введенного пароля в консоль writefln("Password: %s\n", password); }