diff --git a/AUTHORS.md b/AUTHORS.md new file mode 100644 index 00000000..51fcac29 --- /dev/null +++ b/AUTHORS.md @@ -0,0 +1,6 @@ +The following are the authors/maintainers of Limine with the rights to push commits to trunk and create +releases signed with their GPG keys. + +- Mintsuki, GPG ID 05D29860D0A0668AAEFB9D691F3C021BECA23821. +- Iczelia (Kamila Szewczyk), GPG ID 6C222EA6B2BD216AA406516AC868F0B6DE38409D. + diff --git a/CONFIG.md b/CONFIG.md index 631db57a..45ee6236 100644 --- a/CONFIG.md +++ b/CONFIG.md @@ -127,6 +127,12 @@ Miscellaneous: "displayed" status bit in the ACPI BGRT table so the OS redraws the logo itself. The image is re-centred for the active resolution. UEFI only; defaults to `no`. +* `keyboard_layout` - Specifies a keyboard layout to remap printable + keystrokes to before they reach the menu and editor. Currently only + `dvorak` is supported. If unset, no remapping is applied and keystrokes + are used as-is. This assumes the underlying firmware resolves keystrokes + as US-QWERTY; on firmware/keyboard combinations that already resolve a + different layout natively, this option may produce incorrect output. Limine interface control options: diff --git a/common/lib/getchar.c b/common/lib/getchar.c index 2c5bab3e..7a135187 100644 --- a/common/lib/getchar.c +++ b/common/lib/getchar.c @@ -5,6 +5,7 @@ #include #include #include +#include #if defined (BIOS) # include #elif defined (UEFI) @@ -13,6 +14,25 @@ #include #include +static const char qwerty_to_dvorak[128] = { + ['q']='\'', ['w']=',', ['e']='.', ['r']='p', ['t']='y', + ['y']='f', ['u']='g', ['i']='c', ['o']='r', ['p']='l', + ['[']='/', [']']='=', ['\\']='\\', ['a']='a', ['s']='o', + ['d']='e', ['f']='u', ['g']='i', ['h']='d', ['j']='h', + ['k']='t', ['l']='n', [';']='s', ['\'']='-', ['z']=';', ['x']='q', + ['c']='j', ['v']='k', ['b']='x', ['n']='b', ['m']='m', + [',']='w', ['.']='v', ['/']='z', + + ['Q']='\"', ['W']='<', ['E']='>', ['R']='P', ['T']='Y', + ['Y']='F', ['U']='G', ['I']='C', ['O']='R', ['P']='L', + ['{']='?', ['}']='+', ['|']='|', ['A']='A', ['S']='O', + ['D']='E', ['F']='U', ['G']='I', ['H']='D', ['J']='H', + ['K']='T', ['L']='N', [':']='S', ['"']='_', ['Z']=':', ['X']='Q', + ['C']='J', ['V']='K', ['B']='X', ['N']='B', ['M']='M', + ['<']='W', ['>']='V', ['?']='Z', +}; + + int getchar(void) { for (;;) { int ret = pit_sleep_and_quit_on_keypress(65535); @@ -104,6 +124,11 @@ int getchar_internal(uint8_t scancode, uint8_t ascii, uint32_t shift_state) { if (ascii < 0x20 || ascii > 0x7e) { return -1; } + + if (current_keyboard_layout == KEYBOARD_LAYOUT_DVORAK && qwerty_to_dvorak[(uint8_t)ascii] != 0) { + return qwerty_to_dvorak[(uint8_t)ascii]; + } + return ascii; } diff --git a/common/menu.c b/common/menu.c index 5dbe150c..bc81a0eb 100644 --- a/common/menu.c +++ b/common/menu.c @@ -48,6 +48,17 @@ static char menu_branding_colour[24] = "\e[38;2;0;170;170m"; static char *menu_branding = NULL; +enum keyboard_layout current_keyboard_layout = KEYBOARD_LAYOUT_UNKNOWN; + +static void keyboard_layout_init(void) { + char *layout = config_get_value(NULL, 0, "keyboard_layout"); + if (layout != NULL && strcasecmp(layout, "dvorak") == 0) { + current_keyboard_layout = KEYBOARD_LAYOUT_DVORAK; + } else { + current_keyboard_layout = KEYBOARD_LAYOUT_QWERTY; + } +} + static char *append_uint_dec(char *p, uint64_t val) { char buf[20]; size_t i = 0; @@ -1161,7 +1172,7 @@ static void menu_init_term(void) { #elif defined (UEFI) char *graphics = "yes"; #endif - + keyboard_layout_init(); if (graphics == NULL || strcmp(graphics, "no") != 0) { size_t req_width = 0, req_height = 0, req_bpp = 0; diff --git a/common/menu.h b/common/menu.h index acaa65c5..d80c5f77 100644 --- a/common/menu.h +++ b/common/menu.h @@ -19,4 +19,12 @@ char *config_entry_editor(const char *title, const char *orig_entry); extern bool booting_from_editor; +enum keyboard_layout { + KEYBOARD_LAYOUT_UNKNOWN = -1, + KEYBOARD_LAYOUT_QWERTY, + KEYBOARD_LAYOUT_DVORAK, +}; + +extern enum keyboard_layout current_keyboard_layout; + #endif