improved memory safety + misc QOL changes
Some checks failed
build_test / build (push) Failing after 2m8s
Some checks failed
build_test / build (push) Failing after 2m8s
This commit is contained in:
parent
2f2ec79575
commit
c3074bc8d4
6
Makefile
6
Makefile
@ -2,6 +2,7 @@
|
||||
CPPC = g++
|
||||
CPPC_FLAGS = -std=c++23 -s -O3 -Wall -Wextra -Wno-write-strings -lncurses -lmenu -lform -lcups
|
||||
DEBUG_FLAGS = -ggdb -std=c++23 -Wall -Wextra -Wno-write-strings -lncurses -lmenu -lform -lcups
|
||||
DEBUG_ASANITIZE = -fsanitize=address -ggdb -fno-omit-frame-pointer -std=c++23 -lncurses -lmenu -lcups -Wall -Wextra -Wno-write-strings
|
||||
|
||||
|
||||
SRC_PATH := src
|
||||
@ -19,6 +20,9 @@ all: make-build-dir $(BIN_PATH)/ParaDocs
|
||||
debug: CPPC_FLAGS = $(DEBUG_FLAGS)
|
||||
debug: make-build-dir $(BIN_PATH)/ParaDocs
|
||||
|
||||
asan: CPPC_FLAGS = $(DEBUG_ASANITIZE)
|
||||
asan: make-build-dir $(BIN_PATH)/ParaDocs
|
||||
|
||||
|
||||
make-build-dir:
|
||||
mkdir -p $(OBJ_PATH)
|
||||
@ -39,4 +43,4 @@ install:
|
||||
clean:
|
||||
rm -fr build
|
||||
|
||||
.PHONY: all clean install debug
|
||||
.PHONY: all clean install debug asan
|
||||
|
13
src/const.h
13
src/const.h
@ -1,7 +1,20 @@
|
||||
|
||||
#include <string_view>
|
||||
#ifndef NAME
|
||||
|
||||
#define NAME "ParaDocs"
|
||||
#define VERSION "0.0.1"
|
||||
|
||||
inline constexpr auto hash_djb2a(const std::string_view sv) {
|
||||
unsigned long hash{5381};
|
||||
for (unsigned char c : sv) {
|
||||
hash = ((hash << 5) + hash) ^ c;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
inline constexpr auto operator"" _sh(const char* str, size_t len) {
|
||||
return hash_djb2a(std::string_view{str, len});
|
||||
}
|
||||
|
||||
#endif
|
102
src/cups.cpp
102
src/cups.cpp
@ -5,22 +5,16 @@
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "memory.h"
|
||||
#include "types.h"
|
||||
|
||||
std::vector<allocation> cups_allocated;
|
||||
|
||||
/**
|
||||
* Displays a menu of available printers and prints content to the selected one
|
||||
* @param content The text content to print
|
||||
* @return true if printing was successful, false otherwise
|
||||
*/
|
||||
bool printDocument(const std::string& content) {
|
||||
current_allocated = &cups_allocated;
|
||||
// Initialize variables
|
||||
bool success = false;
|
||||
cups_dest_t* dests = nullptr;
|
||||
int num_dests = 0;
|
||||
ITEM** menu_items = nullptr;
|
||||
MENU* menu = nullptr;
|
||||
WINDOW* menu_win = nullptr;
|
||||
std::vector<char*> item_names;
|
||||
std::vector<char*> item_descriptions;
|
||||
complete_menu printer_menu = {nullptr, nullptr, 0, nullptr};
|
||||
|
||||
// Write content to a temporary file
|
||||
std::string tempFileName = "/tmp/print_temp_ParaDocs.txt";
|
||||
@ -32,12 +26,20 @@ bool printDocument(const std::string& content) {
|
||||
tempFile.close();
|
||||
|
||||
// Get printer destinations from CUPS
|
||||
num_dests = cupsGetDests(&dests);
|
||||
cups_dest_t* dests = nullptr;
|
||||
int num_dests = cupsGetDests(&dests);
|
||||
if (num_dests <= 0) {
|
||||
remove(tempFileName.c_str());
|
||||
return false; // No printers available
|
||||
}
|
||||
|
||||
char** item_names = new char*[num_dests];
|
||||
cups_allocated.push_back(
|
||||
{CHAR_PTR_ARRAY, item_names, static_cast<size_t>(num_dests)});
|
||||
char** item_descriptions = new char*[num_dests];
|
||||
cups_allocated.push_back(
|
||||
{CHAR_PTR_ARRAY, item_descriptions, static_cast<size_t>(num_dests)});
|
||||
|
||||
// Initialize ncurses
|
||||
initscr();
|
||||
start_color();
|
||||
@ -47,7 +49,7 @@ bool printDocument(const std::string& content) {
|
||||
|
||||
try {
|
||||
// Allocate memory for menu items
|
||||
menu_items = new ITEM*[num_dests + 1];
|
||||
printer_menu.items = new ITEM*[num_dests + 1];
|
||||
|
||||
// Prepare menu items for each printer
|
||||
for (int i = 0; i < num_dests; i++) {
|
||||
@ -62,7 +64,7 @@ bool printDocument(const std::string& content) {
|
||||
// Allocate memory for name string
|
||||
char* name_str = new char[display_name.length() + 1];
|
||||
std::strcpy(name_str, display_name.c_str());
|
||||
item_names.push_back(name_str);
|
||||
item_names[i] = name_str;
|
||||
|
||||
// Get description if available
|
||||
const char* desc =
|
||||
@ -72,54 +74,55 @@ bool printDocument(const std::string& content) {
|
||||
// Allocate memory for description string
|
||||
char* desc_str = new char[description.length() + 1];
|
||||
std::strcpy(desc_str, description.c_str());
|
||||
item_descriptions.push_back(desc_str);
|
||||
item_descriptions[i] = desc_str;
|
||||
|
||||
// Create menu item
|
||||
menu_items[i] = new_item(name_str, desc_str);
|
||||
if (!menu_items[i]) {
|
||||
printer_menu.items[i] = new_item(name_str, desc_str);
|
||||
if (!printer_menu.items[i]) {
|
||||
throw std::runtime_error("Failed to create menu item");
|
||||
}
|
||||
}
|
||||
menu_items[num_dests] = nullptr; // NULL-terminate the array
|
||||
printer_menu.items[num_dests] = nullptr; // NULL-terminate the array
|
||||
|
||||
// Create the menu
|
||||
menu = new_menu(menu_items);
|
||||
if (!menu) {
|
||||
printer_menu.menu = new_menu(printer_menu.items);
|
||||
if (!printer_menu.menu) {
|
||||
throw std::runtime_error("Failed to create menu");
|
||||
}
|
||||
|
||||
// Set up menu window
|
||||
int rows, cols;
|
||||
getmaxyx(stdscr, rows, cols);
|
||||
menu_win = newwin(rows - 4, cols - 4, 2, 2);
|
||||
keypad(menu_win, TRUE);
|
||||
printer_menu.win = newwin(rows - 4, cols - 4, 2, 2);
|
||||
keypad(printer_menu.win, TRUE);
|
||||
|
||||
// Set menu window and sub window
|
||||
set_menu_win(menu, menu_win);
|
||||
set_menu_sub(menu, derwin(menu_win, rows - 6, cols - 6, 1, 1));
|
||||
set_menu_format(menu, rows - 8, 1);
|
||||
set_menu_mark(menu, " * ");
|
||||
set_menu_win(printer_menu.menu, printer_menu.win);
|
||||
set_menu_sub(printer_menu.menu,
|
||||
derwin(printer_menu.win, rows - 6, cols - 6, 1, 1));
|
||||
set_menu_format(printer_menu.menu, rows - 8, 1);
|
||||
set_menu_mark(printer_menu.menu, " * ");
|
||||
|
||||
// Post the menu with instructions
|
||||
mvprintw(0, 0, "Select a printer and press Enter:");
|
||||
mvprintw(rows - 2, 0, "Press q to cancel");
|
||||
refresh();
|
||||
post_menu(menu);
|
||||
wrefresh(menu_win);
|
||||
post_menu(printer_menu.menu);
|
||||
wrefresh(printer_menu.win);
|
||||
|
||||
// Menu interaction loop
|
||||
int c;
|
||||
while ((c = wgetch(menu_win)) != 'q') {
|
||||
while ((c = wgetch(printer_menu.win)) != 'q') {
|
||||
switch (c) {
|
||||
case KEY_DOWN:
|
||||
menu_driver(menu, REQ_DOWN_ITEM);
|
||||
menu_driver(printer_menu.menu, REQ_DOWN_ITEM);
|
||||
break;
|
||||
case KEY_UP:
|
||||
menu_driver(menu, REQ_UP_ITEM);
|
||||
menu_driver(printer_menu.menu, REQ_UP_ITEM);
|
||||
break;
|
||||
case 10: // Enter key
|
||||
{
|
||||
ITEM* cur = current_item(menu);
|
||||
ITEM* cur = current_item(printer_menu.menu);
|
||||
int index = item_index(cur);
|
||||
|
||||
// Print the document to the selected printer
|
||||
@ -142,7 +145,7 @@ bool printDocument(const std::string& content) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
wrefresh(menu_win);
|
||||
wrefresh(printer_menu.win);
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
mvprintw(0, 0, "Error: %s", e.what());
|
||||
@ -151,39 +154,16 @@ bool printDocument(const std::string& content) {
|
||||
}
|
||||
exit_menu:
|
||||
|
||||
// Clean up resources
|
||||
if (menu) {
|
||||
unpost_menu(menu);
|
||||
free_menu(menu);
|
||||
}
|
||||
|
||||
if (menu_items) {
|
||||
for (int i = 0; i < num_dests && menu_items[i]; i++) {
|
||||
free_item(menu_items[i]);
|
||||
}
|
||||
delete[] menu_items;
|
||||
}
|
||||
|
||||
// Free allocated strings
|
||||
for (char* str : item_names) {
|
||||
delete[] str;
|
||||
}
|
||||
for (char* str : item_descriptions) {
|
||||
delete[] str;
|
||||
}
|
||||
|
||||
if (menu_win) {
|
||||
delwin(menu_win);
|
||||
}
|
||||
|
||||
// End ncurses
|
||||
endwin();
|
||||
unpost_menu(printer_menu.menu);
|
||||
wclear(printer_menu.win);
|
||||
clear();
|
||||
|
||||
// Remove temp file
|
||||
remove(tempFileName.c_str());
|
||||
|
||||
// Free CUPS destinations
|
||||
cupsFreeDests(num_dests, dests);
|
||||
delete_all(&cups_allocated);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
@ -12,7 +12,9 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include "memory.h"
|
||||
|
||||
/*
|
||||
size_t spawn_menu(uint16_t begin_y, uint16_t begin_x, const char** choices,
|
||||
size_t n_choices) {
|
||||
ITEM** sp_items;
|
||||
@ -22,26 +24,26 @@ size_t spawn_menu(uint16_t begin_y, uint16_t begin_x, const char** choices,
|
||||
int i;
|
||||
|
||||
sp_items = new ITEM*[n_choices];
|
||||
/* Create items */
|
||||
// Create items
|
||||
for (i = 0; i < n_choices; ++i) {
|
||||
sp_items[i] = new_item(choices[i], choices[i]);
|
||||
}
|
||||
|
||||
/* Crate menu */
|
||||
// Crate menu
|
||||
sp_menu = new_menu(sp_items);
|
||||
|
||||
/* Create the window to be associated with the menu */
|
||||
// Create the window to be associated with the menu
|
||||
sp_menu_win = newwin(10, 40, begin_y, begin_x);
|
||||
keypad(sp_menu_win, TRUE);
|
||||
|
||||
/* Set main window and sub window */
|
||||
// Set main window and sub window
|
||||
set_menu_win(sp_menu, sp_menu_win);
|
||||
set_menu_sub(sp_menu, derwin(sp_menu_win, 6, 38, begin_y - 1, begin_x - 3));
|
||||
|
||||
/* Set menu mark to the string " * " */
|
||||
// Set menu mark to the string " * "
|
||||
set_menu_mark(sp_menu, " * ");
|
||||
|
||||
/* Print a border around the main window and print a title */
|
||||
// Print a border around the main window and print a title
|
||||
box(sp_menu_win, 0, 0);
|
||||
print_in_middle(sp_menu_win, 1, 0, 40, "My Menu", COLOR_PAIR(1));
|
||||
mvwaddch(sp_menu_win, 2, 0, ACS_LTEE);
|
||||
@ -50,7 +52,7 @@ size_t spawn_menu(uint16_t begin_y, uint16_t begin_x, const char** choices,
|
||||
mvprintw(LINES - 2, 0, "F1 to exit");
|
||||
refresh();
|
||||
|
||||
/* Post the menu */
|
||||
// Post the menu
|
||||
post_menu(sp_menu);
|
||||
wrefresh(sp_menu_win);
|
||||
|
||||
@ -67,7 +69,7 @@ size_t spawn_menu(uint16_t begin_y, uint16_t begin_x, const char** choices,
|
||||
}
|
||||
size_t selected = item_index(current_item(sp_menu));
|
||||
|
||||
/* Unpost and free all the memory taken up */
|
||||
// Unpost and free all the memory taken up
|
||||
unpost_menu(sp_menu);
|
||||
free_menu(sp_menu);
|
||||
for (i = 0; i < n_choices; ++i)
|
||||
@ -76,6 +78,7 @@ size_t spawn_menu(uint16_t begin_y, uint16_t begin_x, const char** choices,
|
||||
|
||||
return selected;
|
||||
}
|
||||
*/
|
||||
|
||||
void print_in_middle(WINDOW* win, int starty, int startx, int width,
|
||||
char* string, chtype color) {
|
||||
@ -157,9 +160,17 @@ std::string spawncmd() {
|
||||
return std::string(cmd);
|
||||
}
|
||||
|
||||
void async_clock(WINDOW* win) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(150));
|
||||
void async_clock(WINDOW* win, WINDOW* text_win) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
bool prev_echo_state;
|
||||
uint16_t prev_y, prev_x;
|
||||
while (true) {
|
||||
prev_echo_state = is_echo();
|
||||
getyx(stdscr, prev_y, prev_x);
|
||||
noecho();
|
||||
wborder(text_win, 0, ' ', 0, 0, 0, ACS_HLINE, 0, ACS_HLINE);
|
||||
mvwprintw(text_win, 1, 1, "správný čas na podání trestního oznámení je");
|
||||
wrefresh(text_win);
|
||||
auto now =
|
||||
std::chrono::current_zone()->to_local(std::chrono::system_clock::now());
|
||||
std::string time_str;
|
||||
@ -176,37 +187,30 @@ void async_clock(WINDOW* win) {
|
||||
time_str = "Error";
|
||||
}
|
||||
|
||||
// Clear window content but preserve border
|
||||
werase(win);
|
||||
wborder(win, 0, 0, 0, 0, ACS_TTEE, 0, ACS_BTEE, 0);
|
||||
|
||||
// Print the time in the window
|
||||
mvwprintw(win, 1, 1, "%s", time_str.c_str());
|
||||
wrefresh(win);
|
||||
if (prev_echo_state) {
|
||||
echo();
|
||||
}
|
||||
move(prev_y, prev_x);
|
||||
refresh();
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
}
|
||||
}
|
||||
|
||||
void show_clock_text(WINDOW* text_win) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
wborder(text_win, 0, ' ', 0, 0, 0, ACS_HLINE, 0, ACS_HLINE);
|
||||
mvwprintw(text_win, 1, 1, "správný čas na podání trestního oznámení je");
|
||||
wrefresh(text_win);
|
||||
}
|
||||
|
||||
void async_clock_init() {
|
||||
// program only launches sometimes i think there is race condition
|
||||
|
||||
//memory leak
|
||||
WINDOW* win = newwin(3, 10, LINES - 3, COLS - 10);
|
||||
box(win, 0, 0);
|
||||
wrefresh(win);
|
||||
std::thread clock_thread(async_clock, win);
|
||||
clock_thread.detach();
|
||||
current_allocated->push_back({WINDOW_TYPE, win, 1});
|
||||
|
||||
//memory leak
|
||||
WINDOW* text_win = newwin(3, 52, LINES - 3, COLS - 10 - 44);
|
||||
current_allocated->push_back({WINDOW_TYPE, text_win, 1});
|
||||
|
||||
std::thread text_thread(show_clock_text, text_win);
|
||||
text_thread.detach();
|
||||
std::thread clock_thread(async_clock, win, text_win);
|
||||
clock_thread.detach();
|
||||
}
|
||||
|
10
src/main.cpp
10
src/main.cpp
@ -1,9 +1,11 @@
|
||||
#include <unistd.h>
|
||||
#include <csignal>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include "color.h"
|
||||
#include "const.h"
|
||||
#include "menu.h"
|
||||
#include "signal.h"
|
||||
|
||||
void PrintHelp() {
|
||||
std::cout << RED R"( ____ ____
|
||||
@ -26,6 +28,14 @@ void PrintVersion() {
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
// signal handlers
|
||||
std::signal(SIGTERM, safe_exit);
|
||||
std::signal(SIGINT, safe_exit);
|
||||
std::signal(SIGQUIT, safe_exit);
|
||||
std::signal(SIGHUP, safe_exit);
|
||||
|
||||
// error signal handlers
|
||||
signal(SIGSEGV, safe_exit);
|
||||
|
||||
int opt;
|
||||
while ((opt = getopt(argc, argv, "hV")) != -1) {
|
||||
|
99
src/memory.cpp
Normal file
99
src/memory.cpp
Normal file
@ -0,0 +1,99 @@
|
||||
#include "memory.h"
|
||||
#include <curses.h>
|
||||
#include <menu.h>
|
||||
#include <ncurses.h>
|
||||
// #include <panel.h> UNCOMENT IF IF WE USE PANELs
|
||||
#include <iostream>
|
||||
#include "color.h"
|
||||
#include "types.h"
|
||||
|
||||
std::vector<allocation>* current_allocated;
|
||||
|
||||
template <typename T>
|
||||
struct NcursesDeleter {
|
||||
static void delete_element(T obj);
|
||||
};
|
||||
|
||||
template <>
|
||||
void NcursesDeleter<WINDOW*>::delete_element(WINDOW* win) {
|
||||
delwin(win);
|
||||
}
|
||||
/*template <>
|
||||
void NcursesDeleter<PANEL*>::delete_element(PANEL* pan) {
|
||||
del_panel(pan);
|
||||
} UNCOMENT IF WE USE PANELs*/
|
||||
template <>
|
||||
void NcursesDeleter<ITEM*>::delete_element(ITEM* item) {
|
||||
free_item(item);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void delete_ncurses_arrays(void* ptr, std::size_t size) {
|
||||
T* array = static_cast<T*>(ptr);
|
||||
for (std::size_t j = 0; j < size; ++j) {
|
||||
NcursesDeleter<T>::delete_element(array[j]);
|
||||
}
|
||||
delete[] array;
|
||||
}
|
||||
|
||||
void delete_all(std::vector<allocation>* allocated) {
|
||||
if (allocated == nullptr) {
|
||||
return;
|
||||
}
|
||||
for (long long i = allocated->size() - 1; i >= 0; i--) {
|
||||
switch (allocated->at(i).type) {
|
||||
case WINDOW_ARRAY: {
|
||||
delete_ncurses_arrays<WINDOW*>(allocated->at(i).ptr,
|
||||
allocated->at(i).size);
|
||||
break;
|
||||
}
|
||||
/* case PANEL_ARRAY: {
|
||||
delete_ncurses_arrays<PANEL*>(allocated->at(i).ptr,
|
||||
allocated->at(i).size);
|
||||
break;
|
||||
} UNCOMENT IF WE USE PANELs*/
|
||||
case ITEM_ARRAY: {
|
||||
delete_ncurses_arrays<ITEM*>(allocated->at(i).ptr,
|
||||
allocated->at(i).size);
|
||||
break;
|
||||
}
|
||||
case CHAR_PTR_ARRAY: {
|
||||
char** array = static_cast<char**>(allocated->at(i).ptr);
|
||||
for (std::size_t j = 0; j < allocated->at(i).size; ++j) {
|
||||
delete[] array[j];
|
||||
}
|
||||
delete[] array;
|
||||
break;
|
||||
}
|
||||
case GENERIC_ARRAY:
|
||||
delete[] static_cast<char*>(allocated->at(i).ptr);
|
||||
break;
|
||||
case WINDOW_TYPE:
|
||||
delwin(static_cast<WINDOW*>(allocated->at(i).ptr));
|
||||
break;
|
||||
/*case PANEL_TYPE:
|
||||
del_panel(static_cast<PANEL*>(allocated->at(i).ptr));
|
||||
break; UNCOMENT IF WE USE PANELs */
|
||||
case MENU_TYPE:
|
||||
free_menu(static_cast<MENU*>(allocated->at(i).ptr));
|
||||
break;
|
||||
case COMPLETE_MENU_TYPE: {
|
||||
free_menu(static_cast<complete_menu*>(allocated->at(i).ptr)->menu);
|
||||
delwin(static_cast<complete_menu*>(allocated->at(i).ptr)->win);
|
||||
delete_ncurses_arrays<ITEM*>(
|
||||
static_cast<complete_menu*>(allocated->at(i).ptr)->items,
|
||||
static_cast<complete_menu*>(allocated->at(i).ptr)->items_size);
|
||||
|
||||
break;
|
||||
}
|
||||
case GENERIC_TYPE:
|
||||
delete static_cast<char*>(allocated->at(i).ptr);
|
||||
break;
|
||||
default:
|
||||
std::cerr << RED "[!!CRITICAL!!]" << RESET " Unknown allocation type"
|
||||
<< "\n";
|
||||
break;
|
||||
}
|
||||
allocated->pop_back();
|
||||
}
|
||||
}
|
30
src/memory.h
Normal file
30
src/memory.h
Normal file
@ -0,0 +1,30 @@
|
||||
// header guard
|
||||
#ifndef PARADOCS_MEMORY_H_
|
||||
#define PARADOCS_MEMORY_H_
|
||||
|
||||
#include <menu.h>
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
enum AllocationType {
|
||||
WINDOW_ARRAY,
|
||||
// PANEL_ARRAY, UNCOMENT IF WE USE PANELs
|
||||
ITEM_ARRAY,
|
||||
CHAR_PTR_ARRAY,
|
||||
GENERIC_ARRAY,
|
||||
WINDOW_TYPE,
|
||||
// PANEL_TYPE, UNCOMENT IF WE USE PANELs
|
||||
MENU_TYPE,
|
||||
COMPLETE_MENU_TYPE,
|
||||
GENERIC_TYPE
|
||||
};
|
||||
|
||||
struct allocation {
|
||||
AllocationType type;
|
||||
void* ptr;
|
||||
std::size_t size;
|
||||
};
|
||||
|
||||
extern std::vector<allocation>* current_allocated;
|
||||
|
||||
void delete_all(std::vector<allocation>* allocated);
|
||||
#endif
|
85
src/menu.cpp
85
src/menu.cpp
@ -1,23 +1,24 @@
|
||||
#include <curses.h>
|
||||
#include <menu.h>
|
||||
#include <ncurses.h>
|
||||
#include <clocale>
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include "const.h"
|
||||
#include "cups.h"
|
||||
#include "gameske_funkce.h"
|
||||
#include "memory.h"
|
||||
#include "types.h"
|
||||
|
||||
#define CTRLD 4
|
||||
std::vector<allocation> main_menu_allocated;
|
||||
|
||||
const char* choices[] = {"paradox", "kompromis", "Stereotyp", "Žena"};
|
||||
const char* date[] = {"2023-10-01", "2023-10-02", "2023-10-03", "2023-10-04"};
|
||||
const char* choices2[] = {"PRINT", "EDIT", "DELETE", "Žena"};
|
||||
|
||||
void menu() {
|
||||
ITEM** my_items;
|
||||
int c;
|
||||
MENU* my_menu;
|
||||
WINDOW* my_menu_win;
|
||||
int n_choices, i;
|
||||
|
||||
current_allocated = &main_menu_allocated;
|
||||
/* Initialize curses */
|
||||
setlocale(LC_ALL, "");
|
||||
initscr();
|
||||
@ -32,61 +33,75 @@ void menu() {
|
||||
async_clock_init();
|
||||
|
||||
/* Create items */
|
||||
n_choices = ARRAY_SIZE(choices);
|
||||
my_items = new ITEM*[ARRAY_SIZE(choices)];
|
||||
for (i = 0; i < n_choices; ++i)
|
||||
my_items[i] = new_item(choices[i], date[i]);
|
||||
size_t n_choices = ARRAY_SIZE(choices);
|
||||
complete_menu main_menu = {nullptr, nullptr, 0, nullptr};
|
||||
main_menu_allocated.push_back({COMPLETE_MENU_TYPE, &main_menu, 1});
|
||||
|
||||
main_menu.items = new ITEM*[ARRAY_SIZE(choices) + 1];
|
||||
main_menu.items_size = ARRAY_SIZE(choices) + 1;
|
||||
for (size_t i = 0; i < n_choices; ++i) {
|
||||
main_menu.items[i] = new_item(choices[i], date[i]);
|
||||
}
|
||||
main_menu.items[n_choices] = nullptr;
|
||||
|
||||
/* Crate menu */
|
||||
my_menu = new_menu(my_items);
|
||||
main_menu.menu = new_menu(main_menu.items);
|
||||
|
||||
/* Create the window to be associated with the menu */
|
||||
my_menu_win = newwin(10, 40, 4, 4);
|
||||
keypad(my_menu_win, TRUE);
|
||||
main_menu.win = newwin(10, 40, 4, 4);
|
||||
keypad(main_menu.win, TRUE);
|
||||
|
||||
/* Set main window and sub window */
|
||||
set_menu_win(my_menu, my_menu_win);
|
||||
set_menu_sub(my_menu, derwin(my_menu_win, 6, 38, 3, 1));
|
||||
set_menu_win(main_menu.menu, main_menu.win);
|
||||
set_menu_sub(main_menu.menu, derwin(main_menu.win, 6, 38, 3, 1));
|
||||
|
||||
/* Set menu mark to the string " * " */
|
||||
set_menu_mark(my_menu, " * ");
|
||||
set_menu_mark(main_menu.menu, " * ");
|
||||
|
||||
/* Print a border around the main window and print a title */
|
||||
box(my_menu_win, 0, 0);
|
||||
print_in_middle(my_menu_win, 1, 0, 40, "My Menu", COLOR_PAIR(1));
|
||||
mvwaddch(my_menu_win, 2, 0, ACS_LTEE);
|
||||
mvwhline(my_menu_win, 2, 1, ACS_HLINE, 38);
|
||||
mvwaddch(my_menu_win, 2, 39, ACS_RTEE);
|
||||
box(main_menu.win, 0, 0);
|
||||
print_in_middle(main_menu.win, 1, 0, 40, "My Menu", COLOR_PAIR(1));
|
||||
mvwaddch(main_menu.win, 2, 0, ACS_LTEE);
|
||||
mvwhline(main_menu.win, 2, 1, ACS_HLINE, 38);
|
||||
mvwaddch(main_menu.win, 2, 39, ACS_RTEE);
|
||||
mvprintw(LINES - 2, 0, "F1 to exit");
|
||||
refresh();
|
||||
|
||||
/* Post the menu */
|
||||
post_menu(my_menu);
|
||||
wrefresh(my_menu_win);
|
||||
post_menu(main_menu.menu);
|
||||
wrefresh(main_menu.win);
|
||||
|
||||
while ((c = wgetch(my_menu_win)) != KEY_F(1)) {
|
||||
int c;
|
||||
while ((c = wgetch(main_menu.win)) != KEY_F(1)) {
|
||||
switch (c) {
|
||||
case KEY_DOWN:
|
||||
menu_driver(my_menu, REQ_DOWN_ITEM);
|
||||
menu_driver(main_menu.menu, REQ_DOWN_ITEM);
|
||||
break;
|
||||
case KEY_UP:
|
||||
menu_driver(my_menu, REQ_UP_ITEM);
|
||||
menu_driver(main_menu.menu, REQ_UP_ITEM);
|
||||
break;
|
||||
case 10:
|
||||
|
||||
refresh();
|
||||
break;
|
||||
case ':':
|
||||
spawncmd();
|
||||
switch (hash_djb2a(spawncmd())) {
|
||||
case "print"_sh:
|
||||
case "p"_sh:
|
||||
// DONT FORGET TO PRINT ACTUAL DOCUMENT
|
||||
printDocument("test");
|
||||
current_allocated = &main_menu_allocated;
|
||||
break;
|
||||
default:
|
||||
print_in_middle(main_menu.win, 10, 0, 40, "Unknown command",
|
||||
COLOR_PAIR(1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
wrefresh(my_menu_win);
|
||||
wrefresh(main_menu.win);
|
||||
}
|
||||
|
||||
/* Unpost and free all the memory taken up */
|
||||
unpost_menu(my_menu);
|
||||
free_menu(my_menu);
|
||||
for (i = 0; i < n_choices; ++i)
|
||||
free_item(my_items[i]);
|
||||
delete[] my_items;
|
||||
unpost_menu(main_menu.menu);
|
||||
delete_all(&main_menu_allocated);
|
||||
endwin();
|
||||
}
|
||||
|
33
src/signal.cpp
Normal file
33
src/signal.cpp
Normal file
@ -0,0 +1,33 @@
|
||||
#include <curses.h>
|
||||
#include <csignal>
|
||||
#include <iostream>
|
||||
#include "memory.h"
|
||||
void safe_exit(int code) {
|
||||
switch (code) {
|
||||
case SIGTERM:
|
||||
std::cerr << "\nreceived SIGTERM exiting...\n";
|
||||
break;
|
||||
case SIGINT:
|
||||
std::cerr << "\nreceived SIGINT exiting...\n";
|
||||
break;
|
||||
case SIGQUIT:
|
||||
std::cerr << "\nreceived SIGQUIT exiting...\n";
|
||||
break;
|
||||
case SIGHUP:
|
||||
std::cerr << "\nreceived SIGHUP exiting...\n";
|
||||
break;
|
||||
|
||||
case SIGSEGV:
|
||||
std::cerr << "\nreceived SIGSEGV(segmentaiton fault) exiting...\nIf this "
|
||||
"repeats please report it as a bug\n";
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
delete_all(current_allocated);
|
||||
echo();
|
||||
endwin();
|
||||
|
||||
exit(code);
|
||||
}
|
7
src/signal.h
Normal file
7
src/signal.h
Normal file
@ -0,0 +1,7 @@
|
||||
|
||||
#ifndef PARADOCS_SIGNAL_H_
|
||||
#define PARADOCS_SIGNAL_H_
|
||||
|
||||
void safe_exit(int code);
|
||||
|
||||
#endif
|
14
src/types.h
Normal file
14
src/types.h
Normal file
@ -0,0 +1,14 @@
|
||||
#include <menu.h>
|
||||
#include <ncurses.h>
|
||||
|
||||
#ifndef PARADOCS_TYPES_H_
|
||||
#define PARADOCS_TYPES_H_
|
||||
|
||||
struct complete_menu {
|
||||
WINDOW* win;
|
||||
ITEM** items;
|
||||
size_t items_size;
|
||||
MENU* menu;
|
||||
};
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user