📄 link.c
字号:
/* HTML parser *//* $Id: link.c,v 1.75.2.2 2005/04/05 21:08:41 jonas Exp $ */#ifdef HAVE_CONFIG_H#include "config.h"#endif#ifndef _GNU_SOURCE#define _GNU_SOURCE /* strcasestr() */#endif#include <stdarg.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include "elinks.h"#include "main.h"#include "bfu/listmenu.h"#include "bfu/menu.h"#include "bookmarks/bookmarks.h"#include "config/options.h"#include "config/kbdbind.h"#include "document/html/frames.h"#include "document/html/parser/link.h"#include "document/html/parser/stack.h"#include "document/html/parser/parse.h"#include "document/html/parser.h"#include "document/html/renderer.h"#include "globhist/globhist.h"#include "mime/mime.h"#include "protocol/uri.h"#include "util/conv.h"#include "util/error.h"#include "util/memdebug.h"#include "util/memory.h"#include "util/string.h"/* Unsafe macros */#include "document/html/internal.h"voidhtml_a(unsigned char *a){ unsigned char *href; href = get_url_val(a, "href"); if (href) { unsigned char *target; mem_free_set(&format.link, join_urls(html_context.base_href, trim_chars(href, ' ', 0))); mem_free(href); target = get_target(a); if (target) { mem_free_set(&format.target, target); } else { mem_free_set(&format.target, stracpy(html_context.base_target)); } if (0) { ; /* Shut up compiler */#ifdef CONFIG_GLOBHIST } else if (get_global_history_item(format.link)) { format.style.fg = format.vlink; html_top.pseudo_class &= ~ELEMENT_LINK; html_top.pseudo_class |= ELEMENT_VISITED;#endif#ifdef CONFIG_BOOKMARKS } else if (get_bookmark(format.link)) { format.style.fg = format.bookmark_link; html_top.pseudo_class &= ~ELEMENT_VISITED; /* XXX: Really set ELEMENT_LINK? --pasky */ html_top.pseudo_class |= ELEMENT_LINK;#endif } else { format.style.fg = format.clink; html_top.pseudo_class &= ~ELEMENT_VISITED; html_top.pseudo_class |= ELEMENT_LINK; } mem_free_set(&format.title, get_attr_val(a, "title")); html_focusable(a); } else { kill_html_stack_item(&html_top); } set_fragment_identifier(a, "name");}/* Returns an allocated string made after @label * but limited to @max_len length, by truncating * the middle of @label string, which is replaced * by an asterisk ('*'). * If @max_len < 0 it returns NULL. * If @max_len == 0 it returns an unmodified copy * of @label string. * In either case, it may return NULL if a memory * allocation failure occurs. * Example: * truncate_label("some_string", 5) => "so*ng" */static unsigned char *truncate_label(unsigned char *label, int max_len){ unsigned char *new_label; int len = strlen(label); int left_part_len; int right_part_len; if (max_len < 0) return NULL; if (max_len == 0 || len <= max_len) return stracpy(label); right_part_len = left_part_len = max_len / 2; if (left_part_len + right_part_len + 1 > max_len) right_part_len--; new_label = mem_alloc(max_len + 1); if (!new_label) return NULL; if (left_part_len) memcpy(new_label, label, left_part_len); new_label[left_part_len] = '*'; if (right_part_len) memcpy(new_label + left_part_len + 1, label + len - right_part_len, right_part_len); new_label[max_len] = '\0'; return new_label;}/* Get image filename from its src attribute. */static unsigned char *get_image_filename_from_src(unsigned char *src){ unsigned char *text = NULL; unsigned char *start, *filename; int len; if (!src) return NULL; /* We can display image as [foo.gif]. */ len = strcspn(src, "?"); for (start = src + len; start > src; start--) if (dir_sep(start[-1])) { break; } len -= start - src; filename = memacpy(start, len); if (filename) { /* XXX: Due to a compatibility alias (added: 2004-12-15 in * 0.10pre3.CVS for document.browse.images.file_tags) this can * return a negative @max_len. */ int max_len = get_opt_int("document.browse.images.filename_maxlen"); text = truncate_label(filename, max_len); mem_free(filename); } return text;}/* Returns an allocated string containing formatted @label. */static unsigned char *get_image_label(unsigned char *label){ unsigned char *formatted_label; int max_len; if (!label) return NULL; max_len = get_opt_int("document.browse.images.label_maxlen"); formatted_label = truncate_label(label, max_len); mem_free(label); return formatted_label;}static voidput_image_label(unsigned char *a, unsigned char *label){ color_t fg; /* This is not 100% appropriate for <img>, but well, accepting * accesskey and tabindex near <img> is just our little * extension to the standard. After all, it makes sense. */ html_focusable(a); fg = format.style.fg; format.style.fg = format.image_link; put_chrs(label, strlen(label), html_context.put_chars_f, html_context.part); format.style.fg = fg;}static voidhtml_img_do(unsigned char *a, unsigned char *object_src){ int ismap, usemap = 0; int add_brackets = 0; unsigned char *src = NULL; unsigned char *label = NULL; unsigned char *usemap_attr; int display_style = get_opt_int("document.browse.images.display_style"); /* Note about display_style: * 0 means always display IMG * 1 means always display filename * 2 means display alt/title attribute if possible, IMG if not * 3 means display alt/title attribute if possible, filename if not */ usemap_attr = get_attr_val(a, "usemap"); if (usemap_attr) { unsigned char *joined_urls = join_urls(html_context.base_href, usemap_attr); unsigned char *map_url; mem_free(usemap_attr); if (!joined_urls) return; map_url = straconcat("MAP@", joined_urls, NULL); mem_free(joined_urls); if (!map_url) return; html_stack_dup(ELEMENT_KILLABLE); mem_free_set(&format.link, map_url); format.form = NULL; format.style.attr |= AT_BOLD; usemap = 1; } ismap = format.link && has_attr(a, "ismap") && !usemap; if (display_style == 2 || display_style == 3) { label = get_attr_val(a, "alt"); if (!label) label = get_attr_val(a, "title"); /* Little hack to preserve rendering of [ ], in directories listing, * but we still want to drop extra spaces in alt or title attribute * to limit display width on certain websites. --Zas */ if (label && strlen(label) > 5) clr_spaces(label); } src = null_or_stracpy(object_src); if (!src) src = get_url_val(a, "src"); if (!src) src = get_url_val(a, "dynsrc"); /* If we have no label yet (no title or alt), so * just use default ones, or image filename. */ if (!label || !*label) { mem_free_set(&label, NULL); /* Do we want to display images with no alt/title and with no * link on them ? * If not, just exit now. */ if (!global_doc_opts->images && !format.link) { mem_free_if(src); if (usemap) kill_html_stack_item(&html_top); return; } add_brackets = 1; if (usemap) { label = stracpy("USEMAP"); } else if (ismap) { label = stracpy("ISMAP"); } else { if (display_style == 3) label = get_image_filename_from_src(src); } } else { label = get_image_label(label); } if (!label || !*label) { mem_free_set(&label, NULL); add_brackets = 1; if (display_style == 1) label = get_image_filename_from_src(src); if (!label || !*label) mem_free_set(&label, stracpy("IMG")); } mem_free_set(&format.image, NULL); mem_free_set(&format.title, NULL); if (label) { int img_link_tag = get_opt_int("document.browse.images.image_link_tagging"); if (img_link_tag && (img_link_tag == 2 || add_brackets)) { unsigned char *img_link_prefix = get_opt_str("document.browse.images.image_link_prefix"); unsigned char *img_link_suffix = get_opt_str("document.browse.images.image_link_suffix"); unsigned char *new_label = straconcat(img_link_prefix, label, img_link_suffix, NULL); if (new_label) mem_free_set(&label, new_label); } if (!get_opt_bool("document.browse.images.show_any_as_links")) { put_image_label(a, label); } else { if (src) { format.image = join_urls(html_context.base_href, src); } format.title = get_attr_val(a, "title"); if (ismap) { unsigned char *new_link; html_stack_dup(ELEMENT_KILLABLE); new_link = straconcat(format.link, "?0,0", NULL); if (new_link) mem_free_set(&format.link, new_link); } put_image_label(a, label); if (ismap) kill_html_stack_item(&html_top); mem_free_set(&format.image, NULL); mem_free_set(&format.title, NULL); } mem_free(label); } mem_free_if(src); if (usemap) kill_html_stack_item(&html_top);}voidhtml_img(unsigned char *a){ html_img_do(a, NULL);}voidput_link_line(unsigned char *prefix, unsigned char *linkname, unsigned char *link, unsigned char *target){ html_context.has_link_lines = 1; html_stack_dup(ELEMENT_KILLABLE); ln_break(1, html_context.line_break_f, html_context.part); mem_free_set(&format.link, NULL); mem_free_set(&format.target, NULL); mem_free_set(&format.title, NULL); format.form = NULL; put_chrs(prefix, strlen(prefix), html_context.put_chars_f, html_context.part); format.link = join_urls(html_context.base_href, link); format.target = stracpy(target); format.style.fg = format.clink; put_chrs(linkname, strlen(linkname), html_context.put_chars_f, html_context.part); ln_break(1, html_context.line_break_f, html_context.part); kill_html_stack_item(&html_top);}voidhtml_applet(unsigned char *a){ unsigned char *code, *alt; code = get_url_val(a, "code"); if (!code) return; alt = get_attr_val(a, "alt"); html_focusable(a); if (alt && *alt) { put_link_line("Applet: ", alt, code, global_doc_opts->framename); } else { put_link_line("", "Applet", code, global_doc_opts->framename); } mem_free_if(alt); mem_free(code);}static voidhtml_iframe_do(unsigned char *a, unsigned char *object_src){ unsigned char *name, *url = NULL; url = null_or_stracpy(object_src); if (!url) url = get_url_val(a, "src"); if (!url) return; name = get_attr_val(a, "name"); if (!name) name = get_attr_val(a, "id"); if (!name) name = stracpy(""); if (!name) { mem_free(url); return; } html_focusable(a); if (*name) { put_link_line("IFrame: ", name, url, global_doc_opts->framename); } else { put_link_line("", "IFrame", url, global_doc_opts->framename); } mem_free(name); mem_free(url);}voidhtml_iframe(unsigned char *a){ html_iframe_do(a, NULL);}voidhtml_object(unsigned char *a)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -