int ti_getnum(const TERMINAL *term, const char *id) { ssize_t ind; size_t i; TERMUSERDEF *ud; _DIAGASSERT(term != NULL); _DIAGASSERT(id != NULL); ind = _ti_numindex(id); if (ind != -1) { if (!VALID_NUMERIC(term->nums[ind])) return ABSENT_NUMERIC; return term->nums[ind]; } for (i = 0; i < term->_nuserdefs; i++) { ud = &term->_userdefs[i]; if (ud->type == 'n' && strcmp(ud->id, id) == 0) { if (!VALID_NUMERIC(ud->num)) return ABSENT_NUMERIC; return ud->num; } } return CANCELLED_NUMERIC; }
int tgetnum(const char *id2) { uint32_t ind; size_t i; TERMUSERDEF *ud; const TENTRY *te; const char id[] = { id2[0], id2[0] ? id2[1] : '\0', '\0' }; if (cur_term == NULL) return -1; ind = _t_numhash((const unsigned char *)id, strlen(id)); if (ind <= __arraycount(_ti_cap_numids)) { te = &_ti_cap_numids[ind]; if (strcmp(id, te->id) == 0) { if (!VALID_NUMERIC(cur_term->nums[te->ti])) return ABSENT_NUMERIC; return cur_term->nums[te->ti]; } } for (i = 0; i < cur_term->_nuserdefs; i++) { ud = &cur_term->_userdefs[i]; if (ud->type == 'n' && strcmp(ud->id, id) == 0) { if (!VALID_NUMERIC(ud->num)) return ABSENT_NUMERIC; return ud->num; } } return -1; }
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(has_colors) (NCURSES_SP_DCL0) { int code; (void) SP_PARM; T((T_CALLED("has_colors()"))); #ifdef USE_TERM_DRIVER code = HasColor; #else code = ((VALID_NUMERIC(max_colors) && VALID_NUMERIC(max_pairs) && (((set_foreground != NULL) && (set_background != NULL)) || ((set_a_foreground != NULL) && (set_a_background != NULL)) || set_color_pair)) ? TRUE : FALSE); #endif returnCode(code); }
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); }
/* * Set the hardware tabs on the terminal, using the 'ct' (clear all tabs), * 'st' (set one tab) and 'ch' (horizontal cursor addressing) capabilities. * This is done before 'if' and 'is', so they can recover in case of error. * * Return TRUE if we set any tab stops, FALSE if not. */ static bool reset_tabstops(int wide) { if ((init_tabs != 8) && VALID_NUMERIC(init_tabs) && VALID_STRING(set_tab) && VALID_STRING(clear_all_tabs)) { int c; to_left_margin(); tputs(clear_all_tabs, 0, out_char); if (init_tabs > 1) { if (init_tabs > wide) init_tabs = (short) wide; for (c = init_tabs; c < wide; c += init_tabs) { fprintf(my_file, "%*s", init_tabs, " "); tputs(set_tab, 0, out_char); } to_left_margin(); } return (TRUE); } return (FALSE); }
TIC * _ti_compile(char *cap, int flags) { char *token, *p, *e, *name, *desc, *alias; signed char flag; long cnum; short num; ssize_t ind; size_t len; TBUF buf; TIC *tic; _DIAGASSERT(cap != NULL); name = _ti_get_token(&cap, ','); if (name == NULL) { dowarn(flags, "no seperator found: %s", cap); return NULL; } desc = strrchr(name, '|'); if (desc != NULL) *desc++ = '\0'; alias = strchr(name, '|'); if (alias != NULL) *alias++ = '\0'; tic = calloc(sizeof(*tic), 1); if (tic == NULL) return NULL; buf.buf = NULL; buf.buflen = 0; tic->name = strdup(name); if (tic->name == NULL) goto error; if (alias != NULL && flags & TIC_ALIAS) { tic->alias = strdup(alias); if (tic->alias == NULL) goto error; } if (desc != NULL && flags & TIC_DESCRIPTION) { tic->desc = strdup(desc); if (tic->desc == NULL) goto error; } for (token = _ti_get_token(&cap, ','); token != NULL && *token != '\0'; token = _ti_get_token(&cap, ',')) { /* Skip commented caps */ if (!(flags & TIC_COMMENT) && token[0] == '.') continue; /* Obsolete entries */ if (token[0] == 'O' && token[1] == 'T') { if (!(flags & TIC_EXTRA)) continue; token += 2; } /* str cap */ p = strchr(token, '='); if (p != NULL) { *p++ = '\0'; /* Don't use the string if we already have it */ ind = _ti_strindex(token); if (ind != -1 && _ti_find_cap(&tic->strs, 's', ind) != NULL) continue; /* Encode the string to our scratch buffer */ buf.bufpos = 0; if (encode_string(tic->name, token, &buf, p, flags) == -1) goto error; if (buf.bufpos > UINT16_T_MAX) { dowarn(flags, "%s: %s: string is too long", tic->name, token); continue; } if (!VALID_STRING(buf.buf)) { dowarn(flags, "%s: %s: invalid string", tic->name, token); continue; } if (ind == -1) _ti_store_extra(tic, 1, token, 's', -1, -2, buf.buf, buf.bufpos, flags); else { if (!_ti_grow_tbuf(&tic->strs, (sizeof(uint16_t) * 2) + buf.bufpos)) goto error; le16enc(tic->strs.buf + tic->strs.bufpos, ind); tic->strs.bufpos += sizeof(uint16_t); le16enc(tic->strs.buf + tic->strs.bufpos, buf.bufpos); tic->strs.bufpos += sizeof(uint16_t); memcpy(tic->strs.buf + tic->strs.bufpos, buf.buf, buf.bufpos); tic->strs.bufpos += buf.bufpos; tic->strs.entries++; } continue; } /* num cap */ p = strchr(token, '#'); if (p != NULL) { *p++ = '\0'; /* Don't use the number if we already have it */ ind = _ti_numindex(token); if (ind != -1 && _ti_find_cap(&tic->nums, 'n', ind) != NULL) continue; cnum = strtol(p, &e, 0); if (*e != '\0') { dowarn(flags, "%s: %s: not a number", tic->name, token); continue; } if (!VALID_NUMERIC(cnum)) { dowarn(flags, "%s: %s: number out of range", tic->name, token); continue; } num = (short)cnum; if (ind == -1) _ti_store_extra(tic, 1, token, 'n', -1, num, NULL, 0, flags); else { if (_ti_grow_tbuf(&tic->nums, sizeof(uint16_t) * 2) == NULL) goto error; le16enc(tic->nums.buf + tic->nums.bufpos, ind); tic->nums.bufpos += sizeof(uint16_t); le16enc(tic->nums.buf + tic->nums.bufpos, num); tic->nums.bufpos += sizeof(uint16_t); tic->nums.entries++; } continue; } flag = 1; len = strlen(token) - 1; if (token[len] == '@') { flag = CANCELLED_BOOLEAN; token[len] = '\0'; } ind = _ti_flagindex(token); if (ind == -1 && flag == CANCELLED_BOOLEAN) { if ((ind = _ti_numindex(token)) != -1) { if (_ti_find_cap(&tic->nums, 'n', ind) != NULL) continue; if (_ti_grow_tbuf(&tic->nums, sizeof(uint16_t) * 2) == NULL) goto error; le16enc(tic->nums.buf + tic->nums.bufpos, ind); tic->nums.bufpos += sizeof(uint16_t); le16enc(tic->nums.buf + tic->nums.bufpos, (uint16_t)CANCELLED_NUMERIC); tic->nums.bufpos += sizeof(uint16_t); tic->nums.entries++; continue; } else if ((ind = _ti_strindex(token)) != -1) { if (_ti_find_cap(&tic->strs, 's', ind) != NULL) continue; if (_ti_grow_tbuf(&tic->strs, (sizeof(uint16_t) * 2) + 1) == NULL) goto error; le16enc(tic->strs.buf + tic->strs.bufpos, ind); tic->strs.bufpos += sizeof(uint16_t); le16enc(tic->strs.buf + tic->strs.bufpos, 0); tic->strs.bufpos += sizeof(uint16_t); tic->strs.entries++; continue; } } if (ind == -1) _ti_store_extra(tic, 1, token, 'f', flag, 0, NULL, 0, flags); else if (_ti_find_cap(&tic->flags, 'f', ind) == NULL) { if (_ti_grow_tbuf(&tic->flags, sizeof(uint16_t) + 1) == NULL) goto error; le16enc(tic->flags.buf + tic->flags.bufpos, ind); tic->flags.bufpos += sizeof(uint16_t); tic->flags.buf[tic->flags.bufpos++] = flag; tic->flags.entries++; } } free(buf.buf); return tic; error: free(buf.buf); _ti_freetic(tic); return NULL; }
SCREEN * newterm(NCURSES_CONST char *name, FILE * ofp, FILE * ifp) { int errret; int slk_format = _nc_slk_format; SCREEN *current; #ifdef TRACE int t = _nc_getenv_num("NCURSES_TRACE"); if (t >= 0) trace(t); #endif T((T_CALLED("newterm(\"%s\",%p,%p)"), name, ofp, ifp)); /* this loads the capability entry, then sets LINES and COLS */ if (setupterm(name, fileno(ofp), &errret) == ERR) return 0; /* implement filter mode */ if (filter_mode) { LINES = 1; if (VALID_NUMERIC(init_tabs)) TABSIZE = init_tabs; else TABSIZE = 8; T(("TABSIZE = %d", TABSIZE)); clear_screen = 0; cursor_down = parm_down_cursor = 0; cursor_address = 0; cursor_up = parm_up_cursor = 0; row_address = 0; cursor_home = carriage_return; } /* If we must simulate soft labels, grab off the line to be used. We assume that we must simulate, if it is none of the standard formats (4-4 or 3-2-3) for which there may be some hardware support. */ if (num_labels <= 0 || !SLK_STDFMT(slk_format)) if (slk_format) { if (ERR == _nc_ripoffline(-SLK_LINES(slk_format), _nc_slk_initialize)) return 0; } /* this actually allocates the screen structure, and saves the * original terminal settings. */ current = SP; _nc_set_screen(0); if (_nc_setupscreen(LINES, COLS, ofp) == ERR) { _nc_set_screen(current); return 0; } /* if the terminal type has real soft labels, set those up */ if (slk_format && num_labels > 0 && SLK_STDFMT(slk_format)) _nc_slk_initialize(stdscr, COLS); SP->_ifd = fileno(ifp); SP->_checkfd = fileno(ifp); typeahead(fileno(ifp)); #ifdef TERMIOS SP->_use_meta = ((cur_term->Ottyb.c_cflag & CSIZE) == CS8 && !(cur_term->Ottyb.c_iflag & ISTRIP)); #else SP->_use_meta = FALSE; #endif SP->_endwin = FALSE; /* Check whether we can optimize scrolling under dumb terminals in case * we do not have any of these capabilities, scrolling optimization * will be useless. */ SP->_scrolling = ((scroll_forward && scroll_reverse) || ((parm_rindex || parm_insert_line || insert_line) && (parm_index || parm_delete_line || delete_line))); baudrate(); /* sets a field in the SP structure */ SP->_keytry = 0; /* * Check for mismatched graphic-rendition capabilities. Most SVr4 * terminfo trees contain entries that have rmul or rmso equated to * sgr0 (Solaris curses copes with those entries). We do this only for * curses, since many termcap applications assume that smso/rmso and * smul/rmul are paired, and will not function properly if we remove * rmso or rmul. Curses applications shouldn't be looking at this * detail. */ #define SGR0_TEST(mode) (mode != 0) && (exit_attribute_mode == 0 || strcmp(mode, exit_attribute_mode)) SP->_use_rmso = SGR0_TEST(exit_standout_mode); SP->_use_rmul = SGR0_TEST(exit_underline_mode); #if USE_WIDEC_SUPPORT /* * XFree86 xterm can be configured to support UTF-8 based on environment * variable settings. */ { char *s; s = getenv("LC_ALL"); if (s == NULL || *s == '\0') { s = getenv("LC_CTYPE"); if (s == NULL || *s == '\0') { s = getenv("LANG"); } } if (s != NULL && *s != '\0' && strstr(s, "UTF-8") != NULL) { SP->_outch = _nc_utf8_outch; } } #endif /* compute movement costs so we can do better move optimization */ _nc_mvcur_init(); /* initialize terminal to a sane state */ _nc_screen_init(); /* Initialize the terminal line settings. */ _nc_initscr(); _nc_signal_handler(TRUE); T((T_RETURN("%p"), SP)); return (SP); }
static int use_predicate(unsigned type, PredIdx idx) /* predicate function to use for use decompilation */ { ENTRY *ep; switch (type) { case BOOLEAN: { int is_set = FALSE; /* * This assumes that multiple use entries are supposed * to contribute the logical or of their boolean capabilities. * This is true if we take the semantics of multiple uses to * be 'each capability gets the first non-default value found * in the sequence of use entries'. * * Note that cancelled or absent booleans are stored as FALSE, * unlike numbers and strings, whose cancelled/absent state is * recorded in the terminfo database. */ for (ep = &entries[1]; ep < entries + termcount; ep++) if (ep->tterm.Booleans[idx] == TRUE) { is_set = entries[0].tterm.Booleans[idx]; break; } if (is_set != entries[0].tterm.Booleans[idx]) return (!is_set); else return (FAIL); } case NUMBER: { int value = ABSENT_NUMERIC; /* * We take the semantics of multiple uses to be 'each * capability gets the first non-default value found * in the sequence of use entries'. */ for (ep = &entries[1]; ep < entries + termcount; ep++) if (VALID_NUMERIC(ep->tterm.Numbers[idx])) { value = ep->tterm.Numbers[idx]; break; } if (value != entries[0].tterm.Numbers[idx]) return (value != ABSENT_NUMERIC); else return (FAIL); } case STRING: { char *termstr, *usestr = ABSENT_STRING; termstr = entries[0].tterm.Strings[idx]; /* * We take the semantics of multiple uses to be 'each * capability gets the first non-default value found * in the sequence of use entries'. */ for (ep = &entries[1]; ep < entries + termcount; ep++) if (ep->tterm.Strings[idx]) { usestr = ep->tterm.Strings[idx]; break; } if (usestr == ABSENT_STRING && termstr == ABSENT_STRING) return (FAIL); else if (!usestr || !termstr || capcmp(idx, usestr, termstr)) return (TRUE); else return (FAIL); } } return (FALSE); /* pacify compiler */ }
static void _nc_get_screensize(int *linep, int *colp) /* Obtain lines/columns values from the environment and/or terminfo entry */ { /* figure out the size of the screen */ T(("screen size: terminfo lines = %d columns = %d", lines, columns)); if (!_use_env) { *linep = (int) lines; *colp = (int) columns; } else { /* usually want to query LINES and COLUMNS from environment */ int value; *linep = *colp = 0; /* first, look for environment variables */ if ((value = _nc_getenv_num("LINES")) > 0) { *linep = value; } if ((value = _nc_getenv_num("COLUMNS")) > 0) { *colp = value; } T(("screen size: environment LINES = %d COLUMNS = %d", *linep, *colp)); #ifdef __EMX__ if (*linep <= 0 || *colp <= 0) { int screendata[2]; _scrsize(screendata); *colp = screendata[0]; *linep = screendata[1]; T(("EMX screen size: environment LINES = %d COLUMNS = %d", *linep, *colp)); } #endif #if HAVE_SIZECHANGE /* if that didn't work, maybe we can try asking the OS */ if (*linep <= 0 || *colp <= 0) { if (isatty(cur_term->Filedes)) { STRUCT_WINSIZE size; errno = 0; do { if (ioctl(cur_term->Filedes, IOCTL_WINSIZE, &size) < 0 && errno != EINTR) goto failure; } while (errno == EINTR); /* * Solaris lets users override either dimension with an * environment variable. */ if (*linep <= 0) *linep = WINSIZE_ROWS(size); if (*colp <= 0) *colp = WINSIZE_COLS(size); } /* FALLTHRU */ failure:; } #endif /* HAVE_SIZECHANGE */ /* if we can't get dynamic info about the size, use static */ if (*linep <= 0) { *linep = (int) lines; } if (*colp <= 0) { *colp = (int) columns; } /* the ultimate fallback, assume fixed 24x80 size */ if (*linep <= 0) { *linep = 24; } if (*colp <= 0) { *colp = 80; } /* * Put the derived values back in the screen-size caps, so * tigetnum() and tgetnum() will do the right thing. */ lines = (short) (*linep); columns = (short) (*colp); } T(("screen size is %dx%d", *linep, *colp)); if (VALID_NUMERIC(init_tabs)) TABSIZE = (int) init_tabs; else TABSIZE = 8; T(("TABSIZE = %d", TABSIZE)); }
static int _ti_readterm(TERMINAL *term, const char *cap, size_t caplen, int flags) { uint8_t ver; uint16_t ind, num; size_t len; TERMUSERDEF *ud; ver = *cap++; /* Only read version 1 structures */ if (ver != 1) { errno = EINVAL; return -1; } if (allocset(&term->flags, 0, TIFLAGMAX + 1, sizeof(*term->flags)) == -1) return -1; if (allocset(&term->nums, -1, TINUMMAX + 1, sizeof(*term->nums)) == -1) return -1; if (allocset(&term->strs, 0, TISTRMAX + 1, sizeof(*term->strs)) == -1) return -1; if (term->_arealen != caplen) { term->_arealen = caplen; term->_area = realloc(term->_area, term->_arealen); if (term->_area == NULL) return -1; } memcpy(term->_area, cap, term->_arealen); cap = term->_area; len = le16dec(cap); cap += sizeof(uint16_t); term->name = cap; cap += len; len = le16dec(cap); cap += sizeof(uint16_t); if (len == 0) term->_alias = NULL; else { term->_alias = cap; cap += len; } len = le16dec(cap); cap += sizeof(uint16_t); if (len == 0) term->desc = NULL; else { term->desc = cap; cap += len; } num = le16dec(cap); cap += sizeof(uint16_t); if (num != 0) { num = le16dec(cap); cap += sizeof(uint16_t); for (; num != 0; num--) { ind = le16dec(cap); cap += sizeof(uint16_t); term->flags[ind] = *cap++; if (flags == 0 && !VALID_BOOLEAN(term->flags[ind])) term->flags[ind] = 0; } } num = le16dec(cap); cap += sizeof(uint16_t); if (num != 0) { num = le16dec(cap); cap += sizeof(uint16_t); for (; num != 0; num--) { ind = le16dec(cap); cap += sizeof(uint16_t); term->nums[ind] = le16dec(cap); if (flags == 0 && !VALID_NUMERIC(term->nums[ind])) term->nums[ind] = ABSENT_NUMERIC; cap += sizeof(uint16_t); } } num = le16dec(cap); cap += sizeof(uint16_t); if (num != 0) { num = le16dec(cap); cap += sizeof(uint16_t); for (; num != 0; num--) { ind = le16dec(cap); cap += sizeof(uint16_t); len = le16dec(cap); cap += sizeof(uint16_t); if (len > 0) term->strs[ind] = cap; else if (flags == 0) term->strs[ind] = ABSENT_STRING; else term->strs[ind] = CANCELLED_STRING; cap += len; } } num = le16dec(cap); cap += sizeof(uint16_t); if (num != 0) { num = le16dec(cap); cap += sizeof(uint16_t); if (num != term->_nuserdefs) { free(term->_userdefs); term->_userdefs = NULL; term->_nuserdefs = num; } if (allocset(&term->_userdefs, 0, term->_nuserdefs, sizeof(*term->_userdefs)) == -1) return -1; for (num = 0; num < term->_nuserdefs; num++) { ud = &term->_userdefs[num]; len = le16dec(cap); cap += sizeof(uint16_t); ud->id = cap; cap += len; ud->type = *cap++; switch (ud->type) { case 'f': ud->flag = *cap++; if (flags == 0 && !VALID_BOOLEAN(ud->flag)) ud->flag = 0; ud->num = ABSENT_NUMERIC; ud->str = ABSENT_STRING; break; case 'n': ud->flag = ABSENT_BOOLEAN; ud->num = le16dec(cap); if (flags == 0 && !VALID_NUMERIC(ud->num)) ud->num = ABSENT_NUMERIC; ud->str = ABSENT_STRING; cap += sizeof(uint16_t); break; case 's': ud->flag = ABSENT_BOOLEAN; ud->num = ABSENT_NUMERIC; len = le16dec(cap); cap += sizeof(uint16_t); if (len > 0) ud->str = cap; else if (flags == 0) ud->str = ABSENT_STRING; else ud->str = CANCELLED_STRING; cap += len; break; default: errno = EINVAL; return -1; } } } else { term->_nuserdefs = 0; if (term->_userdefs) { free(term->_userdefs); term->_userdefs = NULL; } } return 1; }