From 54fbed833005cf4933108160a0175df4d42f5df7 Mon Sep 17 00:00:00 2001 From: Simon <33755707+Crotex@users.noreply.github.com> Date: Thu, 9 Jan 2020 14:12:58 +0100 Subject: [PATCH 1/3] Added paging - Navigation via 'm' and 'n' --- menu.c | 85 +++++++++++++++++++++++++++++++++++----------------------- menu.h | 19 ++++++++++--- 2 files changed, 66 insertions(+), 38 deletions(-) diff --git a/menu.c b/menu.c index c516898..982c135 100644 --- a/menu.c +++ b/menu.c @@ -40,11 +40,59 @@ void get_console_dimensions(int* width, int* height) *height = csbi.srWindow.Bottom - csbi.srWindow.Top + 1; } -void show_menu(const int itemc, const struct MenuItem itemv[], const char title[], const bool loopback, const bool pause, const struct MenuBorder *border) +void page(const struct MenuPage *pages, const size_t page_count) { + unsigned int page_index = 0; + bool action_performed, loop, pageChanged = true; + char pageKey, itemKey; + + do { + do { + show_menu(pages[page_index].item_count, pages[page_index].items, pages[page_index].title, pages[page_index].border); + + // Wait for user selection + putchar('>'); + putchar(' '); + + loop = pages[page_index].loopback; + pageKey = _getch(); + + if (pageKey == 'm') + page_index < page_count - 1 ? page_index++ : page_index; + else if (pageKey == 'n') + page_index > 0 ? page_index-- : page_index; + else { + pageChanged = false; + itemKey = pageKey; + do { + action_performed = false; + + itemKey != pageKey ? itemKey = _getch() : pageKey; + pageKey = 0; + for (int i = 0; i < pages[page_index].item_count; ++i) { + if (pages[page_index].items[i].key == itemKey) { + // Perform action + system("cls"); + pages[page_index].items[i].action(); + action_performed = true; + + // Pause if requested + if (pages[page_index].pause) { + putchar('\n'); + system("pause"); + } + } + } + } while (!action_performed); + } + } while (loop || pageChanged); + + page_index = 0; + } while (1); +} + +void show_menu(const int itemc, const struct MenuItem itemv[], const char title[], const struct MenuBorder *border) { unsigned width, height, item_index; - char key; - bool action_performed; // Clear the console window system("cls"); @@ -132,35 +180,4 @@ void show_menu(const int itemc, const struct MenuItem itemv[], const char title[ i != height - 2 ? putchar(border->line_vertical) : putchar(' '); } } - - // Wait for user selection - putchar('>'); - putchar(' '); - action_performed = false; - do { - key = _getch(); - for (int i = 0; i < itemc; ++i) - { - if (itemv[i].key == key) - { - // Perform action - system("cls"); - itemv[i].action(); - action_performed = true; - - // Pause if requested - if (pause) - { - putchar('\n'); - system("pause"); - } - } - } - } while (!action_performed); - - // Show menu again if requested - if (loopback) - { - show_menu(itemc, itemv, title, loopback, pause, border); - } } \ No newline at end of file diff --git a/menu.h b/menu.h index 67c905a..92981a7 100644 --- a/menu.h +++ b/menu.h @@ -2,6 +2,8 @@ #include "pch.h" + + /// Represents one menu item in a menu. struct MenuItem { char* text; @@ -9,6 +11,8 @@ struct MenuItem { void* (*action)(void); }; + + /// Represents a border in which a menu is displayed. struct MenuBorder { char line_vertical; @@ -23,11 +27,18 @@ struct MenuBorder { const extern struct MenuBorder DEFAULT, MODERN, NO_BORDER, SOLID; -/// Displaces a CUI menu to the user and lets them choose an option, then calls the corresponding function. +/// Represents a page in the menu. +struct MenuPage { + const struct MenuItem* items; + const size_t item_count; + char* title; + bool loopback, pause; + const struct MenuBorder* border; +}; + +/// Displaces a CUI menu to the user /// The length of the array itemv of menu items. /// An array of all menu items to display in the menu. /// The title of the menu. -/// If this parameter is set to true, the menu will be displayed again after an action is executed. -/// If this parameter is set to true, a pausecommand will be run after an action is executed. /// Specifies the border in which the menu is displayed. -void show_menu(const int itemc, const struct MenuItem itemv[], const char title[], const bool loopback, const bool pause, const struct MenuBorder *border); \ No newline at end of file +void show_menu(const int itemc, const struct MenuItem itemv[], const char title[], const struct MenuBorder *border); \ No newline at end of file From 72046f2e0c7d475d938d166a5fe2987bb42344a7 Mon Sep 17 00:00:00 2001 From: Simon <33755707+Crotex@users.noreply.github.com> Date: Thu, 9 Jan 2020 14:31:00 +0100 Subject: [PATCH 2/3] Added paging Fixes #2 --- menu.c | 4 ++-- menu.h | 11 ++++++++--- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/menu.c b/menu.c index 982c135..721e23d 100644 --- a/menu.c +++ b/menu.c @@ -40,7 +40,7 @@ void get_console_dimensions(int* width, int* height) *height = csbi.srWindow.Bottom - csbi.srWindow.Top + 1; } -void page(const struct MenuPage *pages, const size_t page_count) { +void page(const struct MenuPage *pages, const size_t page_count, const bool infinite_loop) { unsigned int page_index = 0; bool action_performed, loop, pageChanged = true; char pageKey, itemKey; @@ -87,7 +87,7 @@ void page(const struct MenuPage *pages, const size_t page_count) { } while (loop || pageChanged); page_index = 0; - } while (1); + } while (infinite_loop); } void show_menu(const int itemc, const struct MenuItem itemv[], const char title[], const struct MenuBorder *border) diff --git a/menu.h b/menu.h index 92981a7..63d3845 100644 --- a/menu.h +++ b/menu.h @@ -3,7 +3,6 @@ #include "pch.h" - /// Represents one menu item in a menu. struct MenuItem { char* text; @@ -11,8 +10,6 @@ struct MenuItem { void* (*action)(void); }; - - /// Represents a border in which a menu is displayed. struct MenuBorder { char line_vertical; @@ -27,6 +24,7 @@ struct MenuBorder { const extern struct MenuBorder DEFAULT, MODERN, NO_BORDER, SOLID; + /// Represents a page in the menu. struct MenuPage { const struct MenuItem* items; @@ -36,6 +34,13 @@ struct MenuPage { const struct MenuBorder* border; }; + +/// Constructs a menu with a specific amount of pages +/// An array of all pages to display. +/// The length of the array pages. +/// Always display the first page after a loopback=false item finished executing. +void page(const struct MenuPage* pages, const size_t page_count, const bool infinite_loop); + /// Displaces a CUI menu to the user /// The length of the array itemv of menu items. /// An array of all menu items to display in the menu. From 9f5b615df917c65a46c748c74ece3b44c536908f Mon Sep 17 00:00:00 2001 From: CyB3RC0nN0R Date: Tue, 14 Jan 2020 08:12:36 +0100 Subject: [PATCH 3/3] Removed show_menu from menu.h, simplified some code --- menu.c | 126 +++++++++++++++++++++++++++++++-------------------------- menu.h | 17 ++------ 2 files changed, 73 insertions(+), 70 deletions(-) diff --git a/menu.c b/menu.c index 721e23d..7e51057 100644 --- a/menu.c +++ b/menu.c @@ -1,5 +1,6 @@ #include "pch.h" #include "framework.h" + #include "menu.h" const struct MenuBorder DEFAULT = { @@ -18,6 +19,66 @@ const struct MenuBorder SOLID = { 186, 205, 201, 187, 200, 188, '[', ']' }; +void show_menu(const int itemc, const struct MenuItem itemv[], const char title[], const struct MenuBorder* border); + +void page(const struct MenuPage* pages, const size_t page_count, const bool infinite_loop) +{ + unsigned int page_index = 0; + bool action_performed, loop, page_changed = true; + char page_key, itemKey; + int i; + + do { + do { + show_menu(pages[page_index].item_count, pages[page_index].items, pages[page_index].title, pages[page_index].border); + + // Wait for user selection + putchar('>'); + putchar(' '); + + loop = pages[page_index].loopback; + page_key = _getch(); + + // Forward paging + if (page_key == 'm' && page_index < page_count - 1) + ++page_index; + // Backward paging + else if (page_key == 'n' && page_index > 0) + --page_index; + else + { + page_changed = false; + itemKey = page_key; + do { + action_performed = false; + + itemKey != page_key ? itemKey = _getch() : page_key; + page_key = 0; + for (i = 0; i < pages[page_index].item_count; ++i) + { + if (pages[page_index].items[i].key == itemKey) + { + // Perform action + system("cls"); + pages[page_index].items[i].action(); + action_performed = true; + + // Pause if requested + if (pages[page_index].pause) + { + putchar('\n'); + system("pause"); + } + } + } + } while (!action_performed); + } + } while (loop || page_changed); + + page_index = 0; + } while (infinite_loop); +} + // Checks if a line index should display a menu item bool is_item_line(const int line, const int itemc, int* item_index) { @@ -40,57 +101,8 @@ void get_console_dimensions(int* width, int* height) *height = csbi.srWindow.Bottom - csbi.srWindow.Top + 1; } -void page(const struct MenuPage *pages, const size_t page_count, const bool infinite_loop) { - unsigned int page_index = 0; - bool action_performed, loop, pageChanged = true; - char pageKey, itemKey; - - do { - do { - show_menu(pages[page_index].item_count, pages[page_index].items, pages[page_index].title, pages[page_index].border); - - // Wait for user selection - putchar('>'); - putchar(' '); - - loop = pages[page_index].loopback; - pageKey = _getch(); - - if (pageKey == 'm') - page_index < page_count - 1 ? page_index++ : page_index; - else if (pageKey == 'n') - page_index > 0 ? page_index-- : page_index; - else { - pageChanged = false; - itemKey = pageKey; - do { - action_performed = false; - - itemKey != pageKey ? itemKey = _getch() : pageKey; - pageKey = 0; - for (int i = 0; i < pages[page_index].item_count; ++i) { - if (pages[page_index].items[i].key == itemKey) { - // Perform action - system("cls"); - pages[page_index].items[i].action(); - action_performed = true; - - // Pause if requested - if (pages[page_index].pause) { - putchar('\n'); - system("pause"); - } - } - } - } while (!action_performed); - } - } while (loop || pageChanged); - - page_index = 0; - } while (infinite_loop); -} - -void show_menu(const int itemc, const struct MenuItem itemv[], const char title[], const struct MenuBorder *border) +// Draws a menu to the console +void show_menu(const int itemc, const struct MenuItem itemv[], const char title[], const struct MenuBorder* border) { unsigned width, height, item_index; @@ -99,7 +111,7 @@ void show_menu(const int itemc, const struct MenuItem itemv[], const char title[ // Get the width and height of the console window get_console_dimensions(&width, &height); - + // Print frame with title for (unsigned i = 0; i < height - 1; ++i) { @@ -111,13 +123,13 @@ void show_menu(const int itemc, const struct MenuItem itemv[], const char title[ for (unsigned j = 1; j < width - strlen(title) - 2; ++j) { - if (j == ((width - strlen(title)) - 2)/ 2) + if (j == ((width - strlen(title)) - 2) / 2) { putchar(border->title_left); fputs(title, stdout); putchar(border->title_right); } - else + else { putchar(border->line_horizontal); } @@ -132,7 +144,7 @@ void show_menu(const int itemc, const struct MenuItem itemv[], const char title[ // Print item text putchar(border->line_vertical); - if (strcmp(itemv[item_index].text, "BLANK") == 0) { + if (strcmp(itemv[item_index].text, "BLANK") == 0) { putchar('\t'); // BLANK equals 5 characters @@ -146,13 +158,13 @@ void show_menu(const int itemc, const struct MenuItem itemv[], const char title[ { printf("\t%c) %s", itemv[item_index].key, itemv[item_index].text); } - + // Print right side of frame for (unsigned j = 0; j < width - strlen(itemv[item_index].text) - 12; ++j) { putchar(' '); } - + putchar(border->line_vertical); } // Line above bottom line diff --git a/menu.h b/menu.h index 63d3845..cb210ad 100644 --- a/menu.h +++ b/menu.h @@ -2,7 +2,6 @@ #include "pch.h" - /// Represents one menu item in a menu. struct MenuItem { char* text; @@ -22,10 +21,10 @@ struct MenuBorder { char title_right; }; +// Default borders initialized in menu.c const extern struct MenuBorder DEFAULT, MODERN, NO_BORDER, SOLID; - -/// Represents a page in the menu. +/// Represents a page containing menu items inside a menu. struct MenuPage { const struct MenuItem* items; const size_t item_count; @@ -34,16 +33,8 @@ struct MenuPage { const struct MenuBorder* border; }; - -/// Constructs a menu with a specific amount of pages +/// Constructs a CUI menu with a specific amount of pages. /// An array of all pages to display. /// The length of the array pages. /// Always display the first page after a loopback=false item finished executing. -void page(const struct MenuPage* pages, const size_t page_count, const bool infinite_loop); - -/// Displaces a CUI menu to the user -/// The length of the array itemv of menu items. -/// An array of all menu items to display in the menu. -/// The title of the menu. -/// Specifies the border in which the menu is displayed. -void show_menu(const int itemc, const struct MenuItem itemv[], const char title[], const struct MenuBorder *border); \ No newline at end of file +void page(const struct MenuPage* pages, const size_t page_count, const bool infinite_loop); \ No newline at end of file