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 = g++
|
||||||
CPPC_FLAGS = -std=c++23 -s -O3 -Wall -Wextra -Wno-write-strings -lncurses -lmenu -lform -lcups
|
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_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
|
SRC_PATH := src
|
||||||
@ -19,6 +20,9 @@ all: make-build-dir $(BIN_PATH)/ParaDocs
|
|||||||
debug: CPPC_FLAGS = $(DEBUG_FLAGS)
|
debug: CPPC_FLAGS = $(DEBUG_FLAGS)
|
||||||
debug: make-build-dir $(BIN_PATH)/ParaDocs
|
debug: make-build-dir $(BIN_PATH)/ParaDocs
|
||||||
|
|
||||||
|
asan: CPPC_FLAGS = $(DEBUG_ASANITIZE)
|
||||||
|
asan: make-build-dir $(BIN_PATH)/ParaDocs
|
||||||
|
|
||||||
|
|
||||||
make-build-dir:
|
make-build-dir:
|
||||||
mkdir -p $(OBJ_PATH)
|
mkdir -p $(OBJ_PATH)
|
||||||
@ -39,4 +43,4 @@ install:
|
|||||||
clean:
|
clean:
|
||||||
rm -fr build
|
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
|
#ifndef NAME
|
||||||
|
|
||||||
#define NAME "ParaDocs"
|
#define NAME "ParaDocs"
|
||||||
#define VERSION "0.0.1"
|
#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
|
#endif
|
102
src/cups.cpp
102
src/cups.cpp
@ -5,22 +5,16 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#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) {
|
bool printDocument(const std::string& content) {
|
||||||
|
current_allocated = &cups_allocated;
|
||||||
// Initialize variables
|
// Initialize variables
|
||||||
bool success = false;
|
bool success = false;
|
||||||
cups_dest_t* dests = nullptr;
|
complete_menu printer_menu = {nullptr, nullptr, 0, 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;
|
|
||||||
|
|
||||||
// Write content to a temporary file
|
// Write content to a temporary file
|
||||||
std::string tempFileName = "/tmp/print_temp_ParaDocs.txt";
|
std::string tempFileName = "/tmp/print_temp_ParaDocs.txt";
|
||||||
@ -32,12 +26,20 @@ bool printDocument(const std::string& content) {
|
|||||||
tempFile.close();
|
tempFile.close();
|
||||||
|
|
||||||
// Get printer destinations from CUPS
|
// Get printer destinations from CUPS
|
||||||
num_dests = cupsGetDests(&dests);
|
cups_dest_t* dests = nullptr;
|
||||||
|
int num_dests = cupsGetDests(&dests);
|
||||||
if (num_dests <= 0) {
|
if (num_dests <= 0) {
|
||||||
remove(tempFileName.c_str());
|
remove(tempFileName.c_str());
|
||||||
return false; // No printers available
|
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
|
// Initialize ncurses
|
||||||
initscr();
|
initscr();
|
||||||
start_color();
|
start_color();
|
||||||
@ -47,7 +49,7 @@ bool printDocument(const std::string& content) {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// Allocate memory for menu items
|
// 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
|
// Prepare menu items for each printer
|
||||||
for (int i = 0; i < num_dests; i++) {
|
for (int i = 0; i < num_dests; i++) {
|
||||||
@ -62,7 +64,7 @@ bool printDocument(const std::string& content) {
|
|||||||
// Allocate memory for name string
|
// Allocate memory for name string
|
||||||
char* name_str = new char[display_name.length() + 1];
|
char* name_str = new char[display_name.length() + 1];
|
||||||
std::strcpy(name_str, display_name.c_str());
|
std::strcpy(name_str, display_name.c_str());
|
||||||
item_names.push_back(name_str);
|
item_names[i] = name_str;
|
||||||
|
|
||||||
// Get description if available
|
// Get description if available
|
||||||
const char* desc =
|
const char* desc =
|
||||||
@ -72,54 +74,55 @@ bool printDocument(const std::string& content) {
|
|||||||
// Allocate memory for description string
|
// Allocate memory for description string
|
||||||
char* desc_str = new char[description.length() + 1];
|
char* desc_str = new char[description.length() + 1];
|
||||||
std::strcpy(desc_str, description.c_str());
|
std::strcpy(desc_str, description.c_str());
|
||||||
item_descriptions.push_back(desc_str);
|
item_descriptions[i] = desc_str;
|
||||||
|
|
||||||
// Create menu item
|
// Create menu item
|
||||||
menu_items[i] = new_item(name_str, desc_str);
|
printer_menu.items[i] = new_item(name_str, desc_str);
|
||||||
if (!menu_items[i]) {
|
if (!printer_menu.items[i]) {
|
||||||
throw std::runtime_error("Failed to create menu item");
|
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
|
// Create the menu
|
||||||
menu = new_menu(menu_items);
|
printer_menu.menu = new_menu(printer_menu.items);
|
||||||
if (!menu) {
|
if (!printer_menu.menu) {
|
||||||
throw std::runtime_error("Failed to create menu");
|
throw std::runtime_error("Failed to create menu");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up menu window
|
// Set up menu window
|
||||||
int rows, cols;
|
int rows, cols;
|
||||||
getmaxyx(stdscr, rows, cols);
|
getmaxyx(stdscr, rows, cols);
|
||||||
menu_win = newwin(rows - 4, cols - 4, 2, 2);
|
printer_menu.win = newwin(rows - 4, cols - 4, 2, 2);
|
||||||
keypad(menu_win, TRUE);
|
keypad(printer_menu.win, TRUE);
|
||||||
|
|
||||||
// Set menu window and sub window
|
// Set menu window and sub window
|
||||||
set_menu_win(menu, menu_win);
|
set_menu_win(printer_menu.menu, printer_menu.win);
|
||||||
set_menu_sub(menu, derwin(menu_win, rows - 6, cols - 6, 1, 1));
|
set_menu_sub(printer_menu.menu,
|
||||||
set_menu_format(menu, rows - 8, 1);
|
derwin(printer_menu.win, rows - 6, cols - 6, 1, 1));
|
||||||
set_menu_mark(menu, " * ");
|
set_menu_format(printer_menu.menu, rows - 8, 1);
|
||||||
|
set_menu_mark(printer_menu.menu, " * ");
|
||||||
|
|
||||||
// Post the menu with instructions
|
// Post the menu with instructions
|
||||||
mvprintw(0, 0, "Select a printer and press Enter:");
|
mvprintw(0, 0, "Select a printer and press Enter:");
|
||||||
mvprintw(rows - 2, 0, "Press q to cancel");
|
mvprintw(rows - 2, 0, "Press q to cancel");
|
||||||
refresh();
|
refresh();
|
||||||
post_menu(menu);
|
post_menu(printer_menu.menu);
|
||||||
wrefresh(menu_win);
|
wrefresh(printer_menu.win);
|
||||||
|
|
||||||
// Menu interaction loop
|
// Menu interaction loop
|
||||||
int c;
|
int c;
|
||||||
while ((c = wgetch(menu_win)) != 'q') {
|
while ((c = wgetch(printer_menu.win)) != 'q') {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case KEY_DOWN:
|
case KEY_DOWN:
|
||||||
menu_driver(menu, REQ_DOWN_ITEM);
|
menu_driver(printer_menu.menu, REQ_DOWN_ITEM);
|
||||||
break;
|
break;
|
||||||
case KEY_UP:
|
case KEY_UP:
|
||||||
menu_driver(menu, REQ_UP_ITEM);
|
menu_driver(printer_menu.menu, REQ_UP_ITEM);
|
||||||
break;
|
break;
|
||||||
case 10: // Enter key
|
case 10: // Enter key
|
||||||
{
|
{
|
||||||
ITEM* cur = current_item(menu);
|
ITEM* cur = current_item(printer_menu.menu);
|
||||||
int index = item_index(cur);
|
int index = item_index(cur);
|
||||||
|
|
||||||
// Print the document to the selected printer
|
// Print the document to the selected printer
|
||||||
@ -142,7 +145,7 @@ bool printDocument(const std::string& content) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
wrefresh(menu_win);
|
wrefresh(printer_menu.win);
|
||||||
}
|
}
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
mvprintw(0, 0, "Error: %s", e.what());
|
mvprintw(0, 0, "Error: %s", e.what());
|
||||||
@ -151,39 +154,16 @@ bool printDocument(const std::string& content) {
|
|||||||
}
|
}
|
||||||
exit_menu:
|
exit_menu:
|
||||||
|
|
||||||
// Clean up resources
|
unpost_menu(printer_menu.menu);
|
||||||
if (menu) {
|
wclear(printer_menu.win);
|
||||||
unpost_menu(menu);
|
clear();
|
||||||
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();
|
|
||||||
|
|
||||||
// Remove temp file
|
// Remove temp file
|
||||||
remove(tempFileName.c_str());
|
remove(tempFileName.c_str());
|
||||||
|
|
||||||
// Free CUPS destinations
|
// Free CUPS destinations
|
||||||
cupsFreeDests(num_dests, dests);
|
cupsFreeDests(num_dests, dests);
|
||||||
|
delete_all(&cups_allocated);
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,9 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include "memory.h"
|
||||||
|
|
||||||
|
/*
|
||||||
size_t spawn_menu(uint16_t begin_y, uint16_t begin_x, const char** choices,
|
size_t spawn_menu(uint16_t begin_y, uint16_t begin_x, const char** choices,
|
||||||
size_t n_choices) {
|
size_t n_choices) {
|
||||||
ITEM** sp_items;
|
ITEM** sp_items;
|
||||||
@ -22,26 +24,26 @@ size_t spawn_menu(uint16_t begin_y, uint16_t begin_x, const char** choices,
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
sp_items = new ITEM*[n_choices];
|
sp_items = new ITEM*[n_choices];
|
||||||
/* Create items */
|
// Create items
|
||||||
for (i = 0; i < n_choices; ++i) {
|
for (i = 0; i < n_choices; ++i) {
|
||||||
sp_items[i] = new_item(choices[i], choices[i]);
|
sp_items[i] = new_item(choices[i], choices[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Crate menu */
|
// Crate menu
|
||||||
sp_menu = new_menu(sp_items);
|
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);
|
sp_menu_win = newwin(10, 40, begin_y, begin_x);
|
||||||
keypad(sp_menu_win, TRUE);
|
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_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_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, " * ");
|
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);
|
box(sp_menu_win, 0, 0);
|
||||||
print_in_middle(sp_menu_win, 1, 0, 40, "My Menu", COLOR_PAIR(1));
|
print_in_middle(sp_menu_win, 1, 0, 40, "My Menu", COLOR_PAIR(1));
|
||||||
mvwaddch(sp_menu_win, 2, 0, ACS_LTEE);
|
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");
|
mvprintw(LINES - 2, 0, "F1 to exit");
|
||||||
refresh();
|
refresh();
|
||||||
|
|
||||||
/* Post the menu */
|
// Post the menu
|
||||||
post_menu(sp_menu);
|
post_menu(sp_menu);
|
||||||
wrefresh(sp_menu_win);
|
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));
|
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);
|
unpost_menu(sp_menu);
|
||||||
free_menu(sp_menu);
|
free_menu(sp_menu);
|
||||||
for (i = 0; i < n_choices; ++i)
|
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;
|
return selected;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
void print_in_middle(WINDOW* win, int starty, int startx, int width,
|
void print_in_middle(WINDOW* win, int starty, int startx, int width,
|
||||||
char* string, chtype color) {
|
char* string, chtype color) {
|
||||||
@ -157,9 +160,17 @@ std::string spawncmd() {
|
|||||||
return std::string(cmd);
|
return std::string(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void async_clock(WINDOW* win) {
|
void async_clock(WINDOW* win, WINDOW* text_win) {
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(150));
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||||
|
bool prev_echo_state;
|
||||||
|
uint16_t prev_y, prev_x;
|
||||||
while (true) {
|
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 =
|
auto now =
|
||||||
std::chrono::current_zone()->to_local(std::chrono::system_clock::now());
|
std::chrono::current_zone()->to_local(std::chrono::system_clock::now());
|
||||||
std::string time_str;
|
std::string time_str;
|
||||||
@ -176,37 +187,30 @@ void async_clock(WINDOW* win) {
|
|||||||
time_str = "Error";
|
time_str = "Error";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear window content but preserve border
|
|
||||||
werase(win);
|
werase(win);
|
||||||
wborder(win, 0, 0, 0, 0, ACS_TTEE, 0, ACS_BTEE, 0);
|
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());
|
mvwprintw(win, 1, 1, "%s", time_str.c_str());
|
||||||
wrefresh(win);
|
wrefresh(win);
|
||||||
|
if (prev_echo_state) {
|
||||||
|
echo();
|
||||||
|
}
|
||||||
|
move(prev_y, prev_x);
|
||||||
|
refresh();
|
||||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
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() {
|
void async_clock_init() {
|
||||||
// program only launches sometimes i think there is race condition
|
|
||||||
|
|
||||||
//memory leak
|
//memory leak
|
||||||
WINDOW* win = newwin(3, 10, LINES - 3, COLS - 10);
|
WINDOW* win = newwin(3, 10, LINES - 3, COLS - 10);
|
||||||
box(win, 0, 0);
|
current_allocated->push_back({WINDOW_TYPE, win, 1});
|
||||||
wrefresh(win);
|
|
||||||
std::thread clock_thread(async_clock, win);
|
|
||||||
clock_thread.detach();
|
|
||||||
|
|
||||||
//memory leak
|
//memory leak
|
||||||
WINDOW* text_win = newwin(3, 52, LINES - 3, COLS - 10 - 44);
|
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);
|
std::thread clock_thread(async_clock, win, text_win);
|
||||||
text_thread.detach();
|
clock_thread.detach();
|
||||||
}
|
}
|
||||||
|
10
src/main.cpp
10
src/main.cpp
@ -1,9 +1,11 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <csignal>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include "color.h"
|
#include "color.h"
|
||||||
#include "const.h"
|
#include "const.h"
|
||||||
#include "menu.h"
|
#include "menu.h"
|
||||||
|
#include "signal.h"
|
||||||
|
|
||||||
void PrintHelp() {
|
void PrintHelp() {
|
||||||
std::cout << RED R"( ____ ____
|
std::cout << RED R"( ____ ____
|
||||||
@ -26,6 +28,14 @@ void PrintVersion() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
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;
|
int opt;
|
||||||
while ((opt = getopt(argc, argv, "hV")) != -1) {
|
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 <curses.h>
|
||||||
#include <menu.h>
|
#include <menu.h>
|
||||||
|
#include <ncurses.h>
|
||||||
#include <clocale>
|
#include <clocale>
|
||||||
|
#include <cstddef>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include "const.h"
|
||||||
|
#include "cups.h"
|
||||||
#include "gameske_funkce.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* choices[] = {"paradox", "kompromis", "Stereotyp", "Žena"};
|
||||||
const char* date[] = {"2023-10-01", "2023-10-02", "2023-10-03", "2023-10-04"};
|
const char* date[] = {"2023-10-01", "2023-10-02", "2023-10-03", "2023-10-04"};
|
||||||
const char* choices2[] = {"PRINT", "EDIT", "DELETE", "Žena"};
|
const char* choices2[] = {"PRINT", "EDIT", "DELETE", "Žena"};
|
||||||
|
|
||||||
void menu() {
|
void menu() {
|
||||||
ITEM** my_items;
|
current_allocated = &main_menu_allocated;
|
||||||
int c;
|
|
||||||
MENU* my_menu;
|
|
||||||
WINDOW* my_menu_win;
|
|
||||||
int n_choices, i;
|
|
||||||
|
|
||||||
/* Initialize curses */
|
/* Initialize curses */
|
||||||
setlocale(LC_ALL, "");
|
setlocale(LC_ALL, "");
|
||||||
initscr();
|
initscr();
|
||||||
@ -32,61 +33,75 @@ void menu() {
|
|||||||
async_clock_init();
|
async_clock_init();
|
||||||
|
|
||||||
/* Create items */
|
/* Create items */
|
||||||
n_choices = ARRAY_SIZE(choices);
|
size_t n_choices = ARRAY_SIZE(choices);
|
||||||
my_items = new ITEM*[ARRAY_SIZE(choices)];
|
complete_menu main_menu = {nullptr, nullptr, 0, nullptr};
|
||||||
for (i = 0; i < n_choices; ++i)
|
main_menu_allocated.push_back({COMPLETE_MENU_TYPE, &main_menu, 1});
|
||||||
my_items[i] = new_item(choices[i], date[i]);
|
|
||||||
|
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 */
|
/* 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 */
|
/* Create the window to be associated with the menu */
|
||||||
my_menu_win = newwin(10, 40, 4, 4);
|
main_menu.win = newwin(10, 40, 4, 4);
|
||||||
keypad(my_menu_win, TRUE);
|
keypad(main_menu.win, TRUE);
|
||||||
|
|
||||||
/* Set main window and sub window */
|
/* Set main window and sub window */
|
||||||
set_menu_win(my_menu, my_menu_win);
|
set_menu_win(main_menu.menu, main_menu.win);
|
||||||
set_menu_sub(my_menu, derwin(my_menu_win, 6, 38, 3, 1));
|
set_menu_sub(main_menu.menu, derwin(main_menu.win, 6, 38, 3, 1));
|
||||||
|
|
||||||
/* Set menu mark to the string " * " */
|
/* 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 */
|
/* Print a border around the main window and print a title */
|
||||||
box(my_menu_win, 0, 0);
|
box(main_menu.win, 0, 0);
|
||||||
print_in_middle(my_menu_win, 1, 0, 40, "My Menu", COLOR_PAIR(1));
|
print_in_middle(main_menu.win, 1, 0, 40, "My Menu", COLOR_PAIR(1));
|
||||||
mvwaddch(my_menu_win, 2, 0, ACS_LTEE);
|
mvwaddch(main_menu.win, 2, 0, ACS_LTEE);
|
||||||
mvwhline(my_menu_win, 2, 1, ACS_HLINE, 38);
|
mvwhline(main_menu.win, 2, 1, ACS_HLINE, 38);
|
||||||
mvwaddch(my_menu_win, 2, 39, ACS_RTEE);
|
mvwaddch(main_menu.win, 2, 39, ACS_RTEE);
|
||||||
mvprintw(LINES - 2, 0, "F1 to exit");
|
mvprintw(LINES - 2, 0, "F1 to exit");
|
||||||
refresh();
|
refresh();
|
||||||
|
|
||||||
/* Post the menu */
|
/* Post the menu */
|
||||||
post_menu(my_menu);
|
post_menu(main_menu.menu);
|
||||||
wrefresh(my_menu_win);
|
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) {
|
switch (c) {
|
||||||
case KEY_DOWN:
|
case KEY_DOWN:
|
||||||
menu_driver(my_menu, REQ_DOWN_ITEM);
|
menu_driver(main_menu.menu, REQ_DOWN_ITEM);
|
||||||
break;
|
break;
|
||||||
case KEY_UP:
|
case KEY_UP:
|
||||||
menu_driver(my_menu, REQ_UP_ITEM);
|
menu_driver(main_menu.menu, REQ_UP_ITEM);
|
||||||
break;
|
break;
|
||||||
case 10:
|
case 10:
|
||||||
|
|
||||||
refresh();
|
refresh();
|
||||||
break;
|
break;
|
||||||
case ':':
|
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(main_menu.menu);
|
||||||
unpost_menu(my_menu);
|
delete_all(&main_menu_allocated);
|
||||||
free_menu(my_menu);
|
|
||||||
for (i = 0; i < n_choices; ++i)
|
|
||||||
free_item(my_items[i]);
|
|
||||||
delete[] my_items;
|
|
||||||
endwin();
|
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