mirror of
https://github.com/limine-bootloader/limine
synced 2024-12-12 09:44:04 +03:00
commit
6b4d5cb6be
@ -67,6 +67,9 @@ Some keys take *URIs* as values; these are described in the next section.
|
||||
* `BACKGROUND_STYLE` - The style which will be used to display the background image. Either `tiled` or `centered`. Default is `tiled`.
|
||||
* `BACKDROP_COLOUR` - When the background style is `centered`, this specifies the colour of the backdrop for parts of the screen not covered by the background image, in RRGGBB format.
|
||||
* `BACKDROP_COLOR` - Alias of `BACKDROP_COLOUR`.
|
||||
* `EDITOR_ENABLED` - If set to `no`, the editor will not be accessible. Defaults to `yes`.
|
||||
* `EDITOR_HIGHLIGHTING` - If set to `no`, syntax highlighting in the editor will be disabled. Defaults to `yes`.
|
||||
* `EDITOR_VALIDATION` - If set to `no`, the editor will not alert you about invalid keys / syntax errors. Defaults to `yes`.
|
||||
* `VERBOSE` - If set to `yes`, print additional information during boot. Defaults to not verbose.
|
||||
|
||||
*Locally assignable (non protocol specific)* keys are:
|
||||
|
176
stage23/menu.c
176
stage23/menu.c
@ -16,6 +16,10 @@
|
||||
static char *menu_branding = NULL;
|
||||
|
||||
#define EDITOR_MAX_BUFFER_SIZE 4096
|
||||
#define TOK_KEY 0
|
||||
#define TOK_EQUALS 1
|
||||
#define TOK_VALUE 2
|
||||
#define TOK_BADKEY 3
|
||||
|
||||
static size_t get_line_offset(size_t *displacement, size_t index, const char *buffer) {
|
||||
size_t offset = 0;
|
||||
@ -67,7 +71,69 @@ static size_t get_prev_line(size_t index, const char *buffer) {
|
||||
return offset;
|
||||
}
|
||||
|
||||
static char *config_entry_editor(const char *orig_entry) {
|
||||
static const char *VALID_KEYS[] = {
|
||||
"TIMEOUT",
|
||||
"DEFAULT_ENTRY",
|
||||
"GRAPHICS",
|
||||
"MENU_RESOLUTION",
|
||||
"MENU_BRANDING",
|
||||
"MENU_FONT",
|
||||
"TERMINAL_FONT",
|
||||
"THEME_COLOURS",
|
||||
"THEME_COLORS",
|
||||
"THEME_BACKGROUND",
|
||||
"THEME_FOREGROUND",
|
||||
"THEME_MARGIN",
|
||||
"THEME_MARGIN_GRADIENT",
|
||||
"BACKGROUND_PATH",
|
||||
"BACKGROUND_STYLE",
|
||||
"BACKDROP_COLOUR",
|
||||
"BACKDROP_COLOR",
|
||||
"EDITOR_ENABLED",
|
||||
"EDITOR_HIGHLIGHTING",
|
||||
"EDITOR_VALIDATION",
|
||||
"VERBOSE",
|
||||
"PROTOCOL",
|
||||
"CMDLINE",
|
||||
"KERNEL_CMDLINE",
|
||||
"KERNEL_PATH",
|
||||
"MODULE_PATH",
|
||||
"MODULE_STRING",
|
||||
"RESOLUTION",
|
||||
"KASLR",
|
||||
"DRIVE",
|
||||
"PARTITION",
|
||||
"IMAGE_PATH",
|
||||
NULL
|
||||
};
|
||||
|
||||
static bool validation_enabled = true;
|
||||
static bool invalid_syntax = false;
|
||||
|
||||
static int validate_line(const char *buffer) {
|
||||
if (!validation_enabled) return TOK_KEY;
|
||||
char keybuf[64];
|
||||
int i;
|
||||
for (i = 0; buffer[i] && i < 64; i++) {
|
||||
if (buffer[i] == '=') goto found_equals;
|
||||
keybuf[i] = buffer[i];
|
||||
}
|
||||
fail:
|
||||
if (i < 64) keybuf[i] = 0;
|
||||
if (keybuf[0] == '\n' || (!keybuf[0] && buffer[0] != '=')) return TOK_KEY; // blank line is valid
|
||||
invalid_syntax = true;
|
||||
return TOK_BADKEY;
|
||||
found_equals:
|
||||
if (i < 64) keybuf[i] = 0;
|
||||
for (i = 0; VALID_KEYS[i]; i++) {
|
||||
if (!strcmp(keybuf, VALID_KEYS[i])) {
|
||||
return TOK_KEY;
|
||||
}
|
||||
}
|
||||
goto fail;
|
||||
}
|
||||
|
||||
static char *config_entry_editor(const char *title, const char *orig_entry) {
|
||||
size_t cursor_offset = 0;
|
||||
size_t entry_size = strlen(orig_entry);
|
||||
size_t _window_size = term_rows - 11;
|
||||
@ -82,8 +148,17 @@ static char *config_entry_editor(const char *orig_entry) {
|
||||
entry_size--;
|
||||
}
|
||||
|
||||
if (entry_size >= EDITOR_MAX_BUFFER_SIZE)
|
||||
if (entry_size >= EDITOR_MAX_BUFFER_SIZE) {
|
||||
panic("Entry is too big to be edited.");
|
||||
}
|
||||
|
||||
bool syntax_highlighting_enabled = true;
|
||||
char *syntax_highlighting_enabled_config = config_get_value(NULL, 0, "EDITOR_HIGHLIGHTING");
|
||||
if (!strcmp(syntax_highlighting_enabled_config, "no")) syntax_highlighting_enabled = false;
|
||||
|
||||
validation_enabled = true;
|
||||
char *validation_enabled_config = config_get_value(NULL, 0, "EDITOR_VALIDATION");
|
||||
if (!strcmp(validation_enabled_config, "no")) validation_enabled = false;
|
||||
|
||||
static char *buffer = NULL;
|
||||
if (buffer == NULL)
|
||||
@ -92,12 +167,15 @@ static char *config_entry_editor(const char *orig_entry) {
|
||||
buffer[entry_size] = 0;
|
||||
|
||||
refresh:
|
||||
invalid_syntax = false;
|
||||
|
||||
clear(true);
|
||||
disable_cursor();
|
||||
print("\n\n \e[36m %s \e[37m\n\n\n", menu_branding);
|
||||
|
||||
print("Editing entry.\n");
|
||||
print("Press esc to return to main menu and discard changes, press F10 to boot.\n");
|
||||
//print("Editing \"%s\"\n", title);
|
||||
print(" \e[32mESC\e[0m Discard and Exit \e[32mF10\e[0m Boot\n");
|
||||
|
||||
|
||||
print("\n\xda");
|
||||
for (int i = 0; i < term_cols - 2; i++) {
|
||||
@ -108,8 +186,15 @@ refresh:
|
||||
break;
|
||||
}
|
||||
// FALLTHRU
|
||||
default:
|
||||
print("\xc4");
|
||||
default: {
|
||||
int title_length = strlen(title);
|
||||
if (i == (term_cols / 2) - (title_length / 2) - 1) {
|
||||
print("%s", title);
|
||||
i += title_length - 1;
|
||||
} else {
|
||||
print("\xc4");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
print("\xbf\xb3");
|
||||
@ -117,7 +202,9 @@ refresh:
|
||||
int cursor_x, cursor_y;
|
||||
size_t current_line = 0, line_offset = 0, window_size = _window_size;
|
||||
bool printed_cursor = false;
|
||||
int token_type = validate_line(buffer);
|
||||
for (size_t i = 0; ; i++) {
|
||||
// newline
|
||||
if (buffer[i] == '\n'
|
||||
&& current_line < window_offset + window_size
|
||||
&& current_line >= window_offset) {
|
||||
@ -134,6 +221,7 @@ refresh:
|
||||
else
|
||||
print("\xb3\xb3");
|
||||
line_offset = 0;
|
||||
token_type = validate_line(buffer+i+1);
|
||||
current_line++;
|
||||
continue;
|
||||
}
|
||||
@ -175,10 +263,48 @@ refresh:
|
||||
|
||||
if (current_line >= window_offset) {
|
||||
line_offset++;
|
||||
print("%c", buffer[i]);
|
||||
|
||||
// switch to token type 1 if equals sign
|
||||
if (token_type == TOK_KEY && buffer[i] == '=') token_type = TOK_EQUALS;
|
||||
|
||||
// syntax highlighting
|
||||
if (syntax_highlighting_enabled) {
|
||||
switch (token_type) {
|
||||
case TOK_KEY:
|
||||
print("\e[36m%c\e[0m", buffer[i]);
|
||||
break;
|
||||
case TOK_EQUALS:
|
||||
print("\e[32m%c\e[0m", buffer[i]);
|
||||
break;
|
||||
case TOK_VALUE:
|
||||
print("\e[39m%c\e[0m", buffer[i]);
|
||||
break;
|
||||
case TOK_BADKEY:
|
||||
print("\e[31m%c\e[0m", buffer[i]);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
print("%c", buffer[i]);
|
||||
}
|
||||
|
||||
// switch to token type 2 after equals sign
|
||||
if (token_type == TOK_EQUALS) token_type = TOK_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
// syntax error alert
|
||||
if (validation_enabled) {
|
||||
int x, y;
|
||||
get_cursor_pos(&x, &y);
|
||||
set_cursor_pos(0, term_rows-2);
|
||||
if (invalid_syntax) {
|
||||
print("\e[31mConfiguration is INVALID.\e[0m");
|
||||
} else {
|
||||
print("\e[32mConfiguration is valid.\e[0m");
|
||||
}
|
||||
set_cursor_pos(x, y);
|
||||
}
|
||||
|
||||
if (current_line - window_offset < window_size) {
|
||||
int x, y;
|
||||
for (size_t i = 0; i < (window_size - (current_line - window_offset)) - 1; i++) {
|
||||
@ -349,6 +475,10 @@ char *menu(char **cmdline) {
|
||||
timeout = strtoui(timeout_config, NULL, 10);
|
||||
}
|
||||
|
||||
bool editor_enabled = true;
|
||||
char *editor_enabled_config = config_get_value(NULL, 0, "EDITOR_ENABLED");
|
||||
if (!strcmp(editor_enabled_config, "no")) editor_enabled = false;
|
||||
|
||||
if (!timeout) {
|
||||
// Use print tree to load up selected_menu_entry and determine if the
|
||||
// default entry is valid.
|
||||
@ -394,7 +524,7 @@ refresh:
|
||||
getchar();
|
||||
char *new_body = NULL;
|
||||
while (new_body == NULL)
|
||||
new_body = config_entry_editor("");
|
||||
new_body = config_entry_editor("New Entry", "");
|
||||
selected_menu_entry = ext_mem_alloc(sizeof(struct menu_entry));
|
||||
selected_menu_entry->body = new_body;
|
||||
config_ready = true;
|
||||
@ -406,7 +536,17 @@ refresh:
|
||||
int max_entries = print_tree(0, 0, selected_entry, menu_tree,
|
||||
&selected_menu_entry);
|
||||
|
||||
print("\nArrows to select, enter to boot, 'e' to edit selected entry.");
|
||||
{
|
||||
int x, y;
|
||||
get_cursor_pos(&x, &y);
|
||||
set_cursor_pos(0, 4);
|
||||
if (editor_enabled && selected_menu_entry->sub == NULL) {
|
||||
print("\n \e[32mARROWS\e[0m Select \e[32mENTER\e[0m Boot \e[32mE\e[0m Edit");
|
||||
} else {
|
||||
print("\n \e[32mARROWS\e[0m Select \e[32mENTER\e[0m Boot");
|
||||
}
|
||||
set_cursor_pos(x, y);
|
||||
}
|
||||
|
||||
if (selected_menu_entry->sub != NULL)
|
||||
skip_timeout = true;
|
||||
@ -461,14 +601,16 @@ timeout_aborted:
|
||||
term_double_buffer(false);
|
||||
return selected_menu_entry->body;
|
||||
case 'e': {
|
||||
if (selected_menu_entry->sub != NULL)
|
||||
goto refresh;
|
||||
enable_cursor();
|
||||
char *new_body = config_entry_editor(selected_menu_entry->body);
|
||||
if (new_body == NULL)
|
||||
goto refresh;
|
||||
selected_menu_entry->body = new_body;
|
||||
goto autoboot;
|
||||
if (editor_enabled) {
|
||||
if (selected_menu_entry->sub != NULL)
|
||||
goto refresh;
|
||||
enable_cursor();
|
||||
char *new_body = config_entry_editor(selected_menu_entry->name, selected_menu_entry->body);
|
||||
if (new_body == NULL)
|
||||
goto refresh;
|
||||
selected_menu_entry->body = new_body;
|
||||
goto autoboot;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user