/* Expand key code - returns TRUE if successful. */ static int expand_key(const char *key, GSList **out) { GSList *tmp; const char *start; int last_hyphen; /* meta-^W^Gf -> ^[-^W-^G-f */ start = NULL; last_hyphen = TRUE; for (; *key != '\0'; key++) { if (start != NULL) { if (i_isalnum(*key) || *key == '_') { /* key combo continues */ continue; } if (!expand_combo(start, key-1, out)) return FALSE; expand_out_char(*out, '-'); start = NULL; } if (*key == '-') { if (last_hyphen) { expand_out_char(*out, '-'); expand_out_char(*out, '-'); } last_hyphen = !last_hyphen; } else if (*key == '^') { /* ctrl-code */ if (key[1] != '\0') key++; expand_out_char(*out, '^'); expand_out_char(*out, *key); expand_out_char(*out, '-'); last_hyphen = FALSE; /* optional */ } else if (last_hyphen && i_isalnum(*key) && !i_isdigit(*key)) { /* possibly beginning of keycombo */ start = key; last_hyphen = FALSE; } else { expand_out_char(*out, *key); expand_out_char(*out, '-'); last_hyphen = FALSE; /* optional */ } } if (start != NULL) return expand_combo(start, key-1, out); for (tmp = *out; tmp != NULL; tmp = tmp->next) { GString *str = tmp->data; g_string_truncate(str, str->len-1); } return TRUE; }
/* Expand key code - returns TRUE if successful. */ static int expand_key(const char *key, GSList **out, int *limit) { GSList *tmp; const char *start; int last_hyphen; if ((*limit)-- < 0) { return FALSE; } /* meta-^W^Gf -> ^[-^W-^G-f */ start = NULL; last_hyphen = TRUE; for (; *key != '\0'; key++) { if (start != NULL) { if (i_isalnum(*key) || *key == '_') { /* key combo continues */ continue; } if (!expand_combo(start, key-1, out, limit)) return FALSE; expand_out_char(*out, '-'); start = NULL; } if (*key == '-') { if (last_hyphen) { expand_out_char(*out, '-'); expand_out_char(*out, '-'); } last_hyphen = !last_hyphen; } else if (*key == '^') { expand_out_char(*out, '^'); /* ctrl-code */ if (key[1] != '\0' && key[1] != '-') { key++; expand_out_char(*out, *key); } else { /* escaped syntax for ^, see gui-readline.c */ expand_out_char(*out, '-'); } expand_out_char(*out, '-'); last_hyphen = FALSE; /* optional */ } else if (last_hyphen && i_isalpha(*key)) { /* possibly beginning of keycombo */ start = key; last_hyphen = FALSE; } else if (g_utf8_validate(key, -1, NULL)) { /* Assume we are looking at the start of a * multibyte sequence we will receive as-is, * so add it to the list as-is. */ const char *p, *end = g_utf8_next_char(key); for (p = key; p != end; p++) expand_out_char(*out, *p); expand_out_char(*out, '-'); /* The for loop skips past the remaining character. * Nasty, I know... */ key = end - 1; last_hyphen = FALSE; } else { expand_out_char(*out, *key); expand_out_char(*out, '-'); last_hyphen = FALSE; /* optional */ } } if (start != NULL) return expand_combo(start, key-1, out, limit); for (tmp = *out; tmp != NULL; tmp = tmp->next) { GString *str = tmp->data; g_string_truncate(str, str->len-1); } return TRUE; }
static int expand_combo(const char *start, const char *end, GSList **out, int *limit) { KEY_REC *rec; KEYINFO_REC *info; GSList *tmp, *tmp2, *list, *copy, *newout; char *str, *p; if ((*limit)-- < 0) { return FALSE; } if (start == end) { /* single key */ expand_out_char(*out, *start); return TRUE; } info = key_info_find("key"); if (info == NULL) return FALSE; /* get list of all key combos that generate the named combo.. */ list = NULL; str = g_strndup(start, (int) (end-start)+1); for (tmp = info->keys; tmp != NULL; tmp = tmp->next) { KEY_REC *rec = tmp->data; if (g_strcmp0(rec->data, str) == 0) list = g_slist_append(list, rec); } if (list == NULL) { /* unknown keycombo - add it as-is, maybe the GUI will feed it to us as such */ for (p = str; *p != '\0'; p++) expand_out_char(*out, *p); g_free(str); return TRUE; } g_free(str); if (list->next == NULL) { /* only one way to generate the combo, good */ rec = list->data; g_slist_free(list); return expand_key(rec->key, out, limit); } /* multiple ways to generate the combo - we'll need to include all of them in output */ newout = NULL; for (tmp = list->next; tmp != NULL; tmp = tmp->next) { KEY_REC *rec = tmp->data; copy = NULL; for (tmp2 = *out; tmp2 != NULL; tmp2 = tmp2->next) { GString *str = tmp2->data; copy = g_slist_append(copy, g_string_new(str->str)); } if (!expand_key(rec->key, ©, limit)) { if (*limit < 0) { return FALSE; } /* illegal key combo, remove from list */ expand_out_free(copy); } else { newout = g_slist_concat(newout, copy); } } rec = list->data; g_slist_free(list); if (!expand_key(rec->key, out, limit)) { if (*limit < 0) { return FALSE; } /* illegal key combo, remove from list */ expand_out_free(*out); } *out = g_slist_concat(*out, newout); return *out != NULL; }