vwprintw(WINDOW *win, const char *fmt, va_list argp) { char *buf; int code = ERR; #if NCURSES_SP_FUNCS SCREEN *sp = _nc_screen_of(win); #endif T((T_CALLED("vwprintw(%p,%s,va_list)"), (void *) win, _nc_visbuf(fmt))); buf = NCURSES_SP_NAME(_nc_printf_string) (NCURSES_SP_ARGx fmt, argp); if (buf != 0) { code = waddstr(win, buf); } returnCode(code); }
int scr_restore(const char *file) { FILE *fp; T((T_CALLED("scr_restore(%s)"), _nc_visbuf(file))); if ((fp = fopen(file, "rb")) == 0) returnCode(ERR); else { delwin(newscr); newscr = getwin(fp); (void) fclose(fp); returnCode(OK); } }
int scr_dump(const char *file) { FILE *fp; T((T_CALLED("scr_dump(%s)"), _nc_visbuf(file))); if ((fp = fopen(file, "wb")) == 0) returnCode(ERR); else { (void) putwin(newscr, fp); (void) fclose(fp); dumptime = time((time_t *)0); returnCode(OK); } }
scr_restore(const char *file) { FILE *fp = 0; T((T_CALLED("scr_restore(%s)"), _nc_visbuf(file))); if (_nc_access(file, R_OK) < 0 || (fp = fopen(file, "rb")) == 0) { returnCode(ERR); } else { delwin(newscr); SP->_newscr = newscr = getwin(fp); (void) fclose(fp); returnCode(OK); } }
set_menu_pattern(MENU * menu, const char *p) { ITEM *matchitem; int matchpos; T((T_CALLED("set_menu_pattern(%p,%s)"), menu, _nc_visbuf(p))); if (!menu || !p) RETURN(E_BAD_ARGUMENT); if (!(menu->items)) RETURN(E_NOT_CONNECTED); if (menu->status & _IN_DRIVER) RETURN(E_BAD_STATE); Reset_Pattern(menu); if (!(*p)) { pos_menu_cursor(menu); RETURN(E_OK); } if (menu->status & _LINK_NEEDED) _nc_Link_Items(menu); matchpos = menu->toprow; matchitem = menu->curitem; assert(matchitem); while (*p) { if (!isprint(UChar(*p)) || (_nc_Match_Next_Character_In_Item_Name(menu, *p, &matchitem) != E_OK)) { Reset_Pattern(menu); pos_menu_cursor(menu); RETURN(E_NO_MATCH); } p++; } /* This is reached if there was a match. So we position to the new item */ Adjust_Current_Item(menu, matchpos, matchitem); RETURN(E_OK); }
scr_dump(const char *file) { int result; FILE *fp = 0; T((T_CALLED("scr_dump(%s)"), _nc_visbuf(file))); if (_nc_access(file, W_OK) < 0 || (fp = fopen(file, "wb")) == 0) { result = ERR; } else { (void) putwin(newscr, fp); (void) fclose(fp); result = OK; } returnCode(result); }
static void recur_tries(struct tries *tree, unsigned level) { if (level > len) buffer = (unsigned char *)realloc(buffer, len = (level + 1) * 4); while (tree != 0) { if ((buffer[level] = tree->ch) == 0) buffer[level] = 128; buffer[level+1] = 0; if (tree->value != 0) { _tracef("%5d: %s (%s)", tree->value, _nc_visbuf((char *)buffer), keyname(tree->value)); } if (tree->child) recur_tries(tree->child, level+1); tree = tree->sibling; } }
wprintw(WINDOW *win, const char *fmt,...) { va_list argp; int code; #ifdef TRACE va_start(argp, fmt); T((T_CALLED("wprintw(%p,%s%s)"), win, _nc_visbuf(fmt), _nc_varargs(fmt, argp))); va_end(argp); #endif va_start(argp, fmt); code = vwprintw(win, fmt, argp); va_end(argp); returnCode(code); }
NCURSES_SP_NAME(scr_set) (NCURSES_SP_DCLx const char *file) { int code = ERR; T((T_CALLED("scr_set(%p,%s)"), (void *) SP_PARM, _nc_visbuf(file))); if (NCURSES_SP_NAME(scr_init) (NCURSES_SP_ARGx file) == OK) { delwin(NewScreen(SP_PARM)); NewScreen(SP_PARM) = dupwin(curscr); #if !USE_REENTRANT newscr = NewScreen(SP_PARM); #endif if (NewScreen(SP_PARM) != 0) { code = OK; } } returnCode(code); }
int define_key(char *str, int keycode) { int code = ERR; T((T_CALLED("define_key(%s,%d)"), _nc_visbuf(str), keycode)); if (keycode > 0) { if (has_key(keycode)) { if (_nc_remove_key(&(SP->_keytry), keycode)) code = OK; } if (str != 0) { (void) _nc_add_to_try(&(SP->_keytry), str, keycode); code = OK; } } returnCode(code); }
mvprintw(int y, int x, const char *fmt,...) { va_list argp; int code; #ifdef TRACE va_start(argp, fmt); T((T_CALLED("mvprintw(%d,%d,%s%s)"), y, x, _nc_visbuf(fmt), _nc_varargs(fmt, argp))); va_end(argp); #endif if ((code = move(y, x)) != ERR) { va_start(argp, fmt); code = vwprintw(stdscr, fmt, argp); va_end(argp); } returnCode(code); }
static int compute_offsets(char **Strings, unsigned strmax, short *offsets) { size_t nextfree = 0; unsigned i; for (i = 0; i < strmax; i++) { if (Strings[i] == ABSENT_STRING) { offsets[i] = -1; } else if (Strings[i] == CANCELLED_STRING) { offsets[i] = -2; } else { offsets[i] = nextfree; nextfree += strlen(Strings[i]) + 1; TRACE_OUT(("put Strings[%d]=%s(%d)", i, _nc_visbuf(Strings[i]), nextfree)); } } return nextfree; }
mvwprintw(WINDOW *win, int y, int x, const char *fmt,...) { va_list argp; int code; #ifdef TRACE va_start(argp, fmt); T((T_CALLED("mvwprintw(%d,%d,%p,%s%s)"), y, x, (void *) win, _nc_visbuf(fmt), _nc_varargs(fmt, argp))); va_end(argp); #endif if ((code = wmove(win, y, x)) != ERR) { va_start(argp, fmt); code = vwprintw(win, fmt, argp); va_end(argp); } returnCode(code); }
scr_init(const char *file) { FILE *fp = 0; T((T_CALLED("scr_init(%s)"), _nc_visbuf(file))); if (exit_ca_mode && non_rev_rmcup) returnCode(ERR); if (_nc_access(file, R_OK) < 0 || (fp = fopen(file, "rb")) == 0) { returnCode(ERR); } else { delwin(curscr); SP->_curscr = curscr = getwin(fp); (void) fclose(fp); returnCode(OK); } }
NCURSES_SP_NAME(scr_restore) (NCURSES_SP_DCLx const char *file) { FILE *fp = 0; T((T_CALLED("scr_restore(%s)"), _nc_visbuf(file))); if (_nc_access(file, R_OK) < 0 || (fp = fopen(file, "rb")) == 0) { returnCode(ERR); } else { delwin(newscr); SP_PARM->_newscr = getwin(fp); #if !USE_REENTRANT newscr = SP_PARM->_newscr; #endif (void) fclose(fp); returnCode(OK); } }
static int compute_offsets(char **Strings, size_t strmax, short *offsets) { int nextfree = 0; size_t i; for (i = 0; i < strmax; i++) { if (Strings[i] == ABSENT_STRING) { offsets[i] = -1; } else if (Strings[i] == CANCELLED_STRING) { offsets[i] = -2; } else { offsets[i] = (short) nextfree; nextfree += (int) strlen(Strings[i]) + 1; TRACE_OUT(("put Strings[%d]=%s(%d)", (int) i, _nc_visbuf(Strings[i]), (int) nextfree)); } } return nextfree; }
NCURSES_SP_NAME(scr_restore) (NCURSES_SP_DCLx const char *file) { FILE *fp = 0; int code = ERR; T((T_CALLED("scr_restore(%p,%s)"), (void *) SP_PARM, _nc_visbuf(file))); if (_nc_access(file, R_OK) >= 0 && (fp = fopen(file, "rb")) != 0) { delwin(NewScreen(SP_PARM)); NewScreen(SP_PARM) = getwin(fp); #if !USE_REENTRANT newscr = NewScreen(SP_PARM); #endif (void) fclose(fp); if (NewScreen(SP_PARM) != 0) { code = OK; } } returnCode(code); }
NCURSES_SP_NAME(scr_init) (NCURSES_SP_DCLx const char *file) { FILE *fp = 0; T((T_CALLED("scr_init(%s)"), _nc_visbuf(file))); if (exit_ca_mode && non_rev_rmcup) returnCode(ERR); if (_nc_access(file, R_OK) < 0 || (fp = fopen(file, "rb")) == 0) { returnCode(ERR); } else { delwin(curscr); SP_PARM->_curscr = getwin(fp); #if !USE_REENTRANT curscr = SP_PARM->_curscr; #endif (void) fclose(fp); returnCode(OK); } }
NCURSES_SP_NAME(define_key) (NCURSES_SP_DCLx const char *str, int keycode) { int code = ERR; T((T_CALLED("define_key(%p, %s,%d)"), (void *) SP_PARM, _nc_visbuf(str), keycode)); if (SP_PARM == 0 || !HasTInfoTerminal(SP_PARM)) { code = ERR; } else if (keycode > 0) { unsigned ukey = (unsigned) keycode; #ifdef USE_TERM_DRIVER #define CallHasKey(keycode) CallDriver_1(SP_PARM, td_kyExist, keycode) #else #define CallHasKey(keycode) NCURSES_SP_NAME(has_key)(NCURSES_SP_ARGx keycode) #endif if (str != 0) { NCURSES_SP_NAME(define_key) (NCURSES_SP_ARGx str, 0); } else if (CallHasKey(keycode)) { while (_nc_remove_key(&(SP_PARM->_keytry), ukey)) code = OK; } if (str != 0) { if (NCURSES_SP_NAME(key_defined) (NCURSES_SP_ARGx str) == 0) { if (_nc_add_to_try(&(SP_PARM->_keytry), str, ukey) == OK) { code = OK; } else { code = ERR; } } else { code = ERR; } } } else { while (_nc_remove_string(&(SP_PARM->_keytry), str)) code = OK; } returnCode(code); }
scr_init(const char *file) { FILE *fp = 0; struct stat stb; T((T_CALLED("scr_init(%s)"), _nc_visbuf(file))); if (exit_ca_mode && non_rev_rmcup) returnCode(ERR); if (_nc_access(file, R_OK) < 0 || (fp = fopen(file, "rb")) == 0) returnCode(ERR); else if (fstat(STDOUT_FILENO, &stb) || stb.st_mtime > dumptime) returnCode(ERR); else { delwin(curscr); curscr = getwin(fp); (void) fclose(fp); returnCode(OK); } }
_nc_retrace_ptr(char *code) { T((T_RETURN("%s"), _nc_visbuf(code))); return code; }
_nc_trim_sgr0(TERMTYPE *tp) { char *result = exit_attribute_mode; T((T_CALLED("_nc_trim_sgr0()"))); if (PRESENT(exit_attribute_mode) && PRESENT(set_attributes)) { bool found = FALSE; char *on = set_attribute_9(tp, 1); char *off = set_attribute_9(tp, 0); char *end = strdup(exit_attribute_mode); char *tmp; size_t i, j, k; TR(TRACE_DATABASE, ("checking if we can trim sgr0 based on sgr")); TR(TRACE_DATABASE, ("sgr0 %s", _nc_visbuf(end))); TR(TRACE_DATABASE, ("sgr(9:off) %s", _nc_visbuf(off))); TR(TRACE_DATABASE, ("sgr(9:on) %s", _nc_visbuf(on))); if (!rewrite_sgr(on, enter_alt_charset_mode) || !rewrite_sgr(off, exit_alt_charset_mode) || !rewrite_sgr(end, exit_alt_charset_mode)) { FreeIfNeeded(off); } else if (similar_sgr(off, end) && !similar_sgr(off, on)) { TR(TRACE_DATABASE, ("adjusting sgr(9:off) : %s", _nc_visbuf(off))); result = off; /* * If rmacs is a substring of sgr(0), remove that chunk. */ if (exit_alt_charset_mode != 0) { TR(TRACE_DATABASE, ("scan for rmacs %s", _nc_visbuf(exit_alt_charset_mode))); j = strlen(off); k = strlen(exit_alt_charset_mode); if (j > k) { for (i = 0; i <= (j - k); ++i) { unsigned k2 = compare_part(exit_alt_charset_mode, off + i); if (k2 != 0) { found = TRUE; chop_out(off, (unsigned) i, (unsigned) (i + k2)); break; } } } } /* * SGR 10 would reset to normal font. */ if (!found) { if ((i = (size_t) is_csi(off)) != 0 && off[strlen(off) - 1] == 'm') { TR(TRACE_DATABASE, ("looking for SGR 10 in %s", _nc_visbuf(off))); tmp = skip_zero(off + i); if (tmp[0] == '1' && skip_zero(tmp + 1) != tmp + 1) { i = (size_t) (tmp - off); if (off[i - 1] == ';') i--; j = (size_t) (skip_zero(tmp + 1) - off); (void) chop_out(off, (unsigned) i, (unsigned) j); found = TRUE; } } } if (!found && (tmp = strstr(end, off)) != 0 && strcmp(end, off) != 0) { i = (size_t) (tmp - end); j = strlen(off); tmp = strdup(end); chop_out(tmp, (unsigned) i, (unsigned) j); free(off); result = tmp; } TR(TRACE_DATABASE, ("...adjusted sgr0 : %s", _nc_visbuf(result))); if (!strcmp(result, exit_attribute_mode)) { TR(TRACE_DATABASE, ("...same result, discard")); free(result); result = exit_attribute_mode; } } else { /* * Either the sgr does not reference alternate character set, * or it is incorrect. That's too hard to decide right now. */ free(off); } FreeIfNeeded(end); FreeIfNeeded(on); } else { /* * Possibly some applications are confused if sgr0 contains rmacs, * but that would be a different bug report -TD */ } returnPtr(result); }
static void postprocess_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 (!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("``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~"); } }
static int write_object(TERMTYPE *tp, char *buffer, unsigned *offset, unsigned limit) { char *namelist; size_t namelen, boolmax, nummax, strmax; char zero = '\0'; size_t i; short nextfree; short offsets[MAX_ENTRY_SIZE / 2]; unsigned char buf[MAX_ENTRY_SIZE]; unsigned last_bool = BOOLWRITE; unsigned last_num = NUMWRITE; unsigned last_str = STRWRITE; #if NCURSES_XNAMES /* * Normally we limit the list of values to exclude the "obsolete" * capabilities. However, if we are accepting extended names, add * these as well, since they are used for supporting translation * to/from termcap. */ if (_nc_user_definable) { last_bool = BOOLCOUNT; last_num = NUMCOUNT; last_str = STRCOUNT; } #endif namelist = tp->term_names; namelen = strlen(namelist) + 1; boolmax = 0; for (i = 0; i < last_bool; i++) { if (tp->Booleans[i] == TRUE) boolmax = i + 1; } nummax = 0; for (i = 0; i < last_num; i++) { if (tp->Numbers[i] != ABSENT_NUMERIC) nummax = i + 1; } strmax = 0; for (i = 0; i < last_str; i++) { if (tp->Strings[i] != ABSENT_STRING) strmax = i + 1; } nextfree = compute_offsets(tp->Strings, strmax, offsets); /* fill in the header */ LITTLE_ENDIAN(buf, MAGIC); LITTLE_ENDIAN(buf + 2, min(namelen, MAX_NAME_SIZE + 1)); LITTLE_ENDIAN(buf + 4, boolmax); LITTLE_ENDIAN(buf + 6, nummax); LITTLE_ENDIAN(buf + 8, strmax); LITTLE_ENDIAN(buf + 10, nextfree); /* write out the header */ TRACE_OUT(("Header of %s @%d", namelist, *offset)); if (Write(buf, 12, 1) != 1 || Write(namelist, sizeof(char), namelen) != namelen) return (ERR); for (i = 0; i < boolmax; i++) if (tp->Booleans[i] == TRUE) buf[i] = TRUE; else buf[i] = FALSE; if (Write(buf, sizeof(char), boolmax) != boolmax) return (ERR); if (even_boundary(namelen + boolmax)) return (ERR); TRACE_OUT(("Numerics begin at %04x", *offset)); /* the numerics */ convert_shorts(buf, tp->Numbers, nummax); if (Write(buf, 2, nummax) != nummax) return (ERR); TRACE_OUT(("String offsets begin at %04x", *offset)); /* the string offsets */ convert_shorts(buf, offsets, strmax); if (Write(buf, 2, strmax) != strmax) return (ERR); TRACE_OUT(("String table begins at %04x", *offset)); /* the strings */ for (i = 0; i < strmax; i++) if (VALID_STRING(tp->Strings[i])) if (!WRITE_STRING(tp->Strings[i])) return (ERR); #if NCURSES_XNAMES if (extended_object(tp)) { unsigned extcnt = NUM_EXT_NAMES(tp); if (even_boundary(nextfree)) return (ERR); nextfree = compute_offsets(tp->Strings + STRCOUNT, tp->ext_Strings, offsets); TRACE_OUT(("after extended string capabilities, nextfree=%d", nextfree)); if (tp->ext_Strings >= SIZEOF(offsets)) return (ERR); nextfree += compute_offsets(tp->ext_Names, extcnt, offsets + tp->ext_Strings); TRACE_OUT(("after extended capnames, nextfree=%d", nextfree)); strmax = tp->ext_Strings + extcnt; /* * Write the extended header */ LITTLE_ENDIAN(buf + 0, tp->ext_Booleans); LITTLE_ENDIAN(buf + 2, tp->ext_Numbers); LITTLE_ENDIAN(buf + 4, tp->ext_Strings); LITTLE_ENDIAN(buf + 6, strmax); LITTLE_ENDIAN(buf + 8, nextfree); TRACE_OUT(("WRITE extended-header @%d", *offset)); if (Write(buf, 10, 1) != 1) return (ERR); TRACE_OUT(("WRITE %d booleans @%d", tp->ext_Booleans, *offset)); if (tp->ext_Booleans && Write(tp->Booleans + BOOLCOUNT, sizeof(char), tp->ext_Booleans) != tp->ext_Booleans) return (ERR); if (even_boundary(tp->ext_Booleans)) return (ERR); TRACE_OUT(("WRITE %d numbers @%d", tp->ext_Numbers, *offset)); if (tp->ext_Numbers) { convert_shorts(buf, tp->Numbers + NUMCOUNT, tp->ext_Numbers); if (Write(buf, 2, tp->ext_Numbers) != tp->ext_Numbers) return (ERR); } /* * Convert the offsets for the ext_Strings and ext_Names tables, * in that order. */ convert_shorts(buf, offsets, strmax); TRACE_OUT(("WRITE offsets @%d", *offset)); if (Write(buf, 2, strmax) != strmax) return (ERR); /* * Write the string table after the offset tables so we do not * have to do anything about alignment. */ for (i = 0; i < tp->ext_Strings; i++) { if (VALID_STRING(tp->Strings[i + STRCOUNT])) { TRACE_OUT(("WRITE ext_Strings[%d]=%s", (int) i, _nc_visbuf(tp->Strings[i + STRCOUNT]))); if (!WRITE_STRING(tp->Strings[i + STRCOUNT])) return (ERR); } } /* * Write the extended names */ for (i = 0; i < extcnt; i++) { TRACE_OUT(("WRITE ext_Names[%d]=%s", (int) i, tp->ext_Names[i])); if (!WRITE_STRING(tp->ext_Names[i])) return (ERR); } } #endif /* NCURSES_XNAMES */ total_written++; return (OK); }
_nc_add_to_try(TRIES ** tree, const char *str, unsigned code) { TRIES *ptr, *savedptr; unsigned const char *txt = (unsigned const char *) str; T((T_CALLED("_nc_add_to_try(%p, %s, %u)"), *tree, _nc_visbuf(str), code)); if (txt == 0 || *txt == '\0' || code == 0) returnCode(ERR); if ((*tree) != 0) { ptr = savedptr = (*tree); for (;;) { unsigned char cmp = *txt; while (!CMP_TRY(ptr->ch, cmp) && ptr->sibling != 0) ptr = ptr->sibling; if (CMP_TRY(ptr->ch, cmp)) { if (*(++txt) == '\0') { ptr->value = code; returnCode(OK); } if (ptr->child != 0) ptr = ptr->child; else break; } else { if ((ptr->sibling = typeCalloc(TRIES, 1)) == 0) { returnCode(ERR); } savedptr = ptr = ptr->sibling; SET_TRY(ptr, txt); ptr->value = 0; break; } } /* end for (;;) */ } else { /* (*tree) == 0 :: First sequence to be added */ savedptr = ptr = (*tree) = typeCalloc(TRIES, 1); if (ptr == 0) { returnCode(ERR); } SET_TRY(ptr, txt); ptr->value = 0; } /* at this point, we are adding to the try. ptr->child == 0 */ while (*txt) { ptr->child = typeCalloc(TRIES, 1); ptr = ptr->child; if (ptr == 0) { while ((ptr = savedptr) != 0) { savedptr = ptr->child; free(ptr); } returnCode(ERR); } SET_TRY(ptr, txt); ptr->value = 0; } ptr->value = code; returnCode(OK); }
tputs(const char *string, int affcnt, int (*outc) (int)) { bool always_delay; bool normal_delay; int number; #if BSD_TPUTS int trailpad; #endif /* BSD_TPUTS */ #ifdef TRACE char addrbuf[32]; if (_nc_tracing & TRACE_TPUTS) { if (outc == _nc_outch) (void) strcpy(addrbuf, "_nc_outch"); else (void) sprintf(addrbuf, "%p", outc); if (_nc_tputs_trace) { _tracef("tputs(%s = %s, %d, %s) called", _nc_tputs_trace, _nc_visbuf(string), affcnt, addrbuf); } else { _tracef("tputs(%s, %d, %s) called", _nc_visbuf(string), affcnt, addrbuf); } _nc_tputs_trace = (char *) NULL; } #endif /* TRACE */ if (!VALID_STRING(string)) return ERR; if (cur_term == 0) { always_delay = FALSE; normal_delay = TRUE; } else { always_delay = (string == bell) || (string == flash_screen); normal_delay = !xon_xoff && padding_baud_rate #if NCURSES_NO_PADDING && (SP == 0 || !(SP->_no_padding)) #endif && (_nc_baudrate(ospeed) >= padding_baud_rate); } #if BSD_TPUTS /* * This ugly kluge deals with the fact that some ancient BSD programs * (like nethack) actually do the likes of tputs("50") to get delays. */ trailpad = 0; if (isdigit(UChar(*string))) { while (isdigit(UChar(*string))) { trailpad = trailpad * 10 + (*string - '0'); string++; } trailpad *= 10; if (*string == '.') { string++; if (isdigit(UChar(*string))) { trailpad += (*string - '0'); string++; } while (isdigit(UChar(*string))) string++; } if (*string == '*') { trailpad *= affcnt; string++; } } #endif /* BSD_TPUTS */ my_outch = outc; /* redirect delay_output() */ while (*string) { if (*string != '$') (*outc) (*string); else { string++; if (*string != '<') { (*outc) ('$'); if (*string) (*outc) (*string); } else { bool mandatory; string++; if ((!isdigit(UChar(*string)) && *string != '.') || !strchr(string, '>')) { (*outc) ('$'); (*outc) ('<'); continue; } number = 0; while (isdigit(UChar(*string))) { number = number * 10 + (*string - '0'); string++; } number *= 10; if (*string == '.') { string++; if (isdigit(UChar(*string))) { number += (*string - '0'); string++; } while (isdigit(UChar(*string))) string++; } mandatory = FALSE; while (*string == '*' || *string == '/') { if (*string == '*') { number *= affcnt; string++; } else { /* if (*string == '/') */ mandatory = TRUE; string++; } } if (number > 0 && (always_delay || normal_delay || mandatory)) delay_output(number / 10); } /* endelse (*string == '<') */ } /* endelse (*string == '$') */ if (*string == '\0') break; string++; } #if BSD_TPUTS /* * Emit any BSD-style prefix padding that we've accumulated now. */ if (trailpad > 0 && (always_delay || normal_delay)) delay_output(trailpad / 10); #endif /* BSD_TPUTS */ my_outch = _nc_outch; return OK; }
_nc_init_acs(void) { chtype *fake_map = acs_map; chtype *real_map = SP != 0 ? SP->_acs_map : fake_map; int j; T(("initializing ACS map")); /* * If we're using this from curses (rather than terminfo), we are storing * the mapping information in the SCREEN struct so we can decide how to * render it. */ if (real_map != fake_map) { for (j = 1; j < ACS_LEN; ++j) { real_map[j] = 0; fake_map[j] = A_ALTCHARSET | j; SP->_screen_acs_map[j] = FALSE; } } else { for (j = 1; j < ACS_LEN; ++j) { real_map[j] = 0; } } /* * Initializations for a UNIX-like multi-terminal environment. Use * ASCII chars and count on the terminfo description to do better. */ real_map['l'] = '+'; /* should be upper left corner */ real_map['m'] = '+'; /* should be lower left corner */ real_map['k'] = '+'; /* should be upper right corner */ real_map['j'] = '+'; /* should be lower right corner */ real_map['u'] = '+'; /* should be tee pointing left */ real_map['t'] = '+'; /* should be tee pointing right */ real_map['v'] = '+'; /* should be tee pointing up */ real_map['w'] = '+'; /* should be tee pointing down */ real_map['q'] = '-'; /* should be horizontal line */ real_map['x'] = '|'; /* should be vertical line */ real_map['n'] = '+'; /* should be large plus or crossover */ real_map['o'] = '~'; /* should be scan line 1 */ real_map['s'] = '_'; /* should be scan line 9 */ real_map['`'] = '+'; /* should be diamond */ real_map['a'] = ':'; /* should be checker board (stipple) */ real_map['f'] = '\''; /* should be degree symbol */ real_map['g'] = '#'; /* should be plus/minus */ real_map['~'] = 'o'; /* should be bullet */ real_map[','] = '<'; /* should be arrow pointing left */ real_map['+'] = '>'; /* should be arrow pointing right */ real_map['.'] = 'v'; /* should be arrow pointing down */ real_map['-'] = '^'; /* should be arrow pointing up */ real_map['h'] = '#'; /* should be board of squares */ real_map['i'] = '#'; /* should be lantern symbol */ real_map['0'] = '#'; /* should be solid square block */ /* these defaults were invented for ncurses */ real_map['p'] = '-'; /* should be scan line 3 */ real_map['r'] = '-'; /* should be scan line 7 */ real_map['y'] = '<'; /* should be less-than-or-equal-to */ real_map['z'] = '>'; /* should be greater-than-or-equal-to */ real_map['{'] = '*'; /* should be greek pi */ real_map['|'] = '!'; /* should be not-equal */ real_map['}'] = 'f'; /* should be pound-sterling symbol */ #if !USE_WIDEC_SUPPORT if (_nc_unicode_locale() && _nc_locale_breaks_acs()) { acs_chars = NULL; ena_acs = NULL; enter_alt_charset_mode = NULL; exit_alt_charset_mode = NULL; set_attributes = NULL; } #endif if (ena_acs != NULL) { TPUTS_TRACE("ena_acs"); putp(ena_acs); } #if NCURSES_EXT_FUNCS /* * Linux console "supports" the "PC ROM" character set by the coincidence * that smpch/rmpch and smacs/rmacs have the same values. ncurses has * no codepage support (see SCO Merge for an example). Outside of the * values defined in acsc, there are no definitions for the "PC ROM" * character set (assumed by some applications to be codepage 437), but we * allow those applications to use those codepoints. * * test/blue.c uses this feature. */ #define PCH_KLUDGE(a,b) (a != 0 && b != 0 && !strcmp(a,b)) if (PCH_KLUDGE(enter_pc_charset_mode, enter_alt_charset_mode) && PCH_KLUDGE(exit_pc_charset_mode, exit_alt_charset_mode)) { size_t i; for (i = 1; i < ACS_LEN; ++i) { if (real_map[i] == 0) { real_map[i] = i; if (real_map != fake_map) { if (SP != 0) SP->_screen_acs_map[i] = TRUE; } } } } #endif if (acs_chars != NULL) { size_t i = 0; size_t length = strlen(acs_chars); while (i + 1 < length) { if (acs_chars[i] != 0 && UChar(acs_chars[i]) < ACS_LEN) { real_map[UChar(acs_chars[i])] = UChar(acs_chars[i + 1]) | A_ALTCHARSET; if (SP != 0) SP->_screen_acs_map[UChar(acs_chars[i])] = TRUE; } i += 2; } } #ifdef TRACE /* Show the equivalent mapping, noting if it does not match the * given attribute, whether by re-ordering or duplication. */ if (_nc_tracing & TRACE_CALLS) { size_t n, m; char show[ACS_LEN * 2 + 1]; for (n = 1, m = 0; n < ACS_LEN; n++) { if (real_map[n] != 0) { show[m++] = (char) n; show[m++] = ChCharOf(real_map[n]); } } show[m] = 0; if (acs_chars == NULL || strcmp(acs_chars, show)) _tracef("%s acs_chars %s", (acs_chars == NULL) ? "NULL" : "READ", _nc_visbuf(acs_chars)); _tracef("%s acs_chars %s", (acs_chars == NULL) ? "NULL" : (strcmp(acs_chars, show) ? "DIFF" : "SAME"), _nc_visbuf(show)); } #endif /* TRACE */ }
wgetnstr_events(WINDOW *win, char *str, int maxlen, EVENTLIST_1st(_nc_eventlist * evl)) { SCREEN *sp = _nc_screen_of(win); TTY buf; bool oldnl, oldecho, oldraw, oldcbreak; char erasec; char killc; char *oldstr; int ch; int y, x; T((T_CALLED("wgetnstr(%p,%p, %d)"), win, str, maxlen)); if (!win) returnCode(ERR); _nc_get_tty_mode(&buf); oldnl = sp->_nl; oldecho = sp->_echo; oldraw = sp->_raw; oldcbreak = sp->_cbreak; nl(); noecho(); noraw(); cbreak(); erasec = erasechar(); killc = killchar(); oldstr = str; getyx(win, y, x); if (is_wintouched(win) || (win->_flags & _HASMOVED)) wrefresh(win); while ((ch = wgetch_events(win, evl)) != ERR) { /* * Some terminals (the Wyse-50 is the most common) generate * a \n from the down-arrow key. With this logic, it's the * user's choice whether to set kcud=\n for wgetch(); * terminating *getstr() with \n should work either way. */ if (ch == '\n' || ch == '\r' || ch == KEY_DOWN || ch == KEY_ENTER) { if (oldecho == TRUE && win->_cury == win->_maxy && win->_scroll) wechochar(win, (chtype) '\n'); break; } #ifdef KEY_EVENT if (ch == KEY_EVENT) break; #endif #ifdef KEY_RESIZE if (ch == KEY_RESIZE) break; #endif if (ch == erasec || ch == KEY_LEFT || ch == KEY_BACKSPACE) { if (str > oldstr) { str = WipeOut(win, y, x, oldstr, str, oldecho); } } else if (ch == killc) { while (str > oldstr) { str = WipeOut(win, y, x, oldstr, str, oldecho); } } else if (ch >= KEY_MIN || (maxlen >= 0 && str - oldstr >= maxlen)) { beep(); } else { *str++ = (char) ch; if (oldecho == TRUE) { int oldy = win->_cury; if (waddch(win, (chtype) ch) == ERR) { /* * We can't really use the lower-right * corner for input, since it'll mess * up bookkeeping for erases. */ win->_flags &= ~_WRAPPED; waddch(win, (chtype) ' '); str = WipeOut(win, y, x, oldstr, str, oldecho); continue; } else if (win->_flags & _WRAPPED) { /* * If the last waddch forced a wrap & * scroll, adjust our reference point * for erasures. */ if (win->_scroll && oldy == win->_maxy && win->_cury == win->_maxy) { if (--y <= 0) { y = 0; } } win->_flags &= ~_WRAPPED; } wrefresh(win); } } } win->_curx = 0; win->_flags &= ~_WRAPPED; if (win->_cury < win->_maxy) win->_cury++; wrefresh(win); /* Restore with a single I/O call, to fix minor asymmetry between * raw/noraw, etc. */ sp->_nl = oldnl; sp->_echo = oldecho; sp->_raw = oldraw; sp->_cbreak = oldcbreak; _nc_set_tty_mode(&buf); *str = '\0'; if (ch == ERR) returnCode(ch); T(("wgetnstr returns %s", _nc_visbuf(oldstr))); #ifdef KEY_EVENT if (ch == KEY_EVENT) returnCode(ch); #endif #ifdef KEY_RESIZE if (ch == KEY_RESIZE) returnCode(ch); #endif returnCode(OK); }
_nc_get_token(bool silent) { static const char terminfo_punct[] = "@%&*!#"; long number; int type; int ch; char *numchk; char numbuf[80]; unsigned found; static char buffer[MAX_ENTRY_SIZE]; char *ptr; int dot_flag = FALSE; long token_start; if (pushtype != NO_PUSHBACK) { int retval = pushtype; _nc_set_type(pushname); DEBUG(3, ("pushed-back token: `%s', class %d", _nc_curr_token.tk_name, pushtype)); pushtype = NO_PUSHBACK; pushname[0] = '\0'; /* currtok wasn't altered by _nc_push_token() */ return (retval); } if (end_of_stream()) return (EOF); start_token: token_start = stream_pos(); while ((ch = next_char()) == '\n' || iswhite(ch)) continue; ch = eat_escaped_newline(ch); if (ch == EOF) type = EOF; else { /* if this is a termcap entry, skip a leading separator */ if (separator == ':' && ch == ':') ch = next_char(); if (ch == '.' #if NCURSES_EXT_FUNCS && !_nc_disable_period #endif ) { dot_flag = TRUE; DEBUG(8, ("dot-flag set")); while ((ch = next_char()) == '.' || iswhite(ch)) continue; } if (ch == EOF) { type = EOF; goto end_of_token; } /* have to make some punctuation chars legal for terminfo */ if (!isalnum(ch) #if NCURSES_EXT_FUNCS && !(ch == '.' && _nc_disable_period) #endif && !strchr(terminfo_punct, (char) ch)) { if (!silent) _nc_warning("Illegal character (expected alphanumeric or %s) - %s", terminfo_punct, unctrl((chtype) ch)); _nc_panic_mode(separator); goto start_token; } ptr = buffer; *(ptr++) = ch; if (first_column) { char *desc; _nc_comment_start = token_start; _nc_comment_end = _nc_curr_file_pos; _nc_start_line = _nc_curr_line; _nc_syntax = ERR; while ((ch = next_char()) != '\n') { if (ch == EOF) _nc_err_abort("premature EOF"); else if (ch == ':' && last_char() != ',') { _nc_syntax = SYN_TERMCAP; separator = ':'; break; } else if (ch == ',') { _nc_syntax = SYN_TERMINFO; separator = ','; /* * Fall-through here is not an accident. The idea is that * if we see a comma, we figure this is terminfo unless we * subsequently run into a colon -- but we don't stop * looking for that colon until hitting a newline. This * allows commas to be embedded in description fields of * either syntax. */ /* FALLTHRU */ } else ch = eat_escaped_newline(ch); *ptr++ = ch; } ptr[0] = '\0'; if (_nc_syntax == ERR) { /* * Grrr...what we ought to do here is barf, complaining that * the entry is malformed. But because a couple of name fields * in the 8.2 termcap file end with |\, we just have to assume * it's termcap syntax. */ _nc_syntax = SYN_TERMCAP; separator = ':'; } else if (_nc_syntax == SYN_TERMINFO) { /* throw away trailing /, *$/ */ for (--ptr; iswhite(*ptr) || *ptr == ','; ptr--) continue; ptr[1] = '\0'; } /* * This is the soonest we have the terminal name fetched. Set up * for following warning messages. */ ptr = strchr(buffer, '|'); if (ptr == (char *) NULL) ptr = buffer + strlen(buffer); ch = *ptr; *ptr = '\0'; _nc_set_type(buffer); *ptr = ch; /* * Compute the boundary between the aliases and the description * field for syntax-checking purposes. */ desc = strrchr(buffer, '|'); if (!silent && desc) { if (*desc == '\0') _nc_warning("empty longname field"); else if (strchr(desc, ' ') == (char *) NULL) _nc_warning("older tic versions may treat the description field as an alias"); } if (!desc) desc = buffer + strlen(buffer); /* * Whitespace in a name field other than the long name can confuse * rdist and some termcap tools. Slashes are a no-no. Other * special characters can be dangerous due to shell expansion. */ for (ptr = buffer; ptr < desc; ptr++) { if (isspace(CharOf(*ptr))) { if (!silent) _nc_warning("whitespace in name or alias field"); break; } else if (*ptr == '/') { if (!silent) _nc_warning("slashes aren't allowed in names or aliases"); break; } else if (strchr("$[]!*?", *ptr)) { if (!silent) _nc_warning("dubious character `%c' in name or alias field", *ptr); break; } } ptr = buffer; _nc_curr_token.tk_name = buffer; type = NAMES; } else { while ((ch = next_char()) != EOF) { if (!isalnum(ch)) { if (_nc_syntax == SYN_TERMINFO) { if (ch != '_') break; } else { /* allow ';' for "k;" */ if (ch != ';') break; } } *(ptr++) = ch; } *ptr++ = '\0'; switch (ch) { case ',': case ':': if (ch != separator) _nc_err_abort("Separator inconsistent with syntax"); _nc_curr_token.tk_name = buffer; type = BOOLEAN; break; case '@': if ((ch = next_char()) != separator && !silent) _nc_warning("Missing separator after `%s', have %s", buffer, unctrl((chtype) ch)); _nc_curr_token.tk_name = buffer; type = CANCEL; break; case '#': found = 0; while (isalnum(ch = next_char())) { numbuf[found++] = ch; if (found >= sizeof(numbuf) - 1) break; } numbuf[found] = '\0'; number = strtol(numbuf, &numchk, 0); if (!silent) { if (numchk == numbuf) _nc_warning("no value given for `%s'", buffer); if ((*numchk != '\0') || (ch != separator)) _nc_warning("Missing separator"); } _nc_curr_token.tk_name = buffer; _nc_curr_token.tk_valnumber = number; type = NUMBER; break; case '=': ch = _nc_trans_string(ptr, buffer + sizeof(buffer)); if (!silent && ch != separator) _nc_warning("Missing separator"); _nc_curr_token.tk_name = buffer; _nc_curr_token.tk_valstring = ptr; type = STRING; break; case EOF: type = EOF; break; default: /* just to get rid of the compiler warning */ type = UNDEF; if (!silent) _nc_warning("Illegal character - %s", unctrl((chtype) ch)); } } /* end else (first_column == FALSE) */ } /* end else (ch != EOF) */ end_of_token: #ifdef TRACE if (dot_flag == TRUE) DEBUG(8, ("Commented out ")); if (_nc_tracing >= DEBUG_LEVEL(7)) { switch (type) { case BOOLEAN: _tracef("Token: Boolean; name='%s'", _nc_curr_token.tk_name); break; case NUMBER: _tracef("Token: Number; name='%s', value=%d", _nc_curr_token.tk_name, _nc_curr_token.tk_valnumber); break; case STRING: _tracef("Token: String; name='%s', value=%s", _nc_curr_token.tk_name, _nc_visbuf(_nc_curr_token.tk_valstring)); break; case CANCEL: _tracef("Token: Cancel; name='%s'", _nc_curr_token.tk_name); break; case NAMES: _tracef("Token: Names; value='%s'", _nc_curr_token.tk_name); break; case EOF: _tracef("Token: End of file"); break; default: _nc_warning("Bad token type"); } } #endif if (dot_flag == TRUE) /* if commented out, use the next one */ type = _nc_get_token(silent); DEBUG(3, ("token: `%s', class %d", _nc_curr_token.tk_name != 0 ? _nc_curr_token.tk_name : "<null>", type)); return (type); }
static inline char *tparam_internal(const char *string, va_list ap) { #define NUM_VARS 26 int param[9]; int popcount; int variable[NUM_VARS]; static int sVariable[NUM_VARS]; char len; int number; int level; int x, y; int i; int varused = -1; register const char *cp; out_used = 0; if (string == NULL) return NULL; /* * Find the highest parameter-number referred to in the format string. * Use this value to limit the number of arguments copied from the * variable-length argument list. */ for (cp = string, popcount = number = 0; *cp != '\0'; cp++) { if (cp[0] == '%' && cp[1] != '\0') { switch (cp[1]) { case '%': cp++; break; case 'i': if (popcount < 2) popcount = 2; break; case 'p': cp++; if (cp[1] >= '1' && cp[1] <= '9') { int c = cp[1] - '0'; if (c > popcount) popcount = c; } break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case 'd': case 'c': case 's': ++number; break; } } } if (number > 9) number = 9; for (i = 0; i < max(popcount, number); i++) { /* * FIXME: potential loss here if sizeof(int) != sizeof(char *). * A few caps (such as plab_norm) have string-valued parms. */ param[i] = va_arg(ap, int); } /* * This is a termcap compatibility hack. If there are no explicit pop * operations in the string, load the stack in such a way that * successive pops will grab successive parameters. That will make * the expansion of (for example) \E[%d;%dH work correctly in termcap * style, which means tparam() will expand termcap strings OK. */ stack_ptr = 0; if (popcount == 0) { popcount = number; for (i = number - 1; i >= 0; i--) npush(param[i]); } #ifdef TRACE if (_nc_tracing & TRACE_CALLS) { for (i = 0; i < popcount; i++) save_number(", %d", param[i]); _tracef(T_CALLED("%s(%s%s)"), tname, _nc_visbuf(string), out_buff); out_used = 0; } #endif /* TRACE */ while (*string) { if (*string != '%') save_char(*string); else { string++; switch (*string) { default: break; case '%': save_char('%'); break; case 'd': save_number("%d", npop()); break; case 'x': save_number("%x", npop()); break; case '0': string++; len = *string; if (len == '2' || len == '3') { ++string; if (*string == 'd') { if (len == '2') save_number("%02d", npop()); else save_number("%03d", npop()); } else if (*string == 'x') { if (len == '2') save_number("%02x", npop()); else save_number("%03x", npop()); } } break; case '2': string++; if (*string == 'd') { save_number("%2d", npop()); } else if (*string == 'x') { save_number("%2x", npop()); } break; case '3': string++; if (*string == 'd') { save_number("%3d", npop()); } else if (*string == 'x') { save_number("%3x", npop()); } break; case 'c': save_char(npop()); break; case 's': save_text(spop()); break; case 'p': string++; if (*string >= '1' && *string <= '9') npush(param[*string - '1']); break; case 'P': string++; if (islower(*string)) { i = (*string - 'a'); if (i >= 0 && i < NUM_VARS) { while (varused < i) variable[++varused] = 0; variable[i] = npop(); } } else { i = (*string - 'A'); if (i >= 0 && i < NUM_VARS) sVariable[i] = npop(); } break; case 'g': string++; if (islower(*string)) { i = (*string - 'a'); if (i >= 0 && i < NUM_VARS) { while (varused < i) variable[++varused] = 0; npush(variable[i]); } } else { i = (*string - 'A'); if (i >= 0 && i < NUM_VARS) npush(sVariable[i]); } break; case '\'': string++; npush(*string); string++; break; case L_BRACE: number = 0; string++; while (*string >= '0' && *string <= '9') { number = number * 10 + *string - '0'; string++; } npush(number); break; case '+': npush(npop() + npop()); break; case '-': y = npop(); x = npop(); npush(x - y); break; case '*': npush(npop() * npop()); break; case '/': y = npop(); x = npop(); npush(x / y); break; case 'm': y = npop(); x = npop(); npush(x % y); break; case 'A': npush(npop() && npop()); break; case 'O': npush(npop() || npop()); break; case '&': npush(npop() & npop()); break; case '|': npush(npop() | npop()); break; case '^': npush(npop() ^ npop()); break; case '=': y = npop(); x = npop(); npush(x == y); break; case '<': y = npop(); x = npop(); npush(x < y); break; case '>': y = npop(); x = npop(); npush(x > y); break; case '!': npush(! npop()); break; case '~': npush(~ npop()); break; case 'i': param[0]++; param[1]++; break; case '?': break; case 't': x = npop(); if (!x) { /* scan forward for %e or %; at level zero */ string++; level = 0; while (*string) { if (*string == '%') { string++; if (*string == '?') level++; else if (*string == ';') { if (level > 0) level--; else break; } else if (*string == 'e' && level == 0) break; } if (*string) string++; } } break; case 'e': /* scan forward for a %; at level zero */ string++; level = 0; while (*string) { if (*string == '%') { string++; if (*string == '?') level++; else if (*string == ';') { if (level > 0) level--; else break; } } if (*string) string++; } break; case ';': break; } /* endswitch (*string) */ } /* endelse (*string == '%') */ if (*string == '\0') break; string++; } /* endwhile (*string) */ if (out_buff == 0) out_buff = calloc(1,1); if (out_used == 0) *out_buff = '\0'; T((T_RETURN("%s"), _nc_visbuf(out_buff))); return(out_buff); }