📄 html.c
字号:
/* * File: html.c * * Copyright (C) 1997 Raph Levien <raph@acm.org> * Copyright (C) 1999 James McCollough <jamesm@gtwn.net> * Copyright (C) 2000-2004 Jorge Arellano Cid <jcid@dillo.org> * * 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 of the License, or * (at your option) any later version. *//* * Dillo HTML parsing routines */#define USE_TABLES#include <ctype.h> /* for isspace and tolower */#include <string.h> /* for memcpy and memmove */#include <stdlib.h>#include <stdio.h> /* for sprintf */#include <math.h> /* for rint */#include <gtk/gtk.h>#include "msg.h"#include "list.h"#include "binaryconst.h"#include "colors.h"#include "dillo.h"#include "history.h"#include "nav.h"#include "menu.h"#include "commands.h"#include "dw.h" /* for Dw_cursor_hand */#include "dw_gtk_viewport.h"#include "dw_gtk_scrolled_window.h"#include "dw_widget.h"#include "dw_page.h"#include "dw_bullet.h"#include "dw_button.h"#include "dw_hruler.h"#include "dw_embed_gtk.h"#include "dw_table.h"#include "dw_table_cell.h"#include "dw_list_item.h"#include "IO/IO.h"#include "IO/Url.h"#include "interface.h"#include "progressbar.h"#include "prefs.h"#include "misc.h"#include "capi.h"#include "html.h"#define DEBUG_LEVEL 10#include "debug.h"typedef void (*TagFunct) (DilloHtml *Html, char *Tag, gint Tagsize);#define TAB_SIZE 8/* * Forward declarations */static const char *Html_get_attr(DilloHtml *html, const char *tag, gint tagsize, const char *attrname);static const char *Html_get_attr2(DilloHtml *html, const char *tag, gint tagsize, const char *attrname, DilloHtmlTagParsingFlags flags);static char *Html_get_attr_wdef(DilloHtml *html, const char *tag, gint tagsize, const char *attrname, const char *def);static void Html_add_widget(DilloHtml *html, DwWidget *widget, char *width_str, char *height_str, DwStyle *style_attrs);static void Html_write(DilloHtml *html, char *Buf, gint BufSize, gint Eof);static void Html_close(DilloHtml *html, gint ClientKey);static void Html_callback(int Op, CacheClient_t *Client);static DilloHtml *Html_new(BrowserWindow *bw, const DilloUrl *url);static void Html_tag_open_input(DilloHtml *html, char *tag, gint tagsize);static void Html_add_input(DilloHtmlForm *form, DilloHtmlInputType type, GtkWidget *widget, const char *name, const char *init_str, DilloHtmlSelect *select, gboolean init_val);static void Html_submit_form(GtkWidget *submit, DilloHtmlLB *html_lb, gint click_x, gint click_y);static void Html_reset_form(GtkWidget *reset, DilloHtmlLB *html_lb);static gchar* Html_tags_get_name(gint tag_idx);static gchar Html_tags_get_endtag(gint tag_idx);static gint Html_tag_index(char *tag);/* * Local Data *//* The following array of font sizes has to be _strictly_ crescent */static const gint FontSizes[] = {8, 10, 12, 14, 18, 24};static const gint FontSizesNum = 6;static const gint FontSizesBase = 2;/* * Return the line number of the tag being processed by the parser. */gint Html_get_line_number(DilloHtml *html){ gint i, ofs, line; const char *p = html->Start_Buf; g_return_val_if_fail(p != NULL, -1); ofs = html->CurrTagOfs; line = html->OldTagLine; for (i = html->OldTagOfs; i < ofs; ++i) if (p[i] == '\n') ++line; html->OldTagOfs = html->CurrTagOfs; html->OldTagLine = line; return line;}/* * Collect HTML error strings inside the linkblock. */void Html_msg(DilloHtml *html, const char *format, ... ){ va_list argp; gchar buf[512]; g_snprintf(buf, 512, "HTML warning: line %d, ", Html_get_line_number(html)); g_string_append(html->linkblock->page_bugs, buf); va_start(argp, format); vsnprintf(buf, 512, format, argp); va_end(argp); g_string_append(html->linkblock->page_bugs, buf); a_Interface_bug_meter_update(html->bw, ++html->linkblock->num_page_bugs);}/* * Wrapper for a_Url_new that adds an error detection message. * (if use_base_url is TRUE, html->linkblock->base_url is used) */static DilloUrl *Html_url_new(DilloHtml *html, const gchar *url_str, const gchar *base_url, gint flags, gint32 posx, gint32 posy, gint use_base_url){ DilloUrl *url; gint n_ic; url = a_Url_new( url_str, (use_base_url) ? base_url : URL_STR_(html->linkblock->base_url), flags, posx, posy); if ((n_ic = URL_ILLEGAL_CHARS(url)) != 0) MSG_HTML("URL has %d illegal character%s [00-1F, 7F or space]\n", n_ic, (n_ic) > 1 ? "s" : ""); return url;}/* * Set callback function and callback data for "html/text" MIME type. */DwWidget *a_Html_text(const char *Type, void *P, CA_Callback_t *Call, void **Data){ DilloWeb *web = P; DilloHtml *html = Html_new(web->bw, web->url); *Data = (void *) html; *Call = (CA_Callback_t) Html_callback; return html->dw;}/* * We'll make the linkblock first to get it out of the way. */static DilloHtmlLB *Html_lb_new(BrowserWindow *bw, const DilloUrl *url){ DilloHtmlLB *html_lb = g_new(DilloHtmlLB, 1); html_lb->bw = bw; html_lb->base_url = a_Url_dup(url); html_lb->num_forms_max = 1; html_lb->num_forms = 0; html_lb->forms = NULL; html_lb->num_links_max = 1; html_lb->num_links = 0; html_lb->links = NULL; a_Dw_image_map_list_init(&html_lb->maps); html_lb->link_color = prefs.link_color; html_lb->visited_color = prefs.visited_color; html_lb->num_page_bugs = 0; html_lb->page_bugs = g_string_new(""); return html_lb;}/* * Free the memory used by the linkblock */static void Html_lb_free(void *lb){ gint i, j, k; DilloHtmlForm *form; DilloHtmlLB *html_lb = lb; DEBUG_MSG(3, "Html_lb_free\n"); a_Url_free(html_lb->base_url); for (i = 0; i < html_lb->num_forms; i++) { form = &html_lb->forms[i]; a_Url_free(form->action); for (j = 0; j < form->num_inputs; j++) { g_free(form->inputs[j].name); g_free(form->inputs[j].init_str); if (form->inputs[j].type == DILLO_HTML_INPUT_SELECT || form->inputs[j].type == DILLO_HTML_INPUT_SEL_LIST) { for (k = 0; k < form->inputs[j].select->num_options; k++) { g_free(form->inputs[j].select->options[k].value); } g_free(form->inputs[j].select->options); g_free(form->inputs[j].select); } } g_free(form->inputs); } g_free(html_lb->forms); for (i = 0; i < html_lb->num_links; i++) if (html_lb->links[i]) a_Url_free(html_lb->links[i]); g_free(html_lb->links); a_Dw_image_map_list_free(&html_lb->maps); g_string_free(html_lb->page_bugs, TRUE); g_free(html_lb);}/* * Set the URL data for image maps. */static void Html_set_link_coordinates(DilloHtmlLB *lb, gint link, gint x, gint y){ gchar data[64]; if (x != -1) { g_snprintf(data, 64, "?%d,%d", x, y); a_Url_set_ismap_coords(lb->links[link], data); }}/* * Handle the status function generated by the dw scroller, * and show the url in the browser status-bar. */static void Html_handle_status(DwWidget *widget, gint link, gint x, gint y, DilloHtmlLB *lb){ DilloUrl *url; url = (link == -1) ? NULL : lb->links[link]; if (url) { Html_set_link_coordinates(lb, link, x, y); a_Interface_msg(lb->bw, "%s", URL_ALT_(url) ? URL_ALT_(url) : URL_STR_(url)); a_Dw_widget_set_cursor (widget, Dw_cursor_hand); lb->bw->status_is_link = 1; } else { if (lb->bw->status_is_link) a_Interface_msg(lb->bw, ""); a_Dw_widget_set_cursor (widget, NULL); }}/* * Popup the link menu ("link_pressed" callback of the page) */static gboolean Html_link_menu(DwWidget *widget, gint link, gint x, gint y, GdkEventButton *event, DilloHtmlLB *lb){ DwWidget *widget_at_cursor; gboolean show_oi = FALSE; if (event->button == 3) { Html_set_link_coordinates(lb, link, x, y); a_Menu_popup_set_url(lb->bw, lb->links[link]); /* if we've got an image, prepare the image popup */ widget_at_cursor = a_Dw_gtk_scrolled_window_widget_at_viewport_point( GTK_DW_SCROLLED_WINDOW (lb->bw->docwin), event->x, event->y); if (widget_at_cursor && DW_IS_IMAGE (widget_at_cursor)) { DwImage *image = DW_IMAGE (widget_at_cursor); /* test image->url (it may have not started to arrive yet!) */ if (image->url) { /* use the second URL for this popup */ gtk_object_set_data(GTK_OBJECT (lb->bw->menu_popup.over_image), "url2", GINT_TO_POINTER(2)); a_Menu_popup_set_url2(lb->bw, image->url); show_oi = TRUE; } } a_Menu_popup_ol_show_oi(lb->bw, show_oi); gtk_menu_popup(GTK_MENU(lb->bw->menu_popup.over_link), NULL, NULL, NULL, NULL, event->button, event->time); return TRUE; } return FALSE;}/* * Activate a link ("link_clicked" callback of the page) */static gboolean Html_link_clicked(DwWidget *widget, gint link, gint x, gint y, GdkEventButton *event, DilloHtmlLB *lb){ Html_set_link_coordinates(lb, link, x, y); if (event->button == 1) a_Nav_push(lb->bw, lb->links[link]); else if (event->button == 2) { a_Nav_push_nw(lb->bw, lb->links[link]); } else { return FALSE; } if (DW_IS_PAGE (widget)) a_Dw_page_change_link_color (DW_PAGE (widget), link, lb->visited_color); return TRUE;}/* * Popup the image menu ("button_press_event" callback of image) */static gboolean Html_image_menu(DwWidget *widget, gint32 x, gint32 y, GdkEventButton *event, BrowserWindow *bw){ DwImage *image = DW_IMAGE (widget); if (event->button == 3 && image->url) { a_Menu_popup_set_url(bw, image->url); gtk_menu_popup(GTK_MENU(bw->menu_popup.over_image), NULL, NULL, NULL, NULL, event->button, event->time); return TRUE; } return FALSE;}/* * Popup the page menu ("button_press_event" callback of the viewport) */static int Html_page_menu(GtkWidget *viewport, GdkEventButton *event, BrowserWindow *bw){ gpointer bug_pix; if (event->button == 3) { /* set the working URL */ a_Menu_popup_set_url(bw, a_History_get_url(NAV_TOP(bw))); /* set "View page Bugs" sensitivity */ bug_pix = gtk_object_get_data(GTK_OBJECT(bw->status_bug_meter), "bug"); gtk_widget_set_sensitive(bw->viewbugs_menuitem, GTK_WIDGET_VISIBLE(GTK_WIDGET(bug_pix))); gtk_menu_popup(GTK_MENU(bw->menu_popup.over_page), NULL, NULL, NULL, NULL, event->button, event->time); return TRUE; } else return FALSE;}/* * Connect all signals of a page or an image. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -