}
}
+static BOOLEAN unicode_supported(void) {
+ static INTN cache = -1;
+
+ if (cache < 0)
+ /* Basic unicode box drawing support is mandated by the spec, but it does
+ * not hurt to make sure it works. */
+ cache = !EFI_ERROR(ST->ConOut->TestString(ST->ConOut, (CHAR16 *) L"─"));
+
+ return cache;
+}
+
static void ps_string(const CHAR16 *fmt, const void *value) {
assert(fmt);
if (value)
UINT64 key;
EFI_STATUS err;
- Print(L"\n--- Press any key to continue, ESC or q to quit. ---\n\n");
+ if (unicode_supported())
+ Print(L"\n─── Press any key to continue, ESC or q to quit. ───\n\n");
+ else
+ Print(L"\n--- Press any key to continue, ESC or q to quit. ---\n\n");
+
err = console_key_read(&key, UINT64_MAX);
return !EFI_ERROR(err) && !IN_SET(key, KEYPRESS(0, SCAN_ESC, 0), KEYPRESS(0, 0, 'q'), KEYPRESS(0, 0, 'Q'));
}
UINTN x_start = 0, y_start = 0, y_status = 0;
UINTN x_max, y_max;
_cleanup_(strv_freep) CHAR16 **lines = NULL;
- _cleanup_freepool_ CHAR16 *clearline = NULL, *status = NULL;
+ _cleanup_freepool_ CHAR16 *clearline = NULL, *separator = NULL, *status = NULL;
UINT32 timeout_efivar_saved = config->timeout_sec_efivar;
UINT32 timeout_remain = config->timeout_sec == TIMEOUT_MENU_FORCE ? 0 : config->timeout_sec;
BOOLEAN exit = FALSE, run = TRUE, firmware_setup = FALSE;
log_error_stall(L"Error switching console mode: %r", err);
}
+ UINTN line_width = 0, entry_padding = 3;
while (!exit) {
UINT64 key;
if (new_mode) {
- UINTN line_width = 0, entry_padding = 3;
-
console_query_mode(&x_max, &y_max);
/* account for padding+status */
idx_last = idx_first + visible_max - 1;
/* length of the longest entry */
+ line_width = 0;
for (UINTN i = 0; i < config->entry_count; i++)
line_width = MAX(line_width, StrLen(config->entries[i]->title_show));
line_width = MIN(line_width + 2 * entry_padding, x_max);
y_start = 0;
/* Put status line after the entry list, but give it some breathing room. */
- y_status = MIN(y_start + MIN(visible_max, config->entry_count) + 4, y_max - 1);
+ y_status = MIN(y_start + MIN(visible_max, config->entry_count) + 1, y_max - 1);
lines = strv_free(lines);
clearline = mfree(clearline);
+ separator = mfree(separator);
/* menu entries title lines */
lines = xnew(CHAR16*, config->entry_count + 1);
lines[config->entry_count] = NULL;
clearline = xnew(CHAR16, x_max + 1);
- for (UINTN i = 0; i < x_max; i++)
+ separator = xnew(CHAR16, x_max + 1);
+ for (UINTN i = 0; i < x_max; i++) {
clearline[i] = ' ';
+ separator[i] = unicode_supported() ? L'─' : L'-';
+ }
clearline[x_max] = 0;
+ separator[x_max] = 0;
new_mode = FALSE;
clear = TRUE;
if (i == config->idx_default_efivar)
print_at(x_start, y_start + i - idx_first,
(i == idx_highlight) ? COLOR_HIGHLIGHT : COLOR_ENTRY,
- (CHAR16*) L"=>");
+ (CHAR16*) (unicode_supported() ? L" ►" : L"=>"));
}
refresh = FALSE;
} else if (highlight) {
print_at(x_start, y_start + idx_highlight_prev - idx_first, COLOR_ENTRY, lines[idx_highlight_prev]);
print_at(x_start, y_start + idx_highlight - idx_first, COLOR_HIGHLIGHT, lines[idx_highlight]);
if (idx_highlight_prev == config->idx_default_efivar)
- print_at(x_start , y_start + idx_highlight_prev - idx_first, COLOR_ENTRY, (CHAR16*) L"=>");
+ print_at(x_start , y_start + idx_highlight_prev - idx_first, COLOR_ENTRY, (CHAR16*) (unicode_supported() ? L" ►" : L"=>"));
if (idx_highlight == config->idx_default_efivar)
- print_at(x_start, y_start + idx_highlight - idx_first, COLOR_HIGHLIGHT, (CHAR16*) L"=>");
+ print_at(x_start, y_start + idx_highlight - idx_first, COLOR_HIGHLIGHT, (CHAR16*) (unicode_supported() ? L" ►" : L"=>"));
highlight = FALSE;
}
status = xpool_print(L"Boot in %u s.", timeout_remain);
}
- /* print status at last line of screen */
if (status) {
- UINTN len;
- UINTN x;
-
- /* center line */
- len = StrLen(status);
- if (len < x_max)
- x = (x_max - len) / 2;
- else
- x = 0;
- print_at(0, y_status, COLOR_NORMAL, clearline + (x_max - x));
+ /* If we draw the last char of the last line, the screen will scroll and break our
+ * input. Therefore, draw one less character then we could for the status message.
+ * Note that the same does not apply for the separator line as it will never be drawn
+ * on the last line. */
+ UINTN len = StrnLen(status, x_max - 1);
+ UINTN x = (x_max - len) / 2;
+ status[len] = '\0';
+ print_at(0, y_status, COLOR_NORMAL, clearline + x_max - x);
ST->ConOut->OutputString(ST->ConOut, status);
ST->ConOut->OutputString(ST->ConOut, clearline + 1 + x + len);
+
+ len = MIN(MAX(len, line_width) + 2 * entry_padding, x_max);
+ x = (x_max - len) / 2;
+ print_at(x, y_status - 1, COLOR_NORMAL, separator + x_max - len);
+ } else {
+ print_at(0, y_status - 1, COLOR_NORMAL, clearline);
+ print_at(0, y_status, COLOR_NORMAL, clearline + 1); /* See comment above. */
}
/* Beep several times so that the selected entry can be distinguished. */
timeout_remain = 0;
/* clear status after keystroke */
- if (status) {
- FreePool(status);
- status = NULL;
- print_at(0, y_status, COLOR_NORMAL, clearline + 1);
- }
+ status = mfree(status);
idx_highlight_prev = idx_highlight;