static unsigned char * get_auth_entry_info(struct listbox_item *item, struct terminal *term) { struct auth_entry *auth_entry = (struct auth_entry *)item->udata; struct string info; if (item->type == BI_FOLDER) return NULL; if (!init_string(&info)) return NULL; add_format_to_string(&info, "%s: ", _("URL", term)); add_uri_to_string(&info, auth_entry->uri, URI_HTTP_AUTH); add_format_to_string(&info, "\n%s: ", _("Realm", term)); if (auth_entry->realm) { int len = strlen((const char *)auth_entry->realm); int maxlen = 512; /* Max. number of chars displayed for realm. */ if (len < maxlen) add_bytes_to_string(&info, auth_entry->realm, len); else { add_bytes_to_string(&info, auth_entry->realm, maxlen); add_to_string(&info, (const unsigned char *)"..."); } } else { add_to_string(&info, _("none", term)); } add_format_to_string(&info, "\n%s: %s\n", _("State", term), auth_entry->valid ? _("valid", term) : _("invalid", term)); return info.source; }
/** @relates string */ struct string * add_knum_to_string(struct string *string, long long num) { int ret; unsigned char t[64]; int tlen = 0; if (num && (num / (1024 * 1024)) * (1024 * 1024) == num) { ret = longcat(&t, &tlen, num / (1024 * 1024), sizeof(t) - 2, 0); t[tlen++] = 'M'; t[tlen] = '\0'; } else if (num && (num / 1024) * 1024 == num) { ret = longcat(&t, &tlen, num / 1024, sizeof(t) - 2, 0); t[tlen++] = 'k'; t[tlen] = '\0'; } else { ret = longcat(&t, &tlen, num, sizeof(t) - 1, 0); } if (ret < 0 || !tlen) return NULL; add_bytes_to_string(string, t, tlen); return string; }
struct string * add_cp_html_to_string(struct string *string, int src_codepage, const unsigned char *src, int len) { const unsigned char *const end = src + len; unicode_val_T unicode; for (;;) { unicode = cp_to_unicode(src_codepage, (unsigned char **) &src, end); if (unicode == UCS_NO_CHAR) break; if (unicode < 0x20 || unicode >= 0x7F || unicode == '<' || unicode == '>' || unicode == '&' || unicode == '\"' || unicode == '\'') { int rollback_length = string->length; if (!add_bytes_to_string(string, (const unsigned char *)"&#", 2) || !add_long_to_string(string, unicode) || !add_char_to_string(string, ';')) { string->length = rollback_length; string->source[rollback_length] = '\0'; return NULL; } } else { if (!add_char_to_string(string, unicode)) return NULL; } } return string; }
static inline void add_char_color(struct string *screen, const struct string *seq, unsigned char color) { unsigned char color_buf[3]; unsigned char *color_pos = color_buf; int seq_pos = 0; int color_len = 1; check_string_magic(seq); for (; seq->source[seq_pos] != '%'; seq_pos++) ; add_bytes_to_string(screen, seq->source, seq_pos); if (color < 10) { color_pos += 2; } else { int color2; ++color_len; if (color < 100) { ++color_pos; } else { ++color_len; if (color < 200) { color_buf[0] = '1'; color -= 100; } else { color_buf[0] = '2'; color -= 200; } } color2 = (color % 10); color /= 10; color_buf[1] = '0' + color; color = color2; } color_buf[2] = '0' + color; add_bytes_to_string(screen, color_pos, color_len); seq_pos += 2; /* Skip "%d" */ add_bytes_to_string(screen, &seq->source[seq_pos], seq->length - seq_pos); }
struct string * add_string_replace(struct string *string, unsigned char *src, int len, unsigned char replaceable, unsigned char replacement) { int oldlength = string->length; if (!add_bytes_to_string(string, src, len)) return NULL; for (src = string->source + oldlength; len; len--, src++) if (*src == replaceable) *src = replacement; return string; }
/** @relates string */ struct string * add_long_to_string(struct string *string, long long number) { unsigned char buffer[64]; int length = 0; int width; assert(string); if_assert_failed { return NULL; } width = longcat(buffer, &length, number, sizeof(buffer) - 1, 0); if (width < 0 || !length) return NULL; return add_bytes_to_string(string, buffer, length); }
/* The global Kernel::p method will for each object, directly write * object.inspect() followed by the current output record separator to the * program's standard output and will bypass the Ruby I/O libraries. * * Inspired by Vim we hook into the method and pop up a nice message box so it * can be used to easily debug scripts without dirtying the screen. */ static VALUE erb_stdout_p(int argc, VALUE *argv, VALUE self) { int i; struct string string; struct terminal *term; if (!init_string(&string)) return Qnil; for (i = 0; i < argc; i++) { VALUE substr; unsigned char *ptr; int len; if (i > 0) add_to_string(&string, ", "); substr = rb_inspect(argv[i]); /* The Ruby p() function writes variable number of objects using * the inspect() method, which adds quotes to the strings, so * gently ignore them. */ ptr = RSTRING(substr)->ptr; len = RSTRING(substr)->len; if (*ptr == '"') ptr++, len--; if (ptr[len - 1] == '"') len--; add_bytes_to_string(&string, ptr, len); } term = get_default_terminal(); if (!term) { usrerror("[Ruby] %s", string.source); done_string(&string); return Qnil; } info_box(term, MSGBOX_NO_TEXT_INTL | MSGBOX_FREE_TEXT, N_("Ruby Message"), ALIGN_LEFT, string.source); return Qnil; }
static inline void add_char_true_color(struct string *screen, const struct string *seq, unsigned char *colors) { unsigned char color_buf[3]; int i; check_string_magic(seq); add_string_to_string(screen, seq); for (i = 0; i < 3; i++) { unsigned char *color_pos = color_buf; int color_len = 1; unsigned char color = colors[i]; add_char_to_string(screen, ';'); if (color < 10) { color_pos += 2; } else { int color2; ++color_len; if (color < 100) { ++color_pos; } else { ++color_len; if (color < 200) { color_buf[0] = '1'; color -= 100; } else { color_buf[0] = '2'; color -= 200; } } color2 = (color % 10); color /= 10; color_buf[1] = '0' + color; color = color2; } color_buf[2] = '0' + color; add_bytes_to_string(screen, color_pos, color_len); } add_char_to_string(screen, 'm'); }
/* Compress a string to a single line with newlines etc. replaced with "\\n" * sequence. */ static inline unsigned char * compress_string(unsigned char *string, unsigned int length) { struct string buffer; unsigned char escape[2] = "\\"; if (!init_string(&buffer)) return NULL; for (; length > 0; string++, length--) { unsigned char *bytes = string; if (*string == '\n' || *string == '\r' || *string == '\t') { bytes = escape; escape[1] = *string == '\n' ? 'n' : (*string == '\r' ? 'r' : 't'); } add_bytes_to_string(&buffer, bytes, bytes == escape ? 2 : 1); } return buffer.source; }
/** Adds the term code for positioning the cursor at @a x and @a y to * @a string. The template term code is: "\033[<y>;<x>H" */ static inline struct string * add_cursor_move_to_string(struct string *screen, int y, int x) { #define CURSOR_NUM_LEN 10 /* 10 chars for @y and @x numbers should be more than enough. */ unsigned char code[4 + 2 * CURSOR_NUM_LEN + 1]; unsigned int length = 2; code[0] = '\033'; code[1] = '['; if (ulongcat(code, &length, y, CURSOR_NUM_LEN, 0) < 0) return screen; code[length++] = ';'; if (ulongcat(code, &length, x, CURSOR_NUM_LEN, 0) < 0) return screen; code[length++] = 'H'; return add_bytes_to_string(screen, code, length); #undef CURSOR_NUM_LEN }
struct string * add_html_to_string(struct string *string, const unsigned char *src, int len) { for (; len; len--, src++) { if (*src < 0x20 || *src == '<' || *src == '>' || *src == '&' || *src == '\"' || *src == '\'') { int rollback_length = string->length; if (!add_bytes_to_string(string, (const unsigned char *)"&#", 2) || !add_long_to_string(string, (long long)*src) || !add_char_to_string(string, ';')) { string->length = rollback_length; string->source[rollback_length] = '\0'; return NULL; } } else { if (!add_char_to_string(string, *src)) return NULL; } } return string; }
/** Time critical section. */ static inline void add_char256(struct string *screen, struct screen_driver *driver, struct screen_char *ch, struct screen_state *state) { unsigned char attr_delta = (ch->attr ^ state->attr); if ( #ifdef CONFIG_UTF8 !(driver->opt.utf8_cp && ch->data == UCS_NO_CHAR) && #endif /* CONFIG_UTF8 */ attr_delta ) { if ((attr_delta & SCREEN_ATTR_FRAME) && driver->opt.frame_seqs) { state->border = !!(ch->attr & SCREEN_ATTR_FRAME); add_term_string(screen, driver->opt.frame_seqs[state->border]); } if ((attr_delta & SCREEN_ATTR_ITALIC) && driver->opt.italic) { state->italic = !!(ch->attr & SCREEN_ATTR_ITALIC); add_term_string(screen, driver->opt.italic[state->italic]); } if ((attr_delta & SCREEN_ATTR_UNDERLINE) && driver->opt.underline) { state->underline = !!(ch->attr & SCREEN_ATTR_UNDERLINE); add_term_string(screen, driver->opt.underline[state->underline]); } if (attr_delta & SCREEN_ATTR_BOLD) { if (ch->attr & SCREEN_ATTR_BOLD) { add_bytes_to_string(screen, "\033[1m", 4); } else { /* Force repainting of the other attributes. */ state->color[0] = ch->c.color[0] + 1; } } state->attr = ch->attr; } if ( #ifdef CONFIG_UTF8 !(driver->opt.utf8_cp && ch->data == UCS_NO_CHAR) && #endif /* CONFIG_UTF8 */ !compare_color_256(ch->c.color, state->color) ) { copy_color_256(state->color, ch->c.color); add_foreground_color(screen, driver->opt.color256_seqs, ch); if (!driver->opt.transparent || ch->c.color[1] != 0) { add_background_color(screen, driver->opt.color256_seqs, ch); } if (ch->attr & SCREEN_ATTR_BOLD) add_bytes_to_string(screen, "\033[1m", 4); if (ch->attr & SCREEN_ATTR_ITALIC && driver->opt.italic) { state->italic = !!(ch->attr & SCREEN_ATTR_ITALIC); add_term_string(screen, driver->opt.italic[state->italic]); } if (ch->attr & SCREEN_ATTR_UNDERLINE && driver->opt.underline) { state->underline = !!(ch->attr & SCREEN_ATTR_UNDERLINE); add_term_string(screen, driver->opt.underline[state->underline]); } } add_char_data(screen, driver, ch->data, ch->attr & SCREEN_ATTR_FRAME); }
static enum parse_error parse_unset(struct option *opt_tree, struct conf_parsing_state *state, struct string *mirror, int is_system_conf) { const unsigned char *optname_orig; size_t optname_len; unsigned char *optname_copy; skip_white(&state->pos); if (!*state->pos.look) return show_parse_error(state, ERROR_PARSE); /* Option name */ optname_orig = state->pos.look; while (is_option_name_char(*state->pos.look) || *state->pos.look == '.') state->pos.look++; optname_len = state->pos.look - optname_orig; optname_copy = memacpy(optname_orig, optname_len); if (!optname_copy) return show_parse_error(state, ERROR_NOMEM); { struct option *opt; opt = get_opt_rec_real(opt_tree, optname_copy); mem_free(optname_copy); optname_copy = NULL; if (!opt || (opt->flags & OPT_HIDDEN)) { /* The user wanted to delete the option, and * it has already been deleted; this is not an * error. This might happen if a version of * ELinks has a built-in URL rewriting rule, * the user disables it, and a later version * no longer has it. */ return ERROR_NONE; } if (!mirror) { /* loading a configuration file */ if (opt->flags & OPT_ALLOC) delete_option(opt); else mark_option_as_deleted(opt); } else if (is_system_conf) { /* scanning a file that will not be rewritten */ struct option *flagsite = indirect_option(opt); if (flagsite->flags & OPT_DELETED) flagsite->flags &= ~OPT_MUST_SAVE; else flagsite->flags |= OPT_MUST_SAVE; } else { /* rewriting a configuration file */ struct option *flagsite = indirect_option(opt); if (flagsite->flags & OPT_DELETED) { /* The "unset" command is already in the file, * and unlike with "set", there is no value * to be updated. */ } else if (option_types[opt->type].write) { /* Replace the "unset" command with a * "set" command. */ add_to_string(mirror, "set "); add_bytes_to_string(mirror, optname_orig, optname_len); add_to_string(mirror, " = "); option_types[opt->type].write(opt, mirror); state->mirrored = state->pos.look; } /* Remember that the option need not be * written to the end of the file. */ flagsite->flags &= ~OPT_MUST_SAVE; } } return ERROR_NONE; }
struct connection_state init_directory_listing(struct string *page, struct uri *uri) { struct string dirpath = NULL_STRING; struct string decoded = NULL_STRING; struct string location = NULL_STRING; unsigned char *info; int local = (uri->protocol == PROTOCOL_FILE); if (!init_string(page) || !init_string(&dirpath) || !init_string(&decoded) || !init_string(&location) || !add_uri_to_string(&dirpath, uri, URI_DATA) || !add_uri_to_string(&location, uri, URI_DIR_LOCATION)) goto out_of_memory; if (dirpath.length > 0 && !dir_sep(dirpath.source[dirpath.length - 1]) && !add_char_to_string(&dirpath, local ? CHAR_DIR_SEP : '/')) goto out_of_memory; /* Decode uri for displaying. */ if (!add_string_to_string(&decoded, &dirpath)) goto out_of_memory; decode_uri_string(&decoded); if (!local && !add_char_to_string(&location, '/')) goto out_of_memory; if (!add_to_string(page, (const unsigned char *)"<html>\n<head><title>")) goto out_of_memory; if (!local && !add_html_to_string(page, location.source, location.length)) goto out_of_memory; if (!add_html_to_string(page, decoded.source, decoded.length) || !add_to_string(page, (const unsigned char *)"</title>\n<base href=\"") || !add_html_to_string(page, location.source, location.length) || !add_html_to_string(page, dirpath.source, dirpath.length)) goto out_of_memory; if (!add_to_string(page, (const unsigned char *)"\" />\n</head>\n<body>\n<h2>")) goto out_of_memory; /* Use module names? */ switch (uri->protocol) { case PROTOCOL_FILE: info = (unsigned char *)"Local"; break; case PROTOCOL_FSP: info = (unsigned char *)"FSP"; break; case PROTOCOL_FTP: info = (unsigned char *)"FTP"; break; case PROTOCOL_GOPHER: info = (unsigned char *)"Gopher"; break; case PROTOCOL_SMB: info = (unsigned char *)"Samba"; break; default: info = (unsigned char *)"?"; } if (!add_to_string(page, info) || !add_to_string(page, (const unsigned char *)" directory ")) goto out_of_memory; if (!local && !add_string_to_string(page, &location)) goto out_of_memory; /* Make the directory path with links to each subdir. */ { const unsigned char *slash = dirpath.source; const unsigned char *pslash = slash; const unsigned char sep = local ? CHAR_DIR_SEP : '/'; while ((slash = (const unsigned char *)strchr((char *)slash, sep)) != NULL) { done_string(&decoded); if (!init_string(&decoded) || !add_bytes_to_string(&decoded, pslash, slash - pslash)) goto out_of_memory; decode_uri_string(&decoded); if (!add_to_string(page, (const unsigned char *)"<a href=\"") || !add_html_to_string(page, location.source, location.length) || !add_html_to_string(page, dirpath.source, slash + 1 - dirpath.source) || !add_to_string(page, (const unsigned char *)"\">") || !add_html_to_string(page, decoded.source, decoded.length) || !add_to_string(page, (const unsigned char *)"</a>") || !add_html_to_string(page, &sep, 1)) goto out_of_memory; pslash = ++slash; } } if (!add_to_string(page, (const unsigned char *)"</h2>\n<pre>")) { out_of_memory: done_string(page); } done_string(&dirpath); done_string(&decoded); done_string(&location); return page->length > 0 ? connection_state(S_OK) : connection_state(S_OUT_OF_MEM); }
static unsigned char * rewrite_uri(unsigned char *url, struct uri *current_uri, unsigned char *arg) { struct string n = NULL_STRING; unsigned char *args[MAX_URI_ARGS]; int argslen[MAX_URI_ARGS]; int argc = 0; int i; if (!init_string(&n)) return NULL; /* Extract space separated list of arguments */ args[argc] = arg; for (i = 0; ; i++) { if (args[argc][i] == ' ') { argslen[argc] = i; argc++; if (argc == MAX_URI_ARGS) break; args[argc] = &args[argc - 1][i]; i = 0; for (; *args[argc] == ' '; args[argc]++); } else if (!args[argc][i]) { argslen[argc] = i; argc++; break; } } while (*url) { int p; int value; for (p = 0; url[p] && url[p] != '%'; p++); add_bytes_to_string(&n, url, p); url += p; if (*url != '%') continue; url++; switch (*url) { case 'c': if (!current_uri) break; add_uri_to_string(&n, current_uri, URI_ORIGINAL); break; case 's': if (arg) encode_uri_string(&n, arg, -1, 1); break; case '%': add_char_to_string(&n, '%'); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': value = *url - '0'; if (value >= argc) break; encode_uri_string(&n, args[value], argslen[value], 1); break; default: add_bytes_to_string(&n, url - 1, 2); break; } if (*url) url++; } return n.source; }
static void do_html_select(unsigned char *attr, unsigned char *html, unsigned char *eof, unsigned char **end, struct html_context *html_context) { struct conv_table *ct = (struct conv_table *)html_context->special_f(html_context, SP_TABLE, NULL); struct form_control *fc; struct string lbl = NULL_STRING, orig_lbl = NULL_STRING; unsigned char **values = NULL; unsigned char **labels; unsigned char *name, *t_attr, *en; int namelen; int nnmi = 0; int order = 0; int preselect = -1; int group = 0; int i, max_width; int closing_tag; html_focusable(html_context, attr); init_menu(&lnk_menu); se: en = html; see: html = en; while (html < eof && *html != '<') html++; if (html >= eof) { abort: *end = html; if (lbl.source) done_string(&lbl); if (orig_lbl.source) done_string(&orig_lbl); if (values) { int j; for (j = 0; j < order; j++) mem_free_if(values[j]); mem_free(values); } destroy_menu(&lnk_menu); *end = en; return; } if (lbl.source) { unsigned char *q, *s = en; int l = html - en; while (l && isspace(s[0])) s++, l--; while (l && isspace(s[l-1])) l--; q = convert_string(ct, s, l, html_context->options->cp, CSM_DEFAULT, NULL, NULL, NULL); if (q) add_to_string(&lbl, q), mem_free(q); add_bytes_to_string(&orig_lbl, s, l); } if (html + 2 <= eof && (html[1] == '!' || html[1] == '?')) { html = skip_comment(html, eof); goto se; } if (parse_element(html, eof, &name, &namelen, &t_attr, &en)) { html++; goto se; } if (!namelen) goto see; if (name[0] == '/') { namelen--; if (!namelen) goto see; name++; closing_tag = 1; } else { closing_tag = 0; } if (closing_tag && !c_strlcasecmp(name, namelen, (const unsigned char *)"SELECT", 6)) { add_select_item(&lnk_menu, &lbl, &orig_lbl, values, order, nnmi); goto end_parse; } if (!c_strlcasecmp(name, namelen, (const unsigned char *)"OPTION", 6)) { add_select_item(&lnk_menu, &lbl, &orig_lbl, values, order, nnmi); if (!closing_tag) { unsigned char *value, *label; if (has_attr(t_attr, (unsigned char *)"disabled", html_context->doc_cp)) goto see; if (preselect == -1 && has_attr(t_attr, (unsigned char *)"selected", html_context->doc_cp)) preselect = order; value = get_attr_val(t_attr, (unsigned char *)"value", html_context->doc_cp); if (!mem_align_alloc(&values, order, order + 1, 0xFF)) goto abort; values[order++] = value; label = get_attr_val(t_attr, (unsigned char *)"label", html_context->doc_cp); if (label) new_menu_item(&lnk_menu, label, order - 1, 0); if (!value || !label) { init_string(&lbl); init_string(&orig_lbl); nnmi = !!label; } } goto see; } if (!c_strlcasecmp(name, namelen, (const unsigned char *)"OPTGROUP", 8)) { add_select_item(&lnk_menu, &lbl, &orig_lbl, values, order, nnmi); if (group) new_menu_item(&lnk_menu, NULL, -1, 0), group = 0; if (!closing_tag) { unsigned char *label; label = get_attr_val(t_attr, (unsigned char *)"label", html_context->doc_cp); if (!label) { label = stracpy((const unsigned char *)""); if (!label) goto see; } new_menu_item(&lnk_menu, label, -1, 0); group = 1; } } goto see; end_parse: *end = en; if (!order) goto abort; labels = (unsigned char **)mem_calloc(order, sizeof(unsigned char *)); if (!labels) goto abort; fc = init_form_control(FC_SELECT, attr, html_context); if (!fc) { mem_free(labels); goto abort; } fc->id = get_attr_val(attr, (unsigned char *)"id", html_context->doc_cp); fc->name = get_attr_val(attr, (unsigned char *)"name", html_context->doc_cp); fc->default_state = preselect < 0 ? 0 : preselect; fc->default_value = order ? stracpy(values[fc->default_state]) : stracpy((const unsigned char *)""); fc->nvalues = order; fc->values = values; fc->menu = detach_menu(&lnk_menu); fc->labels = labels; menu_labels(fc->menu, (unsigned char *)"", labels); put_chrs(html_context, (unsigned char *)"[", 1); html_stack_dup(html_context, ELEMENT_KILLABLE); format.form = fc; format.style.attr |= AT_BOLD; max_width = 0; for (i = 0; i < order; i++) { if (!labels[i]) continue; #ifdef CONFIG_UTF8 if (html_context->options->utf8) int_lower_bound(&max_width, utf8_ptr2cells(labels[i], NULL)); else #endif /* CONFIG_UTF8 */ int_lower_bound(&max_width, strlen((const char *)labels[i])); } for (i = 0; i < max_width; i++) put_chrs(html_context, (unsigned char *)"_", 1); pop_html_element(html_context); put_chrs(html_context, (unsigned char *)"]", 1); html_context->special_f(html_context, SP_CONTROL, fc); }
static enum parse_error parse_set_common(struct option *opt_tree, struct conf_parsing_state *state, struct string *mirror, int is_system_conf, int want_domain) { const unsigned char *domain_orig = NULL; size_t domain_len = 0; unsigned char *domain_copy = NULL; const unsigned char *optname_orig; size_t optname_len; unsigned char *optname_copy; skip_white(&state->pos); if (!*state->pos.look) return show_parse_error(state, ERROR_PARSE); if (want_domain) { domain_orig = state->pos.look; while (isident(*state->pos.look) || *state->pos.look == '*' || *state->pos.look == '.' || *state->pos.look == '+') state->pos.look++; domain_len = state->pos.look - domain_orig; skip_white(&state->pos); } /* Option name */ optname_orig = state->pos.look; while (is_option_name_char(*state->pos.look) || *state->pos.look == '.') state->pos.look++; optname_len = state->pos.look - optname_orig; skip_white(&state->pos); /* Equal sign */ if (*state->pos.look != '=') return show_parse_error(state, ERROR_PARSE); state->pos.look++; /* '=' */ skip_white(&state->pos); if (!*state->pos.look) return show_parse_error(state, ERROR_VALUE); optname_copy = memacpy(optname_orig, optname_len); if (!optname_copy) return show_parse_error(state, ERROR_NOMEM); if (want_domain) { domain_copy = memacpy(domain_orig, domain_len); if (!domain_copy) { mem_free(optname_copy); return show_parse_error(state, ERROR_NOMEM); } } /* Option value */ { struct option *opt; unsigned char *val; const struct conf_parsing_pos pos_before_value = state->pos; if (want_domain && *domain_copy) { struct option *domain_tree; domain_tree = get_domain_tree(domain_copy); if (!domain_tree) { mem_free(domain_copy); mem_free(optname_copy); skip_option_value(&state->pos); return show_parse_error(state, ERROR_NOMEM); } if (mirror) { opt = get_opt_rec_real(domain_tree, optname_copy); } else { opt = get_opt_rec(opt_tree, optname_copy); if (opt) { opt = get_option_shadow(opt, opt_tree, domain_tree); if (!opt) { mem_free(domain_copy); mem_free(optname_copy); skip_option_value(&state->pos); return show_parse_error(state, ERROR_NOMEM); } } } } else { opt = mirror ? get_opt_rec_real(opt_tree, optname_copy) : get_opt_rec(opt_tree, optname_copy); } if (want_domain) mem_free(domain_copy); domain_copy = NULL; mem_free(optname_copy); optname_copy = NULL; if (!opt || (opt->flags & OPT_HIDDEN)) { show_parse_error(state, ERROR_OPTION); skip_option_value(&state->pos); return ERROR_OPTION; /* TODO: Distinguish between two scenarios: * - A newer version of ELinks has saved an * option that this version does not recognize. * The option must be preserved. (This works.) * - The user has added an option, saved * elinks.conf, restarted ELinks, deleted the * option, and is now saving elinks.conf again. * The option should be rewritten to "unset". * (This does not work yet.) * In both cases, ELinks has no struct option * for that name. Possible fixes: * - If the tree has OPT_AUTOCREATE, then * assume the user had created that option, * and rewrite it to "unset". Otherwise, * keep it. * - When the user deletes an option, just mark * it with OPT_DELETED, and keep it in memory * as long as OPT_TOUCHED is set. */ } if (!option_types[opt->type].read) { show_parse_error(state, ERROR_VALUE); skip_option_value(&state->pos); return ERROR_VALUE; } val = option_types[opt->type].read(opt, &state->pos.look, &state->pos.line); if (!val) { /* The reader function failed. Jump back to * the beginning of the value and skip it with * the generic code. For the error message, * use the line number at the beginning of the * value, because the ending position is not * interesting if there is an unclosed quote. */ state->pos = pos_before_value; show_parse_error(state, ERROR_VALUE); skip_option_value(&state->pos); return ERROR_VALUE; } if (!mirror) { /* loading a configuration file */ if (!option_types[opt->type].set || !option_types[opt->type].set(opt, val)) { mem_free(val); return show_parse_error(state, ERROR_VALUE); } } else if (is_system_conf) { /* scanning a file that will not be rewritten */ struct option *flagsite = indirect_option(opt); if (!(flagsite->flags & OPT_DELETED) && option_types[opt->type].equals && option_types[opt->type].equals(opt, val)) flagsite->flags &= ~OPT_MUST_SAVE; else flagsite->flags |= OPT_MUST_SAVE; } else { /* rewriting a configuration file */ struct option *flagsite = indirect_option(opt); if (flagsite->flags & OPT_DELETED) { /* Replace the "set" command with an * "unset" command. */ add_to_string(mirror, "unset "); add_bytes_to_string(mirror, optname_orig, optname_len); state->mirrored = state->pos.look; } else if (option_types[opt->type].write) { add_bytes_to_string(mirror, state->mirrored, pos_before_value.look - state->mirrored); option_types[opt->type].write(opt, mirror); state->mirrored = state->pos.look; } /* Remember that the option need not be * written to the end of the file. */ flagsite->flags &= ~OPT_MUST_SAVE; } mem_free(val); } return ERROR_NONE; }
/** Time critical section. */ static inline void add_char16(struct string *screen, struct screen_driver *driver, struct screen_char *ch, struct screen_state *state) { unsigned char border = (ch->attr & SCREEN_ATTR_FRAME); unsigned char italic = (ch->attr & SCREEN_ATTR_ITALIC); unsigned char underline = (ch->attr & SCREEN_ATTR_UNDERLINE); unsigned char bold = (ch->attr & SCREEN_ATTR_BOLD); if ( #ifdef CONFIG_UTF8 !(driver->opt.utf8_cp && ch->data == UCS_NO_CHAR) && #endif /* CONFIG_UTF8 */ border != state->border && driver->opt.frame_seqs ) { state->border = border; add_term_string(screen, driver->opt.frame_seqs[!!border]); } if ( #ifdef CONFIG_UTF8 !(driver->opt.utf8_cp && ch->data == UCS_NO_CHAR) && #endif /* CONFIG_UTF8 */ italic != state->italic && driver->opt.italic ) { state->italic = italic; add_term_string(screen, driver->opt.italic[!!italic]); } if ( #ifdef CONFIG_UTF8 !(driver->opt.utf8_cp && ch->data == UCS_NO_CHAR) && #endif /* CONFIG_UTF8 */ underline != state->underline && driver->opt.underline ) { state->underline = underline; add_term_string(screen, driver->opt.underline[!!underline]); } if ( #ifdef CONFIG_UTF8 !(driver->opt.utf8_cp && ch->data == UCS_NO_CHAR) && #endif /* CONFIG_UTF8 */ bold != state->bold ) { state->bold = bold; if (bold) { add_bytes_to_string(screen, (const unsigned char *)"\033[1m", 4); } else { /* Force repainting of the other attributes. */ state->color[0] = ch->c.color[0] + 1; } } if ( #ifdef CONFIG_UTF8 !(driver->opt.utf8_cp && ch->data == UCS_NO_CHAR) && #endif /* CONFIG_UTF8 */ !compare_color_16(ch->c.color, state->color) ) { copy_color_16(state->color, ch->c.color); add_bytes_to_string(screen, (const unsigned char *)"\033[0", 3); /* @set_screen_driver_opt has set @driver->opt.color_mode * according to terminal-type-specific options. * The caller of @add_char16 has already partially * checked it, but there are still these possibilities: * - COLOR_MODE_MONO. Then don't show colors, but * perhaps use the standout attribute. * - COLOR_MODE_16. Use 16 colors. * - An unsupported color mode. Use 16 colors. */ if (driver->opt.color_mode != COLOR_MODE_MONO) { char code[] = ";30;40"; unsigned char bgcolor = TERM_COLOR_BACKGROUND_16(ch->c.color); code[2] += TERM_COLOR_FOREGROUND_16(ch->c.color); if (!driver->opt.transparent || bgcolor != 0) { code[5] += bgcolor; add_bytes_to_string(screen, (const unsigned char *)code, 6); } else { add_bytes_to_string(screen, (const unsigned char *)code, 3); } } else if (ch->attr & SCREEN_ATTR_STANDOUT) { /* Flip the fore- and background colors for highlighing * purposes. */ add_bytes_to_string(screen, (const unsigned char *)";7", 2); } if (italic && driver->opt.italic) { add_bytes_to_string(screen, (const unsigned char *)";3", 2); } if (underline && driver->opt.underline) { add_bytes_to_string(screen, (const unsigned char *)";4", 2); } /* Check if the char should be rendered bold. */ if (bold) { add_bytes_to_string(screen, (const unsigned char *)";1", 2); } add_bytes_to_string(screen, (const unsigned char *)"m", 1); } add_char_data(screen, driver, ch->data, border); }
static enum parse_error parse_bind(struct option *opt_tree, struct conf_parsing_state *state, struct string *mirror, int is_system_conf) { unsigned char *keymap, *keystroke, *action; enum parse_error err = ERROR_NONE; struct conf_parsing_pos before_error; skip_white(&state->pos); if (!*state->pos.look) return show_parse_error(state, ERROR_PARSE); /* Keymap */ before_error = state->pos; keymap = option_types[OPT_STRING].read(NULL, &state->pos.look, &state->pos.line); skip_white(&state->pos); if (!keymap || !*state->pos.look) { state->pos = before_error; return show_parse_error(state, ERROR_PARSE); } /* Keystroke */ before_error = state->pos; keystroke = option_types[OPT_STRING].read(NULL, &state->pos.look, &state->pos.line); skip_white(&state->pos); if (!keystroke || !*state->pos.look) { mem_free(keymap); mem_free_if(keystroke); state->pos = before_error; return show_parse_error(state, ERROR_PARSE); } /* Equal sign */ skip_white(&state->pos); if (*state->pos.look != '=') { mem_free(keymap); mem_free(keystroke); return show_parse_error(state, ERROR_PARSE); } state->pos.look++; /* '=' */ skip_white(&state->pos); if (!*state->pos.look) { mem_free(keymap); mem_free(keystroke); return show_parse_error(state, ERROR_PARSE); } /* Action */ before_error = state->pos; action = option_types[OPT_STRING].read(NULL, &state->pos.look, &state->pos.line); if (!action) { mem_free(keymap); mem_free(keystroke); state->pos = before_error; return show_parse_error(state, ERROR_PARSE); } if (!mirror) { /* loading a configuration file */ /* We don't bother to bind() if -default-keys. */ if (!get_cmd_opt_bool("default-keys") && bind_do(keymap, keystroke, action, is_system_conf)) { /* bind_do() tried but failed. */ err = show_parse_error(state, ERROR_VALUE); } else { err = ERROR_NONE; } } else if (is_system_conf) { /* scanning a file that will not be rewritten */ /* TODO */ } else { /* rewriting a configuration file */ /* Mirror what we already have. If the keystroke has * been unbound, then act_str is simply "none" and * this does not require special handling. */ unsigned char *act_str = bind_act(keymap, keystroke); if (act_str) { add_bytes_to_string(mirror, state->mirrored, before_error.look - state->mirrored); add_to_string(mirror, act_str); mem_free(act_str); state->mirrored = state->pos.look; } else { err = show_parse_error(state, ERROR_VALUE); } } mem_free(keymap); mem_free(keystroke); mem_free(action); return err; }
/* Set xterm-like term window's title. */ void set_window_title(unsigned char *title, int codepage) { struct string filtered; #ifndef HAVE_SYS_CYGWIN_H /* Check if we're in a xterm-like terminal. */ //if (!is_xterm()) return; #endif if (!init_string(&filtered)) return; /* Copy title to filtered if different from NULL */ if (title) { unsigned char *scan = title; unsigned char *end = title + strlen((const char *)title); /* Remove control characters, so that they cannot * interfere with the command we send to the terminal. * However, do not attempt to limit the title length * to terminal width, because the title is usually * drawn in a different font anyway. */ /* Note that this is the right place where to do it, since * potential alternative set_window_title() routines might * want to take different precautions. */ for (;;) { unsigned char *charbegin = scan; unicode_val_T unicode = cp_to_unicode(codepage, &scan, end); int charlen = scan - charbegin; if (unicode == UCS_NO_CHAR) break; /* This need not recognize all Unicode control * characters. Only those that can make the * terminal misparse the command. */ if (unicode < 0x20 || (unicode >= 0x7F && unicode < 0xA0)) continue; /* If the title is getting too long, truncate * it and add an ellipsis. * * xterm entirely rejects 1024-byte or longer * titles. GNU Screen 4.00.03 misparses * titles longer than 765 bytes, and is unable * to display the title in hardstatus if the * title and other stuff together exceed 766 * bytes. So set the limit quite a bit lower. */ if (filtered.length + charlen >= 600 - 3) { add_to_string(&filtered, (const unsigned char *)"..."); break; } add_bytes_to_string(&filtered, charbegin, charlen); } } //getCurrentView()->setTitle(filtered.source); /* Send terminal escape sequence + title string */ // printf("\033]0;%s\a", filtered.source); #if 0 /* Miciah don't like this so it is disabled because it changes the * default window name. --jonas */ /* Set the GNU screen window name */ if (is_gnuscreen()) printf("\033k%s\033\134", filtered.source); #endif //fflush(stdout); done_string(&filtered); }