📄 dw_page.c
字号:
/* * File: dw_page.c * * Copyright (C) 1997 Raph Levien <raph@acm.org> * Copyright (C) 1999 Luca Rota <drake@freemail.it> * * 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. *//* * This module contains the Dw_page widget, which is the "back end" to * Web text widgets including html. */#include <ctype.h>#include <string.h>#include <stdio.h>#include <gtk/gtk.h>#include "list.h"#include "dw_page.h"#include "dw_marshal.h"#include "dw_gtk_viewport.h"#include "prefs.h"//#define DEBUG_LEVEL 2#include "debug.h"static void Dw_page_init (DwPage *page);static void Dw_page_class_init (DwPageClass *klass);static void Dw_page_destroy (GtkObject *object);static void Dw_page_size_request (DwWidget *widget, DwRequisition *requisition);static void Dw_page_get_extremes (DwWidget *widget, DwExtremes *extremes);static void Dw_page_size_allocate (DwWidget *widget, DwAllocation *allocation);static void Dw_page_mark_change (DwWidget *widget, gint ref);static void Dw_page_set_width (DwWidget *widget, gint32 width);static void Dw_page_set_ascent (DwWidget *widget, gint32 ascent);static void Dw_page_set_descent (DwWidget *widget, gint32 descent);static void Dw_page_draw (DwWidget *page, DwRectangle *area, GdkEventExpose *event);static gint Dw_page_button_press (DwWidget *widget, gint32 x, gint32 y, GdkEventButton *event);static gint Dw_page_button_release (DwWidget *widget, gint32 x, gint32 y, GdkEventButton *event);static gint Dw_page_motion_notify (DwWidget *widget, gint32 x, gint32 y, GdkEventMotion *event);static gint Dw_page_leave_notify (DwWidget *widget, DwWidget *next_widget, GdkEventMotion *event);static void Dw_page_add (DwContainer *container, DwWidget *widget);static void Dw_page_remove (DwContainer *container, DwWidget *widget);static void Dw_page_forall (DwContainer *container, DwCallback callback, gpointer callback_data);static gint Dw_page_findtext (DwContainer *container, gpointer FP, gpointer KP, gchar *NewKey);static void Dw_page_rewrap (DwPage *page);/* * Returns the x offset (the indentation plus any offset needed for * centering or right justification) for the line. The offset returned * is relative to the page *content* (i.e. without border etc.). */#define Dw_page_line_x_offset(page, line) \ ( (page)->inner_padding + (line)->left_offset + \ ((line) == (page)->lines ? (page)->line1_offset : 0) )/* * Like Dw_style_box_offset_x, but relative to the allocation (i.e. * including border etc.). */#define Dw_page_line_total_x_offset(page, line) \ ( Dw_page_line_x_offset (page, line) + \ p_Dw_style_box_offset_x (((DwWidget*)(page))->style) )enum{ LINK_ENTERED, LINK_PRESSED, LINK_RELEASED, LINK_CLICKED, LAST_SIGNAL};static DwContainerClass *parent_class;static guint page_signals[LAST_SIGNAL] = { 0 };/* * Return the type of DwPage */GtkType a_Dw_page_get_type (void){ static GtkType type = 0; if (!type) { GtkTypeInfo info = { "DwPage", sizeof (DwPage), sizeof (DwPageClass), (GtkClassInitFunc) Dw_page_class_init, (GtkObjectInitFunc) Dw_page_init, (GtkArgSetFunc) NULL, (GtkArgGetFunc) NULL, (GtkClassInitFunc) NULL }; type = gtk_type_unique (DW_TYPE_CONTAINER, &info); } return type;}/* * Create a new DwPage */DwWidget* a_Dw_page_new (void){ GtkObject *object; object = gtk_object_new (DW_TYPE_PAGE, NULL); return DW_WIDGET (object);}/* * Initialize a DwPage */static void Dw_page_init (DwPage *page){ DW_WIDGET_SET_FLAGS (page, DW_USES_HINTS); page->list_item = FALSE; page->inner_padding = 0; page->line1_offset = 0; /* * The initial sizes of page->lines and page->words should not be * too high, since this will waste much memory with tables * containing many small cells. The few more calls to realloc * should not decrease the speed considerably. * (Current setting is for minimal memory usage. An interesting fact * is that high values decrease speed due to memory handling overhead!) * todo: Some tests would be useful. */ page->num_lines_max = 1; /* 2 */ page->num_lines = 0; page->lines = NULL; /* g_new(DwPageLine, page->num_lines_max); */ page->num_words_max = 1; /* 8 */ page->num_words = 0; page->words = NULL; /* g_new(DwPageWord, page->num_words_max); */ page->last_line_width = 0; page->wrap_ref = -1; page->hover_link = -1; /* random values */ page->avail_width = 100; page->avail_ascent = 100; page->avail_descent = 0;}/* * Initialize the DwPage's class */static void Dw_page_class_init (DwPageClass *klass){ GtkObjectClass *object_class; DwWidgetClass *widget_class; DwContainerClass *container_class; object_class = (GtkObjectClass*) klass; widget_class = (DwWidgetClass*) klass; container_class = (DwContainerClass*) klass; parent_class = gtk_type_class (DW_TYPE_CONTAINER); /* todo: the link_xxx signals should return boolean values, which are * then returned by the event signal function of DwPage. But I don't * know that much about Gtk+ signals :-( * --SG */ page_signals[LINK_ENTERED] = gtk_signal_new ("link_entered", GTK_RUN_FIRST, object_class->type, GTK_SIGNAL_OFFSET (DwPageClass, link_entered), p_Dw_marshal_link_enter, GTK_TYPE_NONE, 3, GTK_TYPE_INT, GTK_TYPE_INT, GTK_TYPE_INT); page_signals[LINK_PRESSED] = gtk_signal_new ("link_pressed", GTK_RUN_FIRST, object_class->type, GTK_SIGNAL_OFFSET (DwPageClass, link_pressed), p_Dw_marshal_link_button, GTK_TYPE_NONE, 4, GTK_TYPE_INT, GTK_TYPE_INT, GTK_TYPE_INT, GTK_TYPE_GDK_EVENT); page_signals[LINK_RELEASED] = gtk_signal_new ("link_released", GTK_RUN_FIRST, object_class->type, GTK_SIGNAL_OFFSET (DwPageClass, link_released), p_Dw_marshal_link_button, GTK_TYPE_NONE, 4, GTK_TYPE_INT, GTK_TYPE_INT, GTK_TYPE_INT, GTK_TYPE_GDK_EVENT); page_signals[LINK_CLICKED] = gtk_signal_new ("link_clicked", GTK_RUN_FIRST, object_class->type, GTK_SIGNAL_OFFSET (DwPageClass, link_clicked), p_Dw_marshal_link_button, GTK_TYPE_NONE, 4, GTK_TYPE_INT, GTK_TYPE_INT, GTK_TYPE_INT, GTK_TYPE_GDK_EVENT); gtk_object_class_add_signals (object_class, page_signals, LAST_SIGNAL); object_class->destroy = Dw_page_destroy; widget_class->size_request = Dw_page_size_request; widget_class->get_extremes = Dw_page_get_extremes; widget_class->size_allocate = Dw_page_size_allocate; widget_class->mark_size_change = Dw_page_mark_change; widget_class->mark_extremes_change = Dw_page_mark_change; widget_class->set_width = Dw_page_set_width; widget_class->set_ascent = Dw_page_set_ascent; widget_class->set_descent = Dw_page_set_descent; widget_class->draw = Dw_page_draw; widget_class->button_press_event = Dw_page_button_press; widget_class->button_release_event = Dw_page_button_release; widget_class->motion_notify_event = Dw_page_motion_notify; widget_class->leave_notify_event = Dw_page_leave_notify; container_class->add = Dw_page_add; container_class->remove = Dw_page_remove; container_class->forall = Dw_page_forall; container_class->findtext = Dw_page_findtext; klass->link_entered = NULL; klass->link_pressed = NULL; klass->link_released = NULL; klass->link_clicked = NULL;}/* * Destroy the page (standard Gtk+ function) */static void Dw_page_destroy (GtkObject *object){ DwPage *page = DW_PAGE (object); DwPageWord *word; gint i; DEBUG_MSG(10, "Dw_page_destroy\n"); for (i = 0; i < page->num_words; i++) { word = &page->words[i]; if (word->content_type == DW_PAGE_CONTENT_WIDGET) gtk_object_unref(GTK_OBJECT(word->content.widget)); else if (word->content_type == DW_PAGE_CONTENT_TEXT) g_free(word->content.text); else if (word->content_type == DW_PAGE_CONTENT_ANCHOR) g_free(word->content.anchor); a_Dw_style_unref (word->style); a_Dw_style_unref (word->space_style); } g_free (page->lines); g_free (page->words); /* Make sure we don't own widgets anymore. Necessary before call of parent_class->destroy. */ page->num_words = 0; page->num_lines = 0; (* GTK_OBJECT_CLASS(parent_class)->destroy) (object);}/* * Standard Dw function * * The ascent of a page is the ascent of the first line, plus * padding/border/margin. This can be used to align the first lines * of several pages in a horizontal line. */static void Dw_page_size_request (DwWidget *widget, DwRequisition *requisition){ DwPage *page = DW_PAGE (widget); DwPageLine *last_line; gint height; Dw_page_rewrap(page); if (page->num_lines > 0) { last_line = &page->lines[page->num_lines - 1]; requisition->width = MAX (last_line->max_line_width, page->last_line_width); /* Note: the break_space of the last line is ignored, so breaks at the end of a page are not visible. */ height = last_line->top + last_line->ascent + last_line->descent + p_Dw_style_box_rest_height (widget->style); requisition->ascent = page->lines[0].top + page->lines[0].ascent; requisition->descent = height - requisition->ascent; } else { requisition->width = page->last_line_width; requisition->ascent = p_Dw_style_box_offset_y (widget->style); requisition->descent = p_Dw_style_box_rest_height (widget->style); } requisition->width += page->inner_padding + p_Dw_style_box_diff_width (widget->style); if (requisition->width < page->avail_width) requisition->width = page->avail_width;}/* * Get the extremes of a word within a page. */static void Dw_page_get_word_extremes (DwPageWord *word, DwExtremes *extremes){ if (word->content_type == DW_PAGE_CONTENT_WIDGET) { if (DW_WIDGET_USES_HINTS (word->content.widget)) a_Dw_widget_get_extremes (word->content.widget, extremes); else { if (DW_STYLE_IS_PERCENTAGE (word->content.widget->style->width)) { extremes->min_width = 0; if (DW_WIDGET_HAS_CONTENT (word->content.widget)) extremes->max_width = DW_INFINITY; else extremes->max_width = 0; } else if (DW_STYLE_IS_LENGTH (word->content.widget->style->width)) { extremes->min_width = extremes->max_width = DW_STYLE_GET_LENGTH(word->content.widget->style->width, word->style->font); } else a_Dw_widget_get_extremes (word->content.widget, extremes); } } else { extremes->min_width = word->size.width; extremes->max_width = word->size.width; }}/* * Standard Dw function */static void Dw_page_get_extremes (DwWidget *widget, DwExtremes *extremes){ DwPage *page = DW_PAGE (widget); DwExtremes word_extremes; DwPageLine *line; DwPageWord *word; gint word_index, line_index; gint32 par_min, par_max; gboolean nowrap; DEBUG_MSG (4, "Dw_page_get_extremes\n"); if (page->num_lines == 0) { /* empty page */ extremes->min_width = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -