NCURSES_SP_NAME(tgetflag) (NCURSES_SP_DCLx NCURSES_CONST char *id) { int result = 0; /* Solaris returns zero for missing flag */ T((T_CALLED("tgetflag(%p, %s)"), (void *) SP_PARM, id)); if (HasTInfoTerminal(SP_PARM) && ValidCap(id)) { TERMTYPE2 *tp = &TerminalType(TerminalOf(SP_PARM)); struct name_table_entry const *entry_ptr; int j = -1; entry_ptr = _nc_find_type_entry(id, BOOLEAN, TRUE); if (entry_ptr != 0) { j = entry_ptr->nte_index; } #if NCURSES_XNAMES else { int i; for_each_ext_boolean(i, tp) { const char *capname = ExtBoolname(tp, i, boolcodes); if (same_tcname(id, capname) && ValidExt(capname)) { j = i; break; } } } #endif if (j >= 0) { /* note: setupterm forces invalid booleans to false */ result = tp->Booleans[j]; } }
NCURSES_SP_NAME(tigetflag) (NCURSES_SP_DCLx NCURSES_CONST char *str) { int result = ABSENT_BOOLEAN; int j = -1; T((T_CALLED("tigetflag(%p, %s)"), (void *) SP_PARM, str)); if (HasTInfoTerminal(SP_PARM)) { TERMTYPE *tp = &(TerminalOf(SP_PARM)->type); struct name_table_entry const *entry_ptr; entry_ptr = _nc_find_type_entry(str, BOOLEAN, FALSE); if (entry_ptr != 0) { j = entry_ptr->nte_index; } #if NCURSES_XNAMES else { int i; for_each_ext_boolean(i, tp) { const char *capname = ExtBoolname(tp, i, boolnames); if (same_name(str, capname)) { j = i; break; } } } #endif if (j >= 0) { /* note: setupterm forces invalid booleans to false */ result = tp->Booleans[j]; } } returnCode(result); }
NCURSES_SP_NAME(tigetstr) (NCURSES_SP_DCLx NCURSES_CONST char *str) { char *result = CANCELLED_STRING; int j = -1; T((T_CALLED("tigetstr(%p, %s)"), (void *) SP_PARM, str)); if (HasTInfoTerminal(SP_PARM)) { TERMTYPE *tp = &(TerminalOf(SP_PARM)->type); struct name_table_entry const *entry_ptr; entry_ptr = _nc_find_type_entry(str, STRING, FALSE); if (entry_ptr != 0) { j = entry_ptr->nte_index; } #if NCURSES_XNAMES else { int i; for_each_ext_string(i, tp) { const char *capname = ExtStrname(tp, i, strnames); if (same_name(str, capname)) { j = i; break; } } } #endif if (j >= 0) { /* note: setupterm forces cancelled strings to null */ result = tp->Strings[j]; } } returnPtr(result); }
NCURSES_SP_NAME(tgetnum) (NCURSES_SP_DCLx NCURSES_CONST char *id) { int result = ABSENT_NUMERIC; int i, j; T((T_CALLED("tgetnum(%p, %s)"), (void *) SP_PARM, id)); if (HasTInfoTerminal(SP_PARM)) { TERMTYPE *tp = &(TerminalOf(SP_PARM)->type); struct name_table_entry const *entry_ptr; entry_ptr = _nc_find_type_entry(id, NUMBER, TRUE); if (entry_ptr != 0) { j = entry_ptr->nte_index; } #if NCURSES_XNAMES else { j = -1; for_each_ext_number(i, tp) { const char *capname = ExtNumname(tp, i, numcodes); if (same_tcname(id, capname)) { j = i; break; } } } #endif if (j >= 0) { if (VALID_NUMERIC(tp->Numbers[j])) result = tp->Numbers[j]; } } returnCode(result); }
NCURSES_SP_NAME(tgetstr) (NCURSES_SP_DCLx NCURSES_CONST char *id, char **area) { char *result = NULL; int i, j; T((T_CALLED("tgetstr(%s,%p)"), id, (void *) area)); if (HasTInfoTerminal(SP_PARM)) { TERMTYPE *tp = &(TerminalOf(SP_PARM)->type); struct name_table_entry const *entry_ptr; entry_ptr = _nc_find_type_entry(id, STRING, TRUE); if (entry_ptr != 0) { j = entry_ptr->nte_index; } #if NCURSES_XNAMES else { j = -1; for_each_ext_string(i, tp) { const char *capname = ExtStrname(tp, i, strcodes); if (same_tcname(id, capname)) { j = i; break; } } } #endif if (j >= 0) { result = tp->Strings[j]; TR(TRACE_DATABASE, ("found match : %s", _nc_visbuf(result))); /* setupterm forces canceled strings to null */ if (VALID_STRING(result)) { if (result == exit_attribute_mode && FIX_SGR0 != 0) { result = FIX_SGR0; TR(TRACE_DATABASE, ("altered to : %s", _nc_visbuf(result))); } if (area != 0 && *area != 0) { (void) strcpy(*area, result); result = *area; *area += strlen(*area) + 1; } } } } returnPtr(result); }
NCURSES_SP_NAME(tigetnum) (NCURSES_SP_DCLx NCURSES_CONST char *str) { int j = -1; int result = CANCELLED_NUMERIC; /* Solaris returns a -1 on error */ T((T_CALLED("tigetnum(%p, %s)"), (void *) SP_PARM, str)); if (HasTInfoTerminal(SP_PARM)) { TERMTYPE *tp = &(TerminalOf(SP_PARM)->type); struct name_table_entry const *entry_ptr; entry_ptr = _nc_find_type_entry(str, NUMBER, FALSE); if (entry_ptr != 0) { j = entry_ptr->nte_index; } #if NCURSES_XNAMES else { int i; for_each_ext_number(i, tp) { const char *capname = ExtNumname(tp, i, numnames); if (same_name(str, capname)) { j = i; break; } } } #endif if (j >= 0) { if (VALID_NUMERIC(tp->Numbers[j])) result = tp->Numbers[j]; else result = ABSENT_NUMERIC; } } returnCode(result); }
int _nc_parse_entry(struct entry *entryp, int literal, bool silent) { int token_type; struct name_table_entry const *entry_ptr; char *ptr, *base; token_type = _nc_get_token(); if (token_type == EOF) return (EOF); if (token_type != NAMES) _nc_err_abort("Entry does not start with terminal names in column one"); _nc_init_entry(&entryp->tterm); entryp->cstart = _nc_comment_start; entryp->cend = _nc_comment_end; entryp->startline = _nc_start_line; DEBUG(2, ("Comment range is %ld to %ld", entryp->cstart, entryp->cend)); /* junk the 2-character termcap name, if present */ ptr = _nc_curr_token.tk_name; if (ptr[2] == '|') { ptr = _nc_curr_token.tk_name + 3; _nc_curr_token.tk_name[2] = '\0'; } entryp->tterm.str_table = entryp->tterm.term_names = _nc_save_str(ptr); DEBUG(1, ("Starting '%s'", ptr)); /* * We do this because the one-token lookahead in the parse loop * results in the terminal type getting prematurely set to correspond * to that of the next entry. */ _nc_set_type(_nc_first_name(entryp->tterm.term_names)); /* check for overly-long names and aliases */ for (base = entryp->tterm.term_names; (ptr = strchr(base, '|')) != 0; base = ptr + 1) { if (ptr - base > MAX_ALIAS) { _nc_warning("%s `%.*s' may be too long", (base == entryp->tterm.term_names) ? "primary name" : "alias", ptr - base, base); } } entryp->nuses = 0; for (token_type = _nc_get_token(); token_type != EOF && token_type != NAMES; token_type = _nc_get_token()) { if (strcmp(_nc_curr_token.tk_name, "use") == 0 || strcmp(_nc_curr_token.tk_name, "tc") == 0) { entryp->uses[entryp->nuses].name = _nc_save_str(_nc_curr_token.tk_valstring); entryp->uses[entryp->nuses].line = _nc_curr_line; entryp->nuses++; } else { /* normal token lookup */ entry_ptr = _nc_find_entry(_nc_curr_token.tk_name, _nc_syntax ? _nc_cap_hash_table : _nc_info_hash_table); /* * Our kluge to handle aliasing. The reason it's done * this ugly way, with a linear search, is so the hashing * machinery doesn't have to be made really complicated * (also we get better warnings this way). No point in * making this case fast, aliased caps aren't common now * and will get rarer. */ if (entry_ptr == NOTFOUND) { const struct alias *ap; if (_nc_syntax == SYN_TERMCAP) { for (ap = _nc_capalias_table; ap->from; ap++) if (strcmp(ap->from, _nc_curr_token.tk_name) == 0) { if (ap->to == (char *) 0) { _nc_warning("%s (%s termcap extension) ignored", ap->from, ap->source); goto nexttok; } entry_ptr = _nc_find_entry(ap->to, _nc_cap_hash_table); if (entry_ptr && !silent) _nc_warning("%s (%s termcap extension) aliased to %s", ap->from, ap->source, ap->to); break; } } else { /* if (_nc_syntax == SYN_TERMINFO) */ for (ap = _nc_infoalias_table; ap->from; ap++) if (strcmp(ap->from, _nc_curr_token.tk_name) == 0) { if (ap->to == (char *) 0) { _nc_warning("%s (%s terminfo extension) ignored", ap->from, ap->source); goto nexttok; } entry_ptr = _nc_find_entry(ap->to, _nc_info_hash_table); if (entry_ptr && !silent) _nc_warning("%s (%s terminfo extension) aliased to %s", ap->from, ap->source, ap->to); break; } if (entry_ptr == NOTFOUND) { entry_ptr = lookup_fullname(_nc_curr_token.tk_name); } } } #if NCURSES_XNAMES /* * If we have extended-names active, we will automatically * define a name based on its context. */ if (entry_ptr == NOTFOUND && _nc_user_definable && (entry_ptr = _nc_extend_names(entryp, _nc_curr_token.tk_name, token_type)) != 0) { if (_nc_tracing >= DEBUG_LEVEL(1)) _nc_warning("extended capability '%s'", _nc_curr_token.tk_name); } #endif /* NCURSES_XNAMES */ /* can't find this cap name, not even as an alias */ if (entry_ptr == NOTFOUND) { if (!silent) _nc_warning("unknown capability '%s'", _nc_curr_token.tk_name); continue; } /* deal with bad type/value combinations. */ if (token_type != CANCEL && entry_ptr->nte_type != token_type) { /* * Nasty special cases here handle situations in which type * information can resolve name clashes. Normal lookup * finds the last instance in the capability table of a * given name, regardless of type. find_type_entry looks * for a first matching instance with given type. So as * long as all ambiguous names occur in pairs of distinct * type, this will do the job. */ /* tell max_attributes from arrow_key_map */ if (token_type == NUMBER && !strcmp("ma", _nc_curr_token.tk_name)) entry_ptr = _nc_find_type_entry("ma", NUMBER, _nc_get_table(_nc_syntax != 0)); /* map terminfo's string MT to MT */ else if (token_type == STRING && !strcmp("MT", _nc_curr_token.tk_name)) entry_ptr = _nc_find_type_entry("MT", STRING, _nc_get_table(_nc_syntax != 0)); /* treat strings without following "=" as empty strings */ else if (token_type == BOOLEAN && entry_ptr->nte_type == STRING) token_type = STRING; /* we couldn't recover; skip this token */ else { if (!silent) { const char *type_name; switch (entry_ptr->nte_type) { case BOOLEAN: type_name = "boolean"; break; case STRING: type_name = "string"; break; case NUMBER: type_name = "numeric"; break; default: type_name = "unknown"; break; } _nc_warning("wrong type used for %s capability '%s'", type_name, _nc_curr_token.tk_name); } continue; } } /* now we know that the type/value combination is OK */ switch (token_type) { case CANCEL: switch (entry_ptr->nte_type) { case BOOLEAN: entryp->tterm.Booleans[entry_ptr->nte_index] = CANCELLED_BOOLEAN; break; case NUMBER: entryp->tterm.Numbers[entry_ptr->nte_index] = CANCELLED_NUMERIC; break; case STRING: entryp->tterm.Strings[entry_ptr->nte_index] = CANCELLED_STRING; break; } break; case BOOLEAN: entryp->tterm.Booleans[entry_ptr->nte_index] = TRUE; break; case NUMBER: entryp->tterm.Numbers[entry_ptr->nte_index] = _nc_curr_token.tk_valnumber; break; case STRING: ptr = _nc_curr_token.tk_valstring; if (_nc_syntax == SYN_TERMCAP) ptr = _nc_captoinfo(_nc_curr_token.tk_name, ptr, parametrized[entry_ptr->nte_index]); entryp->tterm.Strings[entry_ptr->nte_index] = _nc_save_str(ptr); break; default: if (!silent) _nc_warning("unknown token type"); _nc_panic_mode((_nc_syntax == SYN_TERMCAP) ? ':' : ','); continue; } } /* end else cur_token.name != "use" */ nexttok: continue; /* cannot have a label w/o statement */ } /* endwhile (not EOF and not NAMES) */ _nc_push_token(token_type); _nc_set_type(_nc_first_name(entryp->tterm.term_names)); /* * Try to deduce as much as possible from extension capabilities * (this includes obsolete BSD capabilities). Sigh...it would be more * space-efficient to call this after use resolution, but it has * to be done before entry allocation is wrapped up. */ if (!literal) { if (_nc_syntax == SYN_TERMCAP) { bool has_base_entry = FALSE; int i; /* * Don't insert defaults if this is a `+' entry meant only * for inclusion in other entries (not sure termcap ever * had these, actually). */ if (strchr(entryp->tterm.term_names, '+')) has_base_entry = TRUE; else /* * Otherwise, look for a base entry that will already * have picked up defaults via translation. */ for (i = 0; i < entryp->nuses; i++) if (!strchr((char *) entryp->uses[i].name, '+')) has_base_entry = TRUE; postprocess_termcap(&entryp->tterm, has_base_entry); } else postprocess_terminfo(&entryp->tterm); } _nc_wrap_entry(entryp); return (OK); }