static void load_keyboard_map(char *xkbfile) { char* kbd; char* xkbfileEnd; int keymapLoaded = 0; kbd = xkbfile; xkbfileEnd = xkbfile + strlen(xkbfile); #ifdef __APPLE__ /* Apple X11 breaks XKB detection */ keymapLoaded += load_xkb_keyboard("macosx(macosx)"); #else do { // Multiple maps are separated by '+' int kbdlen = strcspn(kbd + 1, "+") + 1; kbd[kbdlen] = '\0'; // Load keyboard map keymapLoaded += load_xkb_keyboard(kbd); kbd += kbdlen + 1; } while(kbd < xkbfileEnd); #endif if(keymapLoaded <= 0) { // No keymap was loaded, load default hard-coded keymap memcpy(keycodeToVkcode, defaultKeycodeToVkcode, sizeof(keycodeToVkcode)); } }
void load_keyboard_map(KeycodeToVkcode keycodeToVkcode, char *xkbfile) { char* kbd; char* xkbfileEnd; int keymapLoaded = 0; memset(keycodeToVkcode, 0, sizeof(keycodeToVkcode)); kbd = xkbfile; xkbfileEnd = xkbfile + strlen(xkbfile); #ifdef __APPLE__ /* Apple X11 breaks XKB detection */ keymapLoaded += load_xkb_keyboard(keycodeToVkcode, "macosx(macosx)"); #else do { /* Multiple maps are separated by '+' */ int kbdlen = strcspn(kbd + 1, "+") + 1; kbd[kbdlen] = '\0'; /* Load keyboard map */ keymapLoaded += load_xkb_keyboard(keycodeToVkcode, kbd); kbd += kbdlen + 1; } while (kbd < xkbfileEnd); #endif DEBUG_KBD("loaded %d keymaps", keymapLoaded); if(keymapLoaded <= 0) { /* No keymap was loaded, load default hard-coded keymap */ DEBUG_KBD("using default keymap"); memcpy(keycodeToVkcode, defaultKeycodeToVkcode, sizeof(keycodeToVkcode)); } }
static int load_xkb_keyboard(KeycodeToVkcode map, char* kbd) { char* pch; char *beg, *end; char* home; char buffer[1024] = ""; char xkbfile[256] = ""; char xkbfilepath[512] = ""; char xkbmap[256] = ""; char xkbinc[256] = ""; FILE* fp; int kbdFound = 0; int i = 0; int keycode = 0; char keycodeString[32] = ""; char vkcodeName[128] = ""; beg = kbd; /* Extract file name and keymap name */ if((end = strrchr(kbd, '(')) != NULL) { strncpy(xkbfile, &kbd[beg - kbd], end - beg); beg = end + 1; if((end = strrchr(kbd, ')')) != NULL) { strncpy(xkbmap, &kbd[beg - kbd], end - beg); xkbmap[end - beg] = '\0'; } } else { /* The keyboard name is the same as the file name */ strcpy(xkbfile, kbd); strcpy(xkbmap, kbd); } /* Get path to file relative to freerdp's directory */ snprintf(xkbfilepath, sizeof(xkbfilepath), "keymaps/%s", xkbfile); DEBUG_KBD("Loading keymap %s, first trying %s", kbd, xkbfilepath); /* * Open the file for reading only * It can happen that the same file is opened twice at the same time * in order to load multiple keyboard maps from the same file, but * it does not matter: files can be opened as many times as we want * when it is for reading only. */ if((fp = fopen(xkbfilepath, "r")) == NULL) { /* Look first in path given at compile time (install path) */ snprintf(xkbfilepath, sizeof(xkbfilepath), "%s/%s", KEYMAP_PATH, xkbfile); if((fp = fopen(xkbfilepath, "r")) == NULL) { /* If ran from the source tree, the keymaps will be in the parent directory */ snprintf(xkbfilepath, sizeof(xkbfilepath), "../keymaps/%s", xkbfile); if((fp = fopen(xkbfilepath, "r")) == NULL) { /* File wasn't found in the source tree, try ~/.freerdp/ folder */ if((home = getenv("HOME")) == NULL) return 0; /* Get path to file in ~/.freerdp/ folder */ snprintf(xkbfilepath, sizeof(xkbfilepath), "%s/.freerdp/keymaps/%s", home, xkbfile); if((fp = fopen(xkbfilepath, "r")) == NULL) { /* Try /usr/share/freerdp folder */ snprintf(xkbfilepath, sizeof(xkbfilepath), "/usr/share/freerdp/keymaps/%s", xkbfile); if((fp = fopen(xkbfilepath, "r")) == NULL) { /* Try /usr/local/share/freerdp folder */ snprintf(xkbfilepath, sizeof(xkbfilepath), "/usr/local/share/freerdp/keymaps/%s", xkbfile); if((fp = fopen(xkbfilepath, "r")) == NULL) { /* Error: Could not find keymap */ DEBUG_KBD("keymaps for %s not found", xkbfile); return 0; } } } } } } DEBUG_KBD("xkbfilepath: %s", xkbfilepath); while(fgets(buffer, sizeof(buffer), fp) != NULL) { if(buffer[0] == '#') { continue; /* Skip comments */ } if(kbdFound) { /* Closing curly bracket and semicolon */ if((pch = strstr(buffer, "};")) != NULL) { break; } else if((pch = strstr(buffer, "VK_")) != NULL) { /* The end is delimited by the first white space */ end = strcspn(pch, " \t\n\0") + pch; /* We copy the virtual key code name in a string */ beg = pch; strncpy(vkcodeName, beg, end - beg); vkcodeName[end - beg] = '\0'; /* Now we want to extract the virtual key code itself which is in between '<' and '>' */ if((beg = strchr(pch + 3, '<')) == NULL) break; else beg++; if((end = strchr(beg, '>')) == NULL) break; /* We copy the string representing the number in a string */ strncpy(keycodeString, beg, end - beg); keycodeString[end - beg] = '\0'; /* Convert the string representing the code to an integer */ keycode = atoi(keycodeString); /* Make sure it is a valid keycode */ if(keycode < 0 || keycode > 255) break; /* Load this key mapping in the keyboard mapping */ for(i = 0; i < sizeof(virtualKeyboard) / sizeof(virtualKey); i++) { if(strcmp(vkcodeName, virtualKeyboard[i].name) == 0) { map[keycode] = i; } } } else if((pch = strstr(buffer, ": extends")) != NULL) { /* * This map extends another keymap We extract its name * and we recursively load the keymap we need to include. */ if((beg = strchr(pch + sizeof(": extends"), '"')) == NULL) break; beg++; if((end = strchr(beg, '"')) == NULL) break; strncpy(xkbinc, beg, end - beg); xkbinc[end - beg] = '\0'; load_xkb_keyboard(map, xkbinc); /* Load included keymap */ } } else if((pch = strstr(buffer, "keyboard")) != NULL) { /* Keyboard map identifier */ if((beg = strchr(pch + sizeof("keyboard"), '"')) == NULL) break; beg++; if((end = strchr(beg, '"')) == NULL) break; pch = beg; buffer[end - beg] = '\0'; /* Does it match our keymap name? */ if(strncmp(xkbmap, pch, strlen(xkbmap)) == 0) kbdFound = 1; } } fclose(fp); /* Don't forget to close file */ return 1; }