?? keytab.c
字號:
* of '\E' to denote the escape key. Similarly, meta characters can be * given directly in binary or expressed as M- followed by the character. * Meta characters are recorded as two characters in the binary output * string, the first being the escape key, and the second being the key * that was modified by the meta key. This means that binding to * \EA or ^[A or M-A are all equivalent. * * Input: * keyseq char * The key sequence being added. * Input/Output: * binary char * The binary version of the key sequence will be * assigned to binary[], which must have at least * as many characters as keyseq[] plus the number * of embedded binary meta characters. * nc int * The number of characters assigned to binary[] * will be recorded in *nc. * Output: * return int 0 - OK. * 1 - Error. */int _kt_parse_keybinding_string(const char *keyseq, char *binary, int *nc){ const char *iptr = keyseq; /* Pointer into keyseq[] */ char *optr = binary; /* Pointer into binary[] *//* * Parse the input characters until they are exhausted or the * output string becomes full. */ while(*iptr) {/* * Check for special characters. */ switch(*iptr) { case '^': /* A control character specification *//* * Convert the caret expression into the corresponding control * character unless no character follows the caret, in which case * record a literal caret. */ if(iptr[1]) { *optr++ = MAKE_CTRL(iptr[1]); iptr += 2; } else { *optr++ = *iptr++; }; break;/* * A backslash-escaped character? */ case '\\':/* * Convert the escape sequence to a binary character. */ *optr++ = _kt_backslash_escape(iptr+1, &iptr); break;/* * Possibly an emacs-style meta character? */ case 'M': if(_kt_is_emacs_meta(iptr)) { *optr++ = GL_ESC_CHAR; iptr += 2; } else { *optr++ = *iptr++; }; break;/* * Possibly an emacs-style control character specification? */ case 'C': if(_kt_is_emacs_ctrl(iptr)) { *optr++ = MAKE_CTRL(iptr[2]); iptr += 3; } else { *optr++ = *iptr++; }; break; default:/* * Convert embedded meta characters into an escape character followed * by the meta-unmodified character. */ if(IS_META_CHAR(*iptr)) { *optr++ = GL_ESC_CHAR; *optr++ = META_TO_CHAR(*iptr); iptr++;/* * To allow keysequences that start with printable characters to * be distinguished from the cursor-key keywords, prepend a backslash * to the former. This same operation is performed in gl_interpret_char() * before looking up a keysequence that starts with a printable character. */ } else if(iptr==keyseq && !IS_CTRL_CHAR(*iptr) && strcmp(keyseq, "up") != 0 && strcmp(keyseq, "down") != 0 && strcmp(keyseq, "left") != 0 && strcmp(keyseq, "right") != 0) { *optr++ = '\\'; *optr++ = *iptr++; } else { *optr++ = *iptr++; }; }; };/* * How many characters were placed in the output array? */ *nc = optr - binary; return 0;}/*....................................................................... * Add, remove or modify an action. * * Input: * kt KeyTab * The key-binding table. * action char * The name of the action. * fn KtKeyFn * The function that implements the action, or NULL * to remove an existing action. * Output: * return int 0 - OK. * 1 - Error. */int _kt_set_action(KeyTab *kt, const char *action, KtKeyFn *fn){ Symbol *sym; /* The symbol table entry of the action *//* * Check the arguments. */ if(!kt || !action) { fprintf(stderr, "kt_set_action: NULL argument(s).\n"); return 1; };/* * If no function was provided, delete an existing action. */ if(!fn) { sym = _del_HashSymbol(kt->actions, action); return 0; };/* * If the action already exists, replace its action function. */ sym = _find_HashSymbol(kt->actions, action); if(sym) { sym->fn = (void (*)(void))fn; return 0; };/* * Add a new action. */ if(!_new_HashSymbol(kt->actions, action, 0, (void (*)(void))fn, NULL, 0)) { fprintf(stderr, "Insufficient memory to record new key-binding action.\n"); return 1; }; return 0;}/*....................................................................... * Compare two strings of specified length which may contain embedded * ascii NUL's. * * Input: * s1 char * The first of the strings to be compared. * n1 int The length of the string in s1. * s2 char * The second of the strings to be compared. * n2 int The length of the string in s2. * Output: * return int < 0 if(s1 < s2) * 0 if(s1 == s2) * > 0 if(s1 > s2) */static int _kt_compare_strings(const char *s1, int n1, const char *s2, int n2){ int i;/* * Find the first character where the two strings differ. */ for(i=0; i<n1 && i<n2 && s1[i]==s2[i]; i++) ;/* * Did we hit the end of either string before finding a difference? */ if(i==n1 || i==n2) { if(n1 == n2) return 0; else if(n1==i) return -1; else return 1; };/* * Compare the two characters that differed to determine which * string is greatest. */ return s1[i] - s2[i];}/*....................................................................... * Assign a given action function to a binding table entry. * * Input: * sym KeySym * The binding table entry to be modified. * binder KtBinder The source of the binding. * keyfn KtKeyFn * The action function. */static void _kt_assign_action(KeySym *sym, KtBinder binder, KtKeyFn *keyfn){/* * Record the action according to its source. */ switch(binder) { case KTB_USER: sym->user_fn = keyfn; break; case KTB_TERM: sym->term_fn = keyfn; break; case KTB_NORM: default: sym->norm_fn = keyfn; break; };/* * Which of the current set of bindings should be used? */ if(sym->user_fn) sym->keyfn = sym->user_fn; else if(sym->norm_fn) sym->keyfn = sym->norm_fn; else sym->keyfn = sym->term_fn; return;}/*....................................................................... * Remove all key bindings that came from a specified source. * * Input: * kt KeyTab * The table of key bindings. * binder KtBinder The source of the bindings to be cleared. */void _kt_clear_bindings(KeyTab *kt, KtBinder binder){ int oldkey; /* The index of a key in the original binding table */ int newkey; /* The index of a key in the updated binding table *//* * If there is no table, then no bindings exist to be deleted. */ if(!kt) return;/* * Clear bindings of the given source. */ for(oldkey=0; oldkey<kt->nkey; oldkey++) _kt_assign_action(kt->table + oldkey, binder, 0);/* * Delete entries that now don't have a binding from any source. */ newkey = 0; for(oldkey=0; oldkey<kt->nkey; oldkey++) { KeySym *sym = kt->table + oldkey; if(!sym->keyfn) { _del_StringMemString(kt->smem, sym->keyseq); } else { if(oldkey != newkey) kt->table[newkey] = *sym; newkey++; }; };/* * Record the number of keys that were kept. */ kt->nkey = newkey; return;}/*....................................................................... * Translate a backslash escape sequence to a binary character. * * Input: * string const char * The characters that follow the backslash. * Input/Output: * endp const char ** If endp!=NULL, on return *endp will be made to * point to the character in string[] which follows * the escape sequence. * Output: * return char The binary character. */static char _kt_backslash_escape(const char *string, const char **endp){ char c; /* The output character *//* * Is the backslash followed by one or more octal digits? */ switch(*string) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': c = strtol(string, (char **)&string, 8); break; case 'a': c = '\a'; string++; break; case 'b': c = '\b'; string++; break; case 'e': case 'E': /* Escape */ c = GL_ESC_CHAR; string++; break; case 'f': c = '\f'; string++; break; case 'n': c = '\n'; string++; break; case 'r': c = '\r'; string++; break; case 't': c = '\t'; string++; break; case 'v': c = '\v'; string++; break; case '\0': c = '\\'; break; default: c = *string++; break; };/* * Report the character which follows the escape sequence. */ if(endp) *endp = string; return c;}/*....................................................................... * Return non-zero if the next two characters are M- and a third character * follows. Otherwise return 0. * * Input: * string const char * The sub-string to scan. * Output: * return int 1 - The next two characters are M- and these * are followed by at least one character. * 0 - The next two characters aren't M- or no * character follows a M- pair. */static int _kt_is_emacs_meta(const char *string){ return *string++ == 'M' && *string++ == '-' && *string;}/*....................................................................... * Return non-zero if the next two characters are C- and a third character * follows. Otherwise return 0. * * Input: * string const char * The sub-string to scan. * Output: * return int 1 - The next two characters are C- and these * are followed by at least one character. * 0 - The next two characters aren't C- or no * character follows a C- pair. */static int _kt_is_emacs_ctrl(const char *string){ return *string++ == 'C' && *string++ == '-' && *string;}/*....................................................................... * Merge an array of bindings with existing bindings. * * Input: * kt KeyTab * The table of key bindings. * binder KtBinder The source of the bindings. * bindings const KtKeyBinding * The array of bindings. * n int The number of bindings in bindings[]. * Output: * return int 0 - OK. * 1 - Error. */int _kt_add_bindings(KeyTab *kt, KtBinder binder, const KtKeyBinding *bindings, unsigned n){ int i;/* * Check the arguments. */ if(!kt || !bindings) { fprintf(stderr, "_kt_add_bindings: NULL argument(s).\n"); return 1; };/* * Install the array of bindings. */ for(i=0; i<n; i++) { if(_kt_set_keybinding(kt, binder, bindings[i].keyseq, bindings[i].action)) return 1; }; return 0;}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -