📄 parse_entry.c
字号:
} _nc_wrap_entry(entryp, FALSE); return (OK);}NCURSES_EXPORT(int)_nc_capcmp(const char *s, const char *t)/* compare two string capabilities, stripping out padding */{ if (!s && !t) return (0); else if (!s || !t) return (1); for (;;) { if (s[0] == '$' && s[1] == '<') { for (s += 2;; s++) if (!(isdigit(UChar(*s)) || *s == '.' || *s == '*' || *s == '/' || *s == '>')) break; } if (t[0] == '$' && t[1] == '<') { for (t += 2;; t++) if (!(isdigit(UChar(*t)) || *t == '.' || *t == '*' || *t == '/' || *t == '>')) break; } /* we've now pushed s and t past any padding they were pointing at */ if (*s == '\0' && *t == '\0') return (0); if (*s != *t) return (*t - *s); /* else *s == *t but one is not NUL, so continue */ s++, t++; }}static voidappend_acs0(string_desc * dst, int code, int src){ if (src != 0) { char temp[3]; temp[0] = code; temp[1] = src; temp[2] = 0; _nc_safe_strcat(dst, temp); }}static voidappend_acs(string_desc * dst, int code, char *src){ if (src != 0 && strlen(src) == 1) { append_acs0(dst, code, *src); }}/* * The ko capability, if present, consists of a comma-separated capability * list. For each capability, we may assume there is a keycap that sends the * string which is the value of that capability. */typedef struct { const char *from; const char *to;} assoc;static assoc const ko_xlate[] ={ {"al", "kil1"}, /* insert line key -> KEY_IL */ {"bt", "kcbt"}, /* back tab -> KEY_BTAB */ {"cd", "ked"}, /* clear-to-eos key -> KEY_EOL */ {"ce", "kel"}, /* clear-to-eol key -> KEY_EOS */ {"cl", "kclr"}, /* clear key -> KEY_CLEAR */ {"ct", "tbc"}, /* clear all tabs -> KEY_CATAB */ {"dc", "kdch1"}, /* delete char -> KEY_DC */ {"dl", "kdl1"}, /* delete line -> KEY_DL */ {"do", "kcud1"}, /* down key -> KEY_DOWN */ {"ei", "krmir"}, /* exit insert key -> KEY_EIC */ {"ho", "khome"}, /* home key -> KEY_HOME */ {"ic", "kich1"}, /* insert char key -> KEY_IC */ {"im", "kIC"}, /* insert-mode key -> KEY_SIC */ {"le", "kcub1"}, /* le key -> KEY_LEFT */ {"nd", "kcuf1"}, /* nd key -> KEY_RIGHT */ {"nl", "kent"}, /* new line key -> KEY_ENTER */ {"st", "khts"}, /* set-tab key -> KEY_STAB */ {"ta", CANCELLED_STRING}, {"up", "kcuu1"}, /* up-arrow key -> KEY_UP */ {(char *) 0, (char *) 0},};/* * This routine fills in string caps that either had defaults under * termcap or can be manufactured from obsolete termcap capabilities. * It was lifted from Ross Ridge's mytinfo package. */static const char C_CR[] = "\r";static const char C_LF[] = "\n";static const char C_BS[] = "\b";static const char C_HT[] = "\t";/* * Note that WANTED and PRESENT are not simple inverses! If a capability * has been explicitly cancelled, it's not considered WANTED. */#define WANTED(s) ((s) == ABSENT_STRING)#define PRESENT(s) (((s) != ABSENT_STRING) && ((s) != CANCELLED_STRING))/* * This bit of legerdemain turns all the terminfo variable names into * references to locations in the arrays Booleans, Numbers, and Strings --- * precisely what's needed. */#undef CUR#define CUR tp->static voidpostprocess_termcap(TERMTYPE *tp, bool has_base){ char buf[MAX_LINE * 2 + 2]; string_desc result; /* * TERMCAP DEFAULTS AND OBSOLETE-CAPABILITY TRANSLATIONS * * This first part of the code is the functional inverse of the * fragment in capdefaults.c. * ---------------------------------------------------------------------- */ /* if there was a tc entry, assume we picked up defaults via that */ if (!has_base) { if (WANTED(init_3string) && termcap_init2) init_3string = _nc_save_str(termcap_init2); if (WANTED(reset_2string) && termcap_reset) reset_2string = _nc_save_str(termcap_reset); if (WANTED(carriage_return)) { if (carriage_return_delay > 0) { sprintf(buf, "%s$<%d>", C_CR, carriage_return_delay); carriage_return = _nc_save_str(buf); } else carriage_return = _nc_save_str(C_CR); } if (WANTED(cursor_left)) { if (backspace_delay > 0) { sprintf(buf, "%s$<%d>", C_BS, backspace_delay); cursor_left = _nc_save_str(buf); } else if (backspaces_with_bs == 1) cursor_left = _nc_save_str(C_BS); else if (PRESENT(backspace_if_not_bs)) cursor_left = backspace_if_not_bs; } /* vi doesn't use "do", but it does seems to use nl (or '\n') instead */ if (WANTED(cursor_down)) { if (PRESENT(linefeed_if_not_lf)) cursor_down = linefeed_if_not_lf; else if (linefeed_is_newline != 1) { if (new_line_delay > 0) { sprintf(buf, "%s$<%d>", C_LF, new_line_delay); cursor_down = _nc_save_str(buf); } else cursor_down = _nc_save_str(C_LF); } } if (WANTED(scroll_forward) && crt_no_scrolling != 1) { if (PRESENT(linefeed_if_not_lf)) cursor_down = linefeed_if_not_lf; else if (linefeed_is_newline != 1) { if (new_line_delay > 0) { sprintf(buf, "%s$<%d>", C_LF, new_line_delay); scroll_forward = _nc_save_str(buf); } else scroll_forward = _nc_save_str(C_LF); } } if (WANTED(newline)) { if (linefeed_is_newline == 1) { if (new_line_delay > 0) { sprintf(buf, "%s$<%d>", C_LF, new_line_delay); newline = _nc_save_str(buf); } else newline = _nc_save_str(C_LF); } else if (PRESENT(carriage_return) && PRESENT(scroll_forward)) { _nc_str_init(&result, buf, sizeof(buf)); if (_nc_safe_strcat(&result, carriage_return) && _nc_safe_strcat(&result, scroll_forward)) newline = _nc_save_str(buf); } else if (PRESENT(carriage_return) && PRESENT(cursor_down)) { _nc_str_init(&result, buf, sizeof(buf)); if (_nc_safe_strcat(&result, carriage_return) && _nc_safe_strcat(&result, cursor_down)) newline = _nc_save_str(buf); } } } /* * Inverse of capdefaults.c code ends here. * ---------------------------------------------------------------------- * * TERMCAP-TO TERMINFO MAPPINGS FOR SOURCE TRANSLATION * * These translations will *not* be inverted by tgetent(). */ if (!has_base) { /* * We wait until now to decide if we've got a working cr because even * one that doesn't work can be used for newline. Unfortunately the * space allocated for it is wasted. */ if (return_does_clr_eol == 1 || no_correctly_working_cr == 1) carriage_return = ABSENT_STRING; /* * Supposedly most termcap entries have ta now and '\t' is no longer a * default, but it doesn't seem to be true... */ if (WANTED(tab)) { if (horizontal_tab_delay > 0) { sprintf(buf, "%s$<%d>", C_HT, horizontal_tab_delay); tab = _nc_save_str(buf); } else tab = _nc_save_str(C_HT); } if (init_tabs == ABSENT_NUMERIC && has_hardware_tabs == TRUE) init_tabs = 8; /* * Assume we can beep with ^G unless we're given bl@. */ if (WANTED(bell)) bell = _nc_save_str("\007"); } /* * Translate the old termcap :pt: capability to it#8 + ht=\t */ if (has_hardware_tabs == TRUE) { if (init_tabs != 8 && init_tabs != ABSENT_NUMERIC) _nc_warning("hardware tabs with a width other than 8: %d", init_tabs); else { if (tab && _nc_capcmp(tab, C_HT)) _nc_warning("hardware tabs with a non-^I tab string %s", _nc_visbuf(tab)); else { if (WANTED(tab)) tab = _nc_save_str(C_HT); init_tabs = 8; } } } /* * Now translate the ko capability, if there is one. This * isn't from mytinfo... */ if (PRESENT(other_non_function_keys)) { char *base = other_non_function_keys; char *bp, *cp, *dp; struct name_table_entry const *from_ptr; struct name_table_entry const *to_ptr; assoc const *ap; char buf2[MAX_TERMINFO_LENGTH]; bool foundim; /* we're going to use this for a special case later */ dp = strchr(other_non_function_keys, 'i'); foundim = (dp != 0) && (dp[1] == 'm'); /* look at each comma-separated capability in the ko string... */ for (base = other_non_function_keys; (cp = strchr(base, ',')) != 0; base = cp + 1) { size_t len = cp - base; for (ap = ko_xlate; ap->from; ap++) if (len == strlen(ap->from) && strncmp(ap->from, base, len) == 0) break; if (!ap->to) { _nc_warning("unknown capability `%.*s' in ko string", (int) len, base); continue; } else if (ap->to == CANCELLED_STRING) /* ignore it */ continue; /* now we know we found a match in ko_table, so... */ from_ptr = _nc_find_entry(ap->from, _nc_cap_hash_table); to_ptr = _nc_find_entry(ap->to, _nc_info_hash_table); if (!from_ptr || !to_ptr) /* should never happen! */ _nc_err_abort("ko translation table is invalid, I give up"); if (WANTED(tp->Strings[from_ptr->nte_index])) { _nc_warning("no value for ko capability %s", ap->from); continue; } if (tp->Strings[to_ptr->nte_index]) { /* There's no point in warning about it if it's the same * string; that's just an inefficiency. */ if (strcmp( tp->Strings[from_ptr->nte_index], tp->Strings[to_ptr->nte_index]) != 0) _nc_warning("%s (%s) already has an explicit value %s, ignoring ko", ap->to, ap->from, _nc_visbuf(tp->Strings[to_ptr->nte_index])); continue; } /* * The magic moment -- copy the mapped key string over, * stripping out padding. */ for (dp = buf2, bp = tp->Strings[from_ptr->nte_index]; *bp; bp++) { if (bp[0] == '$' && bp[1] == '<') { while (*bp && *bp != '>') { ++bp; } } else *dp++ = *bp; } *dp++ = '\0'; tp->Strings[to_ptr->nte_index] = _nc_save_str(buf2); } /* * Note: ko=im and ko=ic both want to grab the `Insert' * keycap. There's a kich1 but no ksmir, so the ic capability * got mapped to kich1 and im to kIC to avoid a collision. * If the description has im but not ic, hack kIC back to kich1. */ if (foundim && WANTED(key_ic) && key_sic) { key_ic = key_sic; key_sic = ABSENT_STRING; } } if (!has_base) { if (!hard_copy) { if (WANTED(key_backspace)) key_backspace = _nc_save_str(C_BS); if (WANTED(key_left)) key_left = _nc_save_str(C_BS); if (WANTED(key_down)) key_down = _nc_save_str(C_LF); } } /* * Translate XENIX forms characters. */ if (PRESENT(acs_ulcorner) || PRESENT(acs_llcorner) || PRESENT(acs_urcorner) || PRESENT(acs_lrcorner) || PRESENT(acs_ltee) || PRESENT(acs_rtee) || PRESENT(acs_btee) || PRESENT(acs_ttee) || PRESENT(acs_hline) || PRESENT(acs_vline) || PRESENT(acs_plus)) { char buf2[MAX_TERMCAP_LENGTH]; _nc_str_init(&result, buf2, sizeof(buf2)); _nc_safe_strcat(&result, acs_chars); append_acs(&result, 'j', acs_lrcorner); append_acs(&result, 'k', acs_urcorner); append_acs(&result, 'l', acs_ulcorner); append_acs(&result, 'm', acs_llcorner); append_acs(&result, 'n', acs_plus); append_acs(&result, 'q', acs_hline); append_acs(&result, 't', acs_ltee); append_acs(&result, 'u', acs_rtee); append_acs(&result, 'v', acs_btee); append_acs(&result, 'w', acs_ttee); append_acs(&result, 'x', acs_vline); if (buf2[0]) { acs_chars = _nc_save_str(buf2); _nc_warning("acsc string synthesized from XENIX capabilities"); } } else if (acs_chars == 0 && enter_alt_charset_mode != 0 && exit_alt_charset_mode != 0) { acs_chars = _nc_save_str(VT_ACSC); }}static voidpostprocess_terminfo(TERMTYPE *tp){ /* * TERMINFO-TO-TERMINFO MAPPINGS FOR SOURCE TRANSLATION * ---------------------------------------------------------------------- */ /* * Translate AIX forms characters. */ if (PRESENT(box_chars_1)) { char buf2[MAX_TERMCAP_LENGTH]; string_desc result; _nc_str_init(&result, buf2, sizeof(buf2)); _nc_safe_strcat(&result, acs_chars); append_acs0(&result, 'l', box_chars_1[0]); /* ACS_ULCORNER */ append_acs0(&result, 'q', box_chars_1[1]); /* ACS_HLINE */ append_acs0(&result, 'k', box_chars_1[2]); /* ACS_URCORNER */ append_acs0(&result, 'x', box_chars_1[3]); /* ACS_VLINE */ append_acs0(&result, 'j', box_chars_1[4]); /* ACS_LRCORNER */ append_acs0(&result, 'm', box_chars_1[5]); /* ACS_LLCORNER */ append_acs0(&result, 'w', box_chars_1[6]); /* ACS_TTEE */ append_acs0(&result, 'u', box_chars_1[7]); /* ACS_RTEE */ append_acs0(&result, 'v', box_chars_1[8]); /* ACS_BTEE */ append_acs0(&result, 't', box_chars_1[9]); /* ACS_LTEE */ append_acs0(&result, 'n', box_chars_1[10]); /* ACS_PLUS */ if (buf2[0]) { acs_chars = _nc_save_str(buf2); _nc_warning("acsc string synthesized from AIX capabilities"); box_chars_1 = ABSENT_STRING; } } /* * ---------------------------------------------------------------------- */}/* * Do a linear search through the terminfo tables to find a given full-name. * We don't expect to do this often, so there's no hashing function. * * In effect, this scans through the 3 lists of full-names, and looks them * up in _nc_info_table, which is organized so that the nte_index fields are * sorted, but the nte_type fields are not necessarily grouped together. */static struct name_table_entry const *lookup_fullname(const char *find){ int state = -1; for (;;) { int count = 0; NCURSES_CONST char *const *names; switch (++state) { case BOOLEAN: names = boolfnames; break; case STRING: names = strfnames; break; case NUMBER: names = numfnames; break; default: return NOTFOUND; } for (count = 0; names[count] != 0; count++) { if (!strcmp(names[count], find)) { struct name_table_entry const *entry_ptr = _nc_get_table(FALSE); while (entry_ptr->nte_type != state || entry_ptr->nte_index != count) entry_ptr++; return entry_ptr; } } }}/* parse_entry.c ends here */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -