diff --git a/src/editor_easy.cpp b/src/editor_easy.cpp index 6d12ba0..b7230f5 100644 --- a/src/editor_easy.cpp +++ b/src/editor_easy.cpp @@ -1,17 +1,22 @@ +#include +#include #include #include -#include -#include // C++20/C++23 feature -#include +#include #include #include +#include "gameske_funkce.h" +#include "memory.h" -#define WHITE_ON_BLUE 9 -#define BLACK_ON_WHITE 10 +#define HEADER_COLOR_PAIR COLOR_RED +#define FIELD_NAME_COLOR_PAIR 10 +#define INPUT_COLOR_PAIR 11 + +std::vector editor_easy_allocated; [[nodiscard]] std::string vytvorTrestniOznameni() { - // Pomocná funkce pro ořezání mezer (ncurses vyplňuje pole mezerami) - auto trim = [](const char *str) -> std::string { + current_allocated = &editor_easy_allocated; + auto trim = [](const char* str) -> std::string { std::string s(str); if (s.empty()) return s; @@ -22,199 +27,205 @@ return s.substr(start, end - start + 1); }; - init_pair(WHITE_ON_BLUE, COLOR_WHITE, COLOR_BLUE); - init_pair(BLACK_ON_WHITE, COLOR_BLACK, COLOR_WHITE); + curs_set(1); - // Velikost terminalu - int max_y, max_x; - getmaxyx(stdscr, max_y, max_x); + // Minimální velikost terminálu + const int MIN_WIDTH = 90; + const int MIN_HEIGHT = 28; + if (COLS < MIN_WIDTH || LINES < MIN_HEIGHT) { + endwin(); + throw std::runtime_error("Minimální velikost terminálu: 90x28"); + } - echo(); + // Nastavení barev + start_color(); + init_pair(FIELD_NAME_COLOR_PAIR, COLOR_BLACK, COLOR_CYAN); // Popisky + init_pair(INPUT_COLOR_PAIR, COLOR_WHITE, COLOR_BLACK); // Vstupní pole - // Nadpis - attron(COLOR_PAIR(WHITE_ON_BLUE)); - mvprintw(0, 0, "TRESTNÍ OZNÁMENÍ - ZADÁNÍ ÚDAJŮ"); - for (int i = strlen("TRESTNÍ OZNÁMENÍ - ZADÁNÍ ÚDAJŮ"); i < max_x; i++) - addch(' '); - attroff(COLOR_PAIR(WHITE_ON_BLUE)); + // Hlavní okno s rámečkem + WINDOW* main_win = newwin(LINES - 4, COLS - 4, 2, 2); + box(main_win, 0, 0); + wrefresh(main_win); - // Vytvoření polí formuláře - const int NUM_FIELDS = 10; - FIELD *fields[NUM_FIELDS + 1]; // +1 pro NULL terminátor + // Okno pro popisky + WINDOW* label_win = derwin(main_win, LINES - 8, 30, 1, 1); + wbkgd(label_win, COLOR_PAIR(FIELD_NAME_COLOR_PAIR)); - // Definice popisků a vlastností polí - struct FieldInfo { - const char *label; + // Okno pro vstupní pole + WINDOW* field_win = derwin(main_win, LINES - 8, COLS - 38, 1, 32); + wbkgd(field_win, COLOR_PAIR(INPUT_COLOR_PAIR)); + keypad(field_win, TRUE); + + // Definice polí + struct FieldConfig { + const char* label; int height; int width; bool multiline; }; - FieldInfo field_info[NUM_FIELDS] = { - {"Jméno a příjmení:", 1, 40, false}, - {"Adresa:", 1, 50, false}, - {"Telefon:", 1, 20, false}, - {"Email:", 1, 30, false}, - {"Místo činu:", 1, 40, false}, - {"Datum činu (dd.mm.rrrr):", 1, 15, false}, - {"Popis činu:", 5, 60, true}, - {"Jméno pachatele (pokud známo):", 1, 40, false}, - {"Důkazy:", 4, 60, true}, - {"Další informace:", 3, 60, true}}; + FieldConfig field_configs[] = { + {"Jméno", 1, 40, false}, {"Adresa:", 1, 50, false}, + {"Telefon:", 1, 20, false}, {"Email:", 1, 30, false}, + {"Místo činu:", 1, 40, false}, {"Datum činu (dd.mm.rrrr):", 1, 15, false}, + {"Popis činu:", 5, 60, true}, {"Jméno pachatele:", 1, 40, false}, + {"Důkazy:", 4, 60, true}, {"Další informace:", 3, 60, true}}; - // Vytvoření polí - int row = 2; - for (int i = 0; i < NUM_FIELDS; i++) { - mvprintw(row, 2, "%s", field_info[i].label); - - fields[i] = new_field(field_info[i].height, field_info[i].width, row, - 30, // Začátek pole po popisku - 0, 0); - - // Nastavení vlastností pole - set_field_back(fields[i], A_UNDERLINE); - field_opts_off(fields[i], O_AUTOSKIP); - - // Pro víceřádková pole - if (field_info[i].multiline) { - field_opts_off(fields[i], O_STATIC); - field_opts_on(fields[i], O_WRAP); - } - - row += field_info[i].height + 1; + // Vykreslení popisků + int label_row = 0; + for (const FieldConfig& cfg : field_configs) { + mvwprintw(label_win, label_row, 0, "%s", cfg.label); + label_row += cfg.height + 1; } - fields[NUM_FIELDS] = NULL; + wrefresh(label_win); // Vytvoření formuláře - FORM *form = new_form(fields); + std::vector fields; + int field_row = 0; - // Vytvoření oken pro formulář - WINDOW *win_body = newwin(max_y, max_x, 0, 0); - WINDOW *win_form = derwin(win_body, max_y - 5, max_x - 4, 1, 2); + for (const FieldConfig& cfg : field_configs) { + FIELD* field = new_field(cfg.height, cfg.width, field_row, 0, 0, 0); + set_field_back(field, A_UNDERLINE | COLOR_PAIR(INPUT_COLOR_PAIR)); + field_opts_off(field, O_AUTOSKIP | O_STATIC); - // Přiřazení oken k formuláři - set_form_win(form, win_body); - set_form_sub(form, win_form); - - // Zobrazení formuláře - post_form(form); - - // Zobrazení instrukcí - mvprintw(max_y - 3, 2, - "Navigace: šipky - pohyb | Tab - další pole | Enter - nový řádek | " - "F10 - uložit"); - - refresh(); - wrefresh(win_body); - - // Zpracování vstupu od uživatele - int ch; - while ((ch = getch()) != KEY_F(10)) { - switch (ch) { - case KEY_DOWN: - form_driver(form, REQ_NEXT_FIELD); - form_driver(form, REQ_END_LINE); - break; - case KEY_UP: - form_driver(form, REQ_PREV_FIELD); - form_driver(form, REQ_END_LINE); - break; - case KEY_LEFT: - form_driver(form, REQ_PREV_CHAR); - break; - case KEY_RIGHT: - form_driver(form, REQ_NEXT_CHAR); - break; - case KEY_BACKSPACE: - case 127: - form_driver(form, REQ_DEL_PREV); - break; - case KEY_DC: - form_driver(form, REQ_DEL_CHAR); - break; - case 10: // Enter key - case KEY_ENTER: { - int idx = field_index(current_field(form)); - if (field_info[idx].multiline) { - form_driver(form, REQ_NEW_LINE); - } else { - form_driver(form, REQ_NEXT_FIELD); - form_driver(form, REQ_END_LINE); - } - } break; - case '\t': - form_driver(form, REQ_NEXT_FIELD); - form_driver(form, REQ_END_LINE); - break; - case KEY_BTAB: - form_driver(form, REQ_PREV_FIELD); - form_driver(form, REQ_END_LINE); - break; - case KEY_HOME: - form_driver(form, REQ_BEG_LINE); - break; - case KEY_END: - form_driver(form, REQ_END_LINE); - break; - default: - form_driver(form, ch); - break; + if (cfg.multiline) { + field_opts_on(field, O_WRAP); + set_max_field(field, 500); } - wrefresh(win_form); - wrefresh(win_body); + fields.push_back(field); + field_row += cfg.height + 1; + } + fields.push_back(nullptr); + + FORM* form = new_form(&fields[0]); + set_form_win(form, field_win); + set_form_sub(form, derwin(field_win, LINES - 10, COLS - 40, 1, 1)); + + post_form(form); + form_driver(form, REQ_FIRST_FIELD); + + // Hlavička + attron(COLOR_PAIR(HEADER_COLOR_PAIR)); + mvprintw(0, (COLS - 40) / 2, "TRESTNÍ OZNÁMENÍ - ZADÁNÍ ÚDAJŮ"); + mvprintw(1, 2, "Vyplňte všechny údaje a stiskněte F10 pro dokončení"); + refresh(); + + // Hlavní smyčka + int ch; + bool exit_loop = false; + while (!exit_loop && (ch = wgetch(field_win))) { + switch (ch) { + case KEY_F(10): + exit_loop = true; + break; + + case KEY_DOWN: + form_driver(form, REQ_NEXT_FIELD); + form_driver(form, REQ_END_LINE); + break; + + case KEY_UP: + form_driver(form, REQ_PREV_FIELD); + form_driver(form, REQ_END_LINE); + break; + + case KEY_LEFT: + form_driver(form, REQ_PREV_CHAR); + break; + + case KEY_RIGHT: + form_driver(form, REQ_NEXT_CHAR); + break; + + case KEY_BACKSPACE: + case 127: + form_driver(form, REQ_DEL_PREV); + break; + + case KEY_DC: + form_driver(form, REQ_DEL_CHAR); + break; + + case 10: // Enter + if (field_configs[current_field(form)->index].multiline) { + form_driver(form, REQ_NEW_LINE); + } else { + form_driver(form, REQ_NEXT_FIELD); + } + break; + + case '\t': + form_driver(form, REQ_NEXT_FIELD); + break; + + case KEY_BTAB: + form_driver(form, REQ_PREV_FIELD); + break; + + default: + form_driver(form, ch); + break; + } + + // Ruční aktualizace všech oken + touchwin(main_win); + wrefresh(main_win); + wrefresh(label_win); + wrefresh(field_win); } - // Validace před čtením dat (důležité pro získání aktuálních hodnot)[1][5] + // Získání dat form_driver(form, REQ_VALIDATION); - - // Sběr dat z formuláře std::vector field_values; - for (int i = 0; i < NUM_FIELDS; i++) { - char *buffer = field_buffer(fields[i], 0); - field_values.push_back(trim(buffer)); + for (size_t i = 0; i < ARRAY_SIZE(field_configs); i++) { + field_values.push_back(trim(field_buffer(fields[i], 0))); } - // Uvolnění prostředků + // Úklid unpost_form(form); free_form(form); - for (int i = 0; i < NUM_FIELDS; i++) { - free_field(fields[i]); - } - delwin(win_form); - delwin(win_body); - endwin(); + for (fieldnode*& f : fields) + if (f) + free_field(f); + delwin(label_win); + delwin(field_win); + delwin(main_win); + curs_set(0); + clear(); // Aktuální datum std::time_t t = std::time(nullptr); - std::tm *now = std::localtime(&t); + std::tm* now = std::localtime(&t); char date_str[100]; std::strftime(date_str, sizeof(date_str), "%d.%m.%Y", now); // Formátování trestního oznámení pomocí std::format (C++20/C++23) - std::string complaint = - std::format(R"( -TRESTNÍ OZNÁMENÍ - -Policie České republiky -Krajské ředitelství policie -Obvodní oddělení + std::string complaint = std::format( + R"( +VÝZVA K UPUŠTĚNÍ OD PROTIPRÁVNÍHO JEDNÁNÍ V {} dne {} -Oznamovatel: +Adresát: Jméno a příjmení: {} Adresa: {} Telefon: {} Email: {} -Věc: Oznámení o skutečnostech nasvědčujících tomu, že byl spáchán trestný čin +Odesílatel: +Jméno a příjmení: {} +Adresa: {} +Telefon: {} +Email: {} + +Věc: Výzva k okamžitému upuštění od protiprávního jednání {} -K trestnému činu došlo dne {} v {}. +K protiprávnímu jednání došlo dne {} v {}. -Popis skutku: +Popis protiprávního jednání: {} Důkazy: @@ -223,31 +234,43 @@ Důkazy: Další informace: {} -S úctou, +Pokud neupustíte od výše uvedeného jednání, budu nucen/a podniknout další právní kroky, včetně podání trestního oznámení a vymáhání náhrady škody. + +S pozdravem, ............................ {} -(podpis oznamovatele) +(podpis) + +*Toto není právní dokument, ale pouze vzor pro informativní účely. Pro právní poradenství se obraťte na kvalifikovaného právníka.* )", - field_values[4], // Místo - date_str, // Aktuální datum - field_values[0], // Jméno a příjmení - field_values[1], // Adresa - field_values[2], // Telefon - field_values[3], // Email - field_values[7].empty() - ? "Tímto podávám trestní oznámení na neznámého pachatele " - "pro podezření ze spáchání trestného činu." - : std::format("Tímto podávám trestní oznámení na: {} pro " - "podezření ze spáchání trestného činu.", - field_values[7]), - field_values[5], // Datum činu - field_values[4], // Místo činu - field_values[6], // Popis činu - field_values[8], // Důkazy - field_values[9], // Další informace - field_values[0] // Jméno pro podpis - ); - noecho(); + field_values[4], // Místo + date_str, // Aktuální datum + field_values[7], // Jméno a příjmení adresáta + field_values[10], // Adresa adresáta (přidejte do pole) + field_values[11], // Telefon adresáta (přidejte do pole) + field_values[12], // Email adresáta (přidejte do pole) + + // Odesílatel + field_values[0], // Jméno a příjmení odesílatele + field_values[1], // Adresa odesílatele + field_values[2], // Telefon odesílatele + field_values[3], // Email odesílatele + + field_values[7].empty() + ? "Tímto Vás vyzývám, abyste okamžitě upustil/a od protiprávního " + "jednání." + : std::format("Tímto Vás, {}, vyzývám, abyste okamžitě upustil/a od " + "protiprávního jednání.", + field_values[7]), + + field_values[5], // Datum činu + field_values[4], // Místo činu + field_values[6], // Popis činu + field_values[8], // Důkazy + field_values[9], // Další informace + field_values[0] // Jméno pro podpis + ); + return complaint; }