This repository has been archived on 2021-03-14. You can view files and clone it, but cannot push or open issues or pull requests.
menu-lib/menu.c

119 lines
2.3 KiB
C

#include "pch.h"
#include "menu.h"
// Checks if a line index should display a menu item
bool is_item_line(const int line, const int itemc, int* item_index)
{
if (line >= 2 && line % 2 == 0)
{
// Lines 2, 4, ...
*item_index = (line - 2) / 2;
return *item_index < itemc;
}
return false;
}
// Acquires the dimensions (width and height) of the console window
void get_console_dimensions(int* width, int* height)
{
CONSOLE_SCREEN_BUFFER_INFO csbi;
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
*width = csbi.srWindow.Right - csbi.srWindow.Left + 1;
*height = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
}
void show_menu(const int itemc, struct MenuItem itemv[], const char title[], bool loopback, bool pause)
{
unsigned width, height, item_index;
char key;
bool action_performed;
// Clear the console window
system("cls");
// 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)
{
// Top line with title
if (i == 0)
{
for (unsigned j = 0; j < width - strlen(title) + 1; ++j)
{
if (j == (width - strlen(title)) / 2)
{
fputs(title, stdout);
}
else
{
putchar('*');
}
}
}
// Line with menu item
else if (is_item_line(i, itemc, &item_index))
{
// Print item text
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('*');
}
// Line above bottom line
else if (i == height - 2)
{
for (unsigned j = 0; j < width; ++j)
{
putchar('*');
}
}
// Blank line
else
{
putchar('*');
for (unsigned j = 0; j < width - 2; ++j)
{
putchar(' ');
}
putchar('*');
}
putchar('\n');
}
// Wait for user selection
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);
}
}