mirror of
https://github.com/rvtr/unlaunch-installer_dev.git
synced 2026-01-26 13:43:08 -05:00
227 lines
3.6 KiB
C
227 lines
3.6 KiB
C
#include "menu.h"
|
|
#include "main.h"
|
|
|
|
Menu* newMenu()
|
|
{
|
|
Menu* m = (Menu*)malloc(sizeof(Menu));
|
|
|
|
m->cursor = 0;
|
|
m->page = 0;
|
|
m->itemCount = 0;
|
|
m->nextPage = false;
|
|
m->changePage = 0;
|
|
m->header[0] = '\0';
|
|
|
|
for (int i = 0; i < ITEMS_PER_PAGE; i++)
|
|
{
|
|
m->items[i].directory = false;
|
|
m->items[i].label = NULL;
|
|
m->items[i].value = NULL;
|
|
}
|
|
|
|
return m;
|
|
}
|
|
|
|
void freeMenu(Menu* m)
|
|
{
|
|
if (!m) return;
|
|
|
|
clearMenu(m);
|
|
|
|
free(m);
|
|
m = NULL;
|
|
}
|
|
|
|
void addMenuItem(Menu* m, char const* label, char const* value, bool directory)
|
|
{
|
|
if (!m) return;
|
|
|
|
int i = m->itemCount;
|
|
if (i >= ITEMS_PER_PAGE) return;
|
|
|
|
m->items[i].directory = directory;
|
|
|
|
if (label)
|
|
{
|
|
m->items[i].label = (char*)malloc(32);
|
|
sprintf(m->items[i].label, "%.31s", label);
|
|
}
|
|
|
|
if (value)
|
|
{
|
|
m->items[i].value = (char*)malloc(strlen(value)+1);
|
|
sprintf(m->items[i].value, "%s", value);
|
|
}
|
|
|
|
m->itemCount += 1;
|
|
}
|
|
|
|
static int alphabeticalCompare(const void* a, const void* b)
|
|
{
|
|
const Item* itemA = (const Item*)a;
|
|
const Item* itemB = (const Item*)b;
|
|
|
|
if (itemA->directory && !itemB->directory)
|
|
return -1;
|
|
else if (!itemA->directory && itemB->directory)
|
|
return 1;
|
|
else
|
|
return strcasecmp(itemA->label, itemB->label);
|
|
}
|
|
|
|
void sortMenuItems(Menu* m)
|
|
{
|
|
qsort(m->items, m->itemCount, sizeof(Item), alphabeticalCompare);
|
|
}
|
|
|
|
void setMenuHeader(Menu* m, char* str)
|
|
{
|
|
if (!m) return;
|
|
|
|
if (!str)
|
|
{
|
|
m->header[0] = '\0';
|
|
return;
|
|
}
|
|
|
|
char* strPtr = str;
|
|
|
|
if (strlen(strPtr) > 30)
|
|
strPtr = str + (strlen(strPtr) - 30);
|
|
|
|
sprintf(m->header, "%.30s", strPtr);
|
|
}
|
|
|
|
void resetMenu(Menu* m)
|
|
{
|
|
m->cursor = 0;
|
|
m->page = 0;
|
|
m->changePage = 0;
|
|
m->nextPage = 0;
|
|
}
|
|
|
|
void clearMenu(Menu* m)
|
|
{
|
|
if (!m) return;
|
|
|
|
for (int i = 0; i < ITEMS_PER_PAGE; i++)
|
|
{
|
|
if (m->items[i].label)
|
|
{
|
|
free(m->items[i].label);
|
|
m->items[i].label = NULL;
|
|
}
|
|
|
|
if (m->items[i].value)
|
|
{
|
|
free(m->items[i].value);
|
|
m->items[i].value = NULL;
|
|
}
|
|
}
|
|
|
|
m->itemCount = 0;
|
|
}
|
|
|
|
void printMenu(Menu* m)
|
|
{
|
|
clearScreen(&bottomScreen);
|
|
|
|
if (!m) return;
|
|
|
|
//header
|
|
iprintf("\x1B[42m"); //green
|
|
iprintf("%.30s\n\n", m->header);
|
|
iprintf("\x1B[47m"); //white
|
|
|
|
if (m->itemCount <= 0)
|
|
{
|
|
iprintf("Back - [B]\n");
|
|
return;
|
|
}
|
|
|
|
//items
|
|
for (int i = 0; i < m->itemCount; i++)
|
|
{
|
|
if (m->items[i].label)
|
|
{
|
|
if (m->items[i].directory)
|
|
iprintf(" [%.28s]\n", m->items[i].label);
|
|
else
|
|
iprintf(" %.30s\n", m->items[i].label);
|
|
}
|
|
else
|
|
iprintf(" \n");
|
|
}
|
|
|
|
//cursor
|
|
iprintf("\x1b[%d;0H>", 2 + m->cursor);
|
|
|
|
//scroll arrows
|
|
if (m->page > 0)
|
|
iprintf("\x1b[2;31H^");
|
|
|
|
if (m->nextPage)
|
|
iprintf("\x1b[21;31Hv");
|
|
}
|
|
|
|
static void _moveCursor(Menu* m, int dir)
|
|
{
|
|
if (m->changePage != 0)
|
|
return;
|
|
|
|
m->cursor += sign(dir);
|
|
|
|
if (m->cursor < 0)
|
|
{
|
|
if (m->page <= 0)
|
|
m->cursor = 0;
|
|
else
|
|
{
|
|
m->changePage = -1;
|
|
m->cursor = ITEMS_PER_PAGE - 1;
|
|
}
|
|
}
|
|
|
|
else if (m->cursor > m->itemCount-1)
|
|
{
|
|
if (m->nextPage && m->cursor >= ITEMS_PER_PAGE)
|
|
{
|
|
m->changePage = 1;
|
|
m->cursor = 0;
|
|
}
|
|
else
|
|
{
|
|
m->cursor = m->itemCount-1;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool moveCursor(Menu* m)
|
|
{
|
|
if (!m) return false;
|
|
|
|
m->changePage = 0;
|
|
int lastCursor = m->cursor;
|
|
|
|
u32 down = keysDownRepeat();
|
|
|
|
if (down & KEY_DOWN)
|
|
_moveCursor(m, 1);
|
|
|
|
else if (down & KEY_UP)
|
|
_moveCursor(m, -1);
|
|
|
|
if (down & KEY_RIGHT)
|
|
{
|
|
repeat(10)
|
|
_moveCursor(m, 1);
|
|
}
|
|
|
|
else if (down & KEY_LEFT)
|
|
{
|
|
repeat(10)
|
|
_moveCursor(m, -1);
|
|
}
|
|
|
|
return !(lastCursor == m->cursor);
|
|
} |