📄 html.c
字号:
/******************************************************************************* * * html.c - HTML parsing engine * * Actual html tag implementations * * Cheetah Web Browser * Copyright (C) 2001 Garett Spencley * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * *******************************************************************************/#include <string.h>#include <stdio.h>#include <stdlib.h>#include <errno.h>#include "htmltokenizer.h"#include "html.h"#include "gui.h"#include "error.h"#include "dw_hruler.h"#include "colors.h"#include "debug.h"#include "image.h"#include "file.h"#include "dw_bullet.h"#include "font.h"static int list_num; /* For ordered lists *//* * html_add_widget() - Add a widget to the page. * taken from dillo */void html_add_widget(html_t *html, DwWidget *widget, char *width, char *height, DwStyle *style){ gint32 fixed_width = -1, fixed_height = -1; gfloat rel_height = -1, rel_width = -1; /* todo: whitespaces etc. */ if(width) { if(width[strlen(width) - 1] == '%') rel_width = atof(width) / 100; else fixed_width = atoi(width); } if(height) { if(height[strlen(height) - 1] == '%') rel_height = atof(height) / 100; else fixed_height = atoi(height); } a_Dw_widget_set_usize(widget, fixed_width, fixed_height, -1); a_Dw_page_add_widget(DW_PAGE(html->dw), widget, rel_width, rel_height, style);}/* * html_pre() - <PRE> tag */__inline int html_pre (html_t *html, char *tag, html_tag_args *args, tag_type type) { if(type == HTML_TAG_CLOSE) { html_pop_tag(html, PRE); html->preformatted = FALSE; return 0; } html_push_tag(html, PRE); html->preformatted = TRUE; html_set_font(html, "courier", 0, 0); return 0;}/* * html_head() - <HEAD> tag */__inline int html_head (html_t *html, char *tag, html_tag_args *args, tag_type type) { switch(type) { case HTML_TAG_OPEN: html_push_tag(html, HEAD); break; case HTML_TAG_CLOSE: html_pop_tag(html, HEAD); break; } return 0;}/* * html_q() - <Q> tag */__inline int html_q (html_t *html, char *tag, html_tag_args *args, tag_type type) { DwPage *page; char *quote = "\""; /* We need to see if this tag is nested. This is only a temporary solution * since we also need to be language depend (lang="" argument) but we * can't do that until we add support for more than just english */ if(html_seek_tag(html, QUOTE) >= 0) quote = "\'"; switch(type) { case HTML_TAG_OPEN: html_push_tag(html, QUOTE); break; case HTML_TAG_CLOSE: html_pop_tag(html, QUOTE); break; } page = (DwPage *)html->dw; a_Dw_page_add_text(page, g_strdup(quote), html->stack[html->stack_top].style); return 0;}/* * html_title() - <TITLE> tag */__inline int html_title (html_t *html, char *tag, html_tag_args *args, tag_type type) { switch(type) { case HTML_TAG_OPEN: html_push_tag(html, TITLE); break; case HTML_TAG_CLOSE: html_pop_tag(html, TITLE); break; } return 0;}/* * html_br() - <BR> tag */__inline int html_br (html_t *html, char *tag, html_tag_args *args, tag_type type) { a_Dw_page_linebreak((DwPage *)html->dw); return 0;}/* * html_para() - <P> tag */__inline int html_para (html_t *html, char *tag, html_tag_args *args, tag_type type) { a_Dw_page_parbreak((DwPage *)html->dw, 9); return 0;}/* * html_header() - <H> tags */__inline int html_header (html_t *html, char *tag, html_tag_args *args, tag_type type) { int level, size; int sizes[] = { 24, 18, 18, 14, 12, 10 }; if(type == HTML_TAG_CLOSE) { html_pop_tag(html, HEADER); return 0; } html_push_tag(html, HEADER); a_Dw_page_parbreak((DwPage *)html->dw, 9); level = tag[1] - '0'; size = sizes[level-1]; html_set_font(html, "helvetica", size, 1); return 0;}/* * html_script() - <SCRIPT> tag. */__inline int html_script (html_t *html, char *tag, html_tag_args *args, tag_type type) { switch(type) { case HTML_TAG_CLOSE: html->script = FALSE; break; case HTML_TAG_OPEN: html->script = TRUE; break; } return 0;}/* * html_style() - <STYLE> tag. */__inline int html_style (html_t *html, char *tag, html_tag_args *args, tag_type type){ html_tag_args *cur; if(type == HTML_TAG_CLOSE) return 0; /* <STYLE> isn't allowed outside of <HEAD> */ if(html_seek_tag(html, HEAD) < 0) return -1; /* See what kind of style we're dealing with */ cur = args; while(cur) { if(strcasecmp(cur->name, "type") == 0) if(strcasecmp(cur->value, "text/css") == 0) html->css = TRUE; cur = cur->next; } return 0;}/* * html_tt() - <TT> tag */__inline int html_tt (html_t *html, char *tag, html_tag_args *args, tag_type type) { DwStyle style_attrs; DwStyleFont font; if(type == HTML_TAG_CLOSE) { html_pop_tag(html, TT); return 0; } style_attrs = *(html->stack[html->stack_top].style); font = *(style_attrs.font); html_push_tag(html, TT); html_set_font(html, "courier", font.size - 4.0, -1); return 0;}/* * html_bold() - <B> tag */__inline int html_bold (html_t *html, char *tag, html_tag_args *args, tag_type type) { int i, flag; if(type == HTML_TAG_CLOSE) { html_pop_tag(html, BOLD); return 0; } /* We have to make sure that if we're inside some other font-modifying tag we don't * screw it up */ flag = 0; for(i = 0; i <= html->stack_top; i++) { switch(html->stack[i].tag) { case STRONG: return 0; case ITALIC: case CITE: case EM: flag += 2; break; } } html_push_tag(html, BOLD); html_set_font(html, NULL, 0, flag + 1); return 0;}/* * html_var() - <VAR> tag */__inline int html_var (html_t *html, char *tag, html_tag_args *args, tag_type type) { int i, flag; if(type == HTML_TAG_CLOSE) { html_pop_tag(html, VAR); return 0; } /* We have to make sure that if we're inside some other font-modifying tag we don't * screw it up */ flag = 0; for(i = 0; i <= html->stack_top; i++) { switch(html->stack[i].tag) { case EM: case ITALIC: case CITE: case DFN: case ADDRESS: return 0; case BOLD: case STRONG: flag = 1; break; } } html_push_tag(html, VAR); html_set_font(html, NULL, 0, flag + 2); return 0;}/* * html_small() - <SMALL> tag */__inline int html_small (html_t *html, char *tag, html_tag_args *args, tag_type type) { DwStyle attr; DwStyleFont font; if(type == HTML_TAG_CLOSE) { html_pop_tag(html, SMALL); return 0; } attr = *(html->stack[html->stack_top].style); font = *(attr.font); html_push_tag(html, SMALL); html_set_font(html, "courier", font.size - 4.0, -1); return 0;}/* * html_em() - <EM> tag */__inline int html_em (html_t *html, char *tag, html_tag_args *args, tag_type type) { int i, flag; if(type == HTML_TAG_CLOSE) { html_pop_tag(html, EM); return 0; } /* We have to make sure that if we're inside some other font-modifying tag we don't * screw it up */ flag = 0; for(i = 0; i <= html->stack_top; i++) { switch(html->stack[i].tag) { case VAR: case ITALIC: case CITE: case ADDRESS: case DFN: return 0; case BOLD: case STRONG: flag += 1; break; } } html_push_tag(html, EM); html_set_font(html, NULL, 0, flag + 2); return 0;}/* * html_strong() - <STRONG> tag */__inline int html_strong (html_t *html, char *tag, html_tag_args *args, tag_type type) { int i, flag; if(type == HTML_TAG_CLOSE) { html_pop_tag(html, STRONG); return 0; } /* We have to make sure that if we're inside some other font-modifying tag we don't * screw it up */ flag = 0; for(i = 0; i <= html->stack_top; i++) { switch(html->stack[i].tag) { case BOLD: return 0; case ITALIC: case CITE: case EM: case DFN: flag += 2; break; } } html_push_tag(html, STRONG); html_set_font(html, NULL, 0, flag + 1); return 0;}/* * html_ul - <UL> tag */__inline int html_ul (html_t *html, char *tag, html_tag_args *args, tag_type type) { DwStyle style_attrs; if(type == HTML_TAG_CLOSE) { html_pop_tag(html, UL); return 0; } html_push_tag(html, UL); style_attrs = *(html->stack[html->stack_top].style); style_attrs.left_indent_rest += 40; style_attrs.left_indent_first = style_attrs.left_indent_rest; a_Dw_style_unref(html->stack[html->stack_top].style); html->stack[html->stack_top].style = a_Dw_style_new(&style_attrs, html->cw->window->window); return 0;}/* * html_sub() - <SUB> tag. */__inline int html_sub (html_t *html, char *tag, html_tag_args *args, tag_type type) { DwStyle style; if(type == HTML_TAG_CLOSE) { html_pop_tag(html, SUB); return 0; } html_push_tag(html, SUB); style = *(html->stack[html->stack_top].style); style.SubSup = TEXT_SUB; a_Dw_style_unref(html->stack[html->stack_top].style); html->stack[html->stack_top].style = a_Dw_style_new(&style, html->cw->window->window); return 0;}__inline int html_menu (html_t *html, char *tag, html_tag_args *args, tag_type type) { /* Deprecated. * * From W3C: * The DIR element was designed to be used for creating multicolumn directory lists. * The MENU element was designed to be used for single column menu lists. Both elements * have the same structure as UL, just different rendering. In practice, a user agent will * render a DIR or MENU list exactly as a UL list. */ html_ul(html, tag, args, type); return 0;}/* * html_base() - <BASE> tag */__inline int html_base (html_t *html, char *tag, html_tag_args *args, tag_type type) { html_tag_args *cur; /* W3C says base *MUST* be in <HEAD> */ if(html_seek_tag(html, HEAD) < 0) return -1; /* Find href attribute */ cur = args; while(cur) { if(strcasecmp(cur->name, "href") == 0) { if(html->baseuri) free(html->baseuri); html->baseuri = strdup(cur->value); } cur = cur->next; } return 0;}/* * html_dl() - <DL> tag */__inline int html_dl (html_t *html, char *tag, html_tag_args *args, tag_type type) { switch(type) { case HTML_TAG_OPEN: html_push_tag(html, DL); break; case HTML_TAG_CLOSE: html_pop_tag(html, DL); break; } return 0;}/* * html_blockquote() - <BLOCKQUOTE> tag. */__inline int html_blockquote (html_t *html, char *tag, html_tag_args *args, tag_type type) { DwStyle attr; if(type == HTML_TAG_CLOSE) { html_pop_tag(html, BLOCKQUOTE); return 0; } html_push_tag(html, BLOCKQUOTE); attr = *(html->stack[html->stack_top].style); attr.left_indent_rest += 40; attr.left_indent_first = attr.left_indent_rest; attr.right_indent += 40; a_Dw_style_unref(html->stack[html->stack_top].style); html->stack[html->stack_top].style = a_Dw_style_new(&attr, html->cw->window->window); return 0;}/* * html_strike() - <S>, <DEL> and <STRIKE> tags */__inline int html_strike (html_t *html, char *tag, html_tag_args *args, tag_type type) { DwStyle style_attrs; if(type == HTML_TAG_CLOSE) { html_pop_tag(html, STRIKE); return 0; } html_push_tag(html, STRIKE); style_attrs = *(html->stack[html->stack_top].style); style_attrs.strike = TRUE; a_Dw_style_unref (html->stack[html->stack_top].style); html->stack[html->stack_top].style = a_Dw_style_new(&style_attrs, html->cw->window->window); return 0;}/* * html_kbd() - <KBD> tag */__inline int html_kbd (html_t *html, char *tag, html_tag_args *args, tag_type type) { int i; if(type == HTML_TAG_CLOSE) { html_pop_tag(html, KBD); return 0; } for(i = 0; i <= html->stack_top; i++) { switch(html->stack[i].tag) { case CODE: case SAMP: return 0; } } html_push_tag(html, KBD); html_set_font(html, "courier", 0, -1); return 0;}/* * html_ol() - <OL> tag */__inline int html_ol (html_t *html, char *tag, html_tag_args *args, tag_type type) { DwStyle style_attrs; if(type == HTML_TAG_CLOSE) { html_pop_tag(html, OL); return 0; } list_num = 0; html_push_tag(html, OL); style_attrs = *( html->stack[html->stack_top].style ); style_attrs.left_indent_rest += 40;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -