commit 9561520270f004205a396088c25015b1f4e010d5 Author: Alexander Zhirov Date: Sun Oct 13 01:08:40 2024 +0300 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c41c69c --- /dev/null +++ b/.gitignore @@ -0,0 +1,18 @@ +.dub +docs.json +__dummy.html +docs/ +/ncurses-examples +ncurses-examples.so +ncurses-examples.dylib +ncurses-examples.dll +ncurses-examples.a +ncurses-examples.lib +ncurses-examples-test-* +*.exe +*.pdb +*.o +*.obj +*.lst +/bin +/.vscode \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..3842462 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# Примеры кода Ncurses diff --git a/dub.json b/dub.json new file mode 100644 index 0000000..e26592b --- /dev/null +++ b/dub.json @@ -0,0 +1,23 @@ +{ + "authors": [ + "Alexander Zhirov" + ], + "copyright": "Copyright © 2024, Alexander Zhirov", + "description": "Ncurses examples code", + "license": "GPL-2.0", + "name": "ncurses-examples", + "targetPath": "bin", + "targetType": "executable", + "dependencies": { + "ncurses": "~>1.0.0", + "singlog": "~>0.5.0" + }, + "libs": [ + "pam", + "formw" + ], + "postBuildCommands": [ + "ln -sf ncurses-examples bin/password", + "ln -sf ncurses-examples bin/menu" + ] +} \ No newline at end of file diff --git a/dub.selections.json b/dub.selections.json new file mode 100644 index 0000000..0ede166 --- /dev/null +++ b/dub.selections.json @@ -0,0 +1,8 @@ +{ + "fileVersion": 1, + "versions": { + "datefmt": "1.0.4", + "ncurses": "1.0.0", + "singlog": "0.5.0" + } +} diff --git a/source/app.d b/source/app.d new file mode 100644 index 0000000..579f6a2 --- /dev/null +++ b/source/app.d @@ -0,0 +1,24 @@ +module source.app; + +import singlog; + +import window; +import std.path; + +void main(string[] args) { + log.output(log.output.file) + .program(baseName(args[0])) + .level(log.level.debugging) + .file("/tmp/" ~ baseName(args[0]) ~ ".log"); + + switch (baseName(args[0])) { + case "password": + password(); + break; + case "menu": + menu(); + break; + default: + break; + } +} diff --git a/source/window/menu.d b/source/window/menu.d new file mode 100644 index 0000000..23439eb --- /dev/null +++ b/source/window/menu.d @@ -0,0 +1,75 @@ +module window.menu; + +import singlog; +import std.conv; +import std.string; + +import std.stdio; + +public import deimos.ncurses; +public import deimos.form; +public import core.stdc.locale; + +enum { + COLOR_WINDOW = 1, + COLOR_BACKGROUND = 2 +} + +void menu() { + setlocale(LC_ALL,""); + initscr(); + raw(); + noecho(); + curs_set(0); + + 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); + + bkgd(COLOR_PAIR(COLOR_BACKGROUND)); + + refresh(); + + WINDOW *win = newwin(7, 16, height/2 - 4, width/2 - 8); + keypad(win, TRUE); + box(win, 0, 0); + wbkgd(win, COLOR_PAIR(COLOR_WINDOW)); + wrefresh(win); + + string[] items = ["Пункт 1", "Пункт 2", "Пункт 3", "Пункт 4", "Пункт 5"]; + int current_item = 0; + int count_items = items.length.to!int; + int ch; + + do { + switch (ch) { + case KEY_UP: + current_item = (current_item - 1 + count_items) % count_items; + break; + case KEY_DOWN: + current_item = (current_item + 1) % count_items; + break; + case 10: + case KEY_ENTER: + log.i(items[current_item]); + break; + default: + break; + } + + foreach (i, item; items) { + if (i == current_item) { + wattron(win, A_REVERSE); + } + mvwprintw(win, i.to!int + 1, 4, item.toStringz); + wattroff(win, A_REVERSE); + } + + wrefresh(win); + } while ((ch = wgetch(win)) != KEY_F(2)); + + endwin(); +} diff --git a/source/window/package.d b/source/window/package.d new file mode 100644 index 0000000..e39411d --- /dev/null +++ b/source/window/package.d @@ -0,0 +1,4 @@ +module window; + +public import window.password; +public import window.menu; diff --git a/source/window/password.d b/source/window/password.d new file mode 100644 index 0000000..adc6a8b --- /dev/null +++ b/source/window/password.d @@ -0,0 +1,119 @@ +module window.password; + +import std.conv; +import std.string; + +import std.stdio; + +public import deimos.ncurses; +public import deimos.form; +public import core.stdc.locale; + +enum { + COLOR_WINDOW = 1, + COLOR_BACKGROUND = 2 +} + +void password() { + setlocale(LC_ALL,""); + initscr(); + raw(); + noecho(); + 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); + + bkgd(COLOR_PAIR(COLOR_BACKGROUND)); + + refresh(); + + WINDOW *win = newwin(5, 44, height/2 - 3, width/2 - 22); + keypad(win, TRUE); + box(win, 0, 0); + 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); + 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 password; + bool stop = false; + + int status; + + dchar ch; + int ret; + + while (!stop) { + ret = wget_wch(win, &ch); + switch (ret) { + case KEY_CODE_YES: + switch (ch) { + case KEY_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: + 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]); + free_field(fields[1]); + endwin(); + + writefln("Password: %s\n", password); +}