📄 dw_page.c
字号:
/* * File: dw_page.c * * Copyright (C) 1997 Raph Levien <raph@acm.org> * Copyright (C) 1999 Luca Rota <drake@freemail.it> * Copyright (C) 2001-2003 Sebastian Geerken <s.geerken@ping.de> * * 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 "msg.h"#include "list.h"#include "dw_page.h"#include "dw_marshal.h"#include "dw_gtk_viewport.h"#include "prefs.h"#define DEBUG_REWRAP_LEVEL 0#define DEBUG_SIZE_LEVEL 10#define DEBUG_EVENT_LEVEL 0#define DEBUG_ITERATOR_LEVEL 0/*#define DEBUG_LEVEL 10*/#include "debug.h"#define MAX3(a, b, c) (MAX (a, MAX (b, c)))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 gboolean Dw_page_button_press (DwWidget *widget, gint32 x, gint32 y, GdkEventButton *event);static gboolean Dw_page_button_release(DwWidget *widget, gint32 x, gint32 y, GdkEventButton *event);static gboolean Dw_page_motion_notify (DwWidget *widget, gint32 x, gint32 y, GdkEventMotion *event);static gboolean 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 void Dw_page_real_word_wrap (DwPage *page, gint word_ind);static DwIterator* Dw_page_iterator (DwWidget *widget, gint mask, gboolean at_end);static gboolean Dw_page_iterator_next (DwIterator *it);static gboolean Dw_page_iterator_prev (DwIterator *it);static void Dw_page_iterator_highlight (DwIterator *it, gint start, gint end, DwHighlightLayer layer);static void Dw_page_iterator_get_allocation (DwIterator *it, gint start, gint end, DwAllocation *allocation);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_eff : 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) )/* * Returns the y offset (within the widget) of a line. */#define Dw_page_line_total_y_offset(page, line) \ Dw_page_line_total_y_offset_allocation(page, line, \ &((DwWidget*)(page))->allocation)/* * Like Dw_page_line_total_y_offset, but with the allocation as parameter. */#define Dw_page_line_total_y_offset_allocation(page, line, allocation) \ ( (allocation)->ascent - (page)->lines[0].ascent + (line)->top )/* * Similar to Dw_page_line_total_y_offset. */#define Dw_page_line_total_y_offset_i(page, line_index) \ Dw_page_line_total_y_offset(page, &(page)->lines[line_index])#define Dw_page_word_wrap(page, word_ind) \ (((DwPageClass*)(((GtkObject*)(page))->klass))->word_wrap (page, word_ind))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); DBG_OBJ_CREATE (object, "DwPage"); 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; page->line1_offset_eff = 0; page->ignore_line1_offset_sometimes = FALSE; /* * 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); */ DBG_OBJ_SET_NUM(page, "num_lines", page->num_lines); 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->last_line_par_min = 0; page->last_line_par_max = 0; page->wrap_ref = -1; DBG_OBJ_SET_NUM(page, "last_line_width", page->last_line_width); DBG_OBJ_SET_NUM(page, "last_line_par_min", page->last_line_par_min); DBG_OBJ_SET_NUM(page, "last_line_par_max", page->last_line_par_max); DBG_OBJ_SET_NUM(page, "wrap_ref", page->wrap_ref); page->hover_link = -1; /* random values */ page->avail_width = 100; page->avail_ascent = 100; page->avail_descent = 0; page->hover_tooltip = NULL;}/* * 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); page_signals[LINK_ENTERED] = gtk_signal_new ("link_entered", GTK_RUN_LAST, object_class->type, GTK_SIGNAL_OFFSET (DwPageClass, link_entered), p_Dw_marshal_link_enter, GTK_TYPE_BOOL, 3, GTK_TYPE_INT, GTK_TYPE_INT, GTK_TYPE_INT); page_signals[LINK_PRESSED] = gtk_signal_new ("link_pressed", GTK_RUN_LAST, object_class->type, GTK_SIGNAL_OFFSET (DwPageClass, link_pressed), p_Dw_marshal_link_button, GTK_TYPE_BOOL, 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_LAST, object_class->type, GTK_SIGNAL_OFFSET (DwPageClass, link_released), p_Dw_marshal_link_button, GTK_TYPE_BOOL, 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_LAST, object_class->type, GTK_SIGNAL_OFFSET (DwPageClass, link_clicked), p_Dw_marshal_link_button, GTK_TYPE_BOOL, 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; widget_class->iterator = Dw_page_iterator; container_class->add = Dw_page_add; container_class->remove = Dw_page_remove; container_class->forall = Dw_page_forall; klass->link_entered = NULL; klass->link_pressed = NULL; klass->link_released = NULL; klass->link_clicked = NULL; klass->word_wrap = Dw_page_real_word_wrap;}/* * 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_CONTENT_WIDGET) gtk_object_unref (GTK_OBJECT(word->content.data.widget)); else if (word->content.type == DW_CONTENT_TEXT) g_free (word->content.data.text); else if (word->content.type == DW_CONTENT_ANCHOR) g_free (word->content.data.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; DBG_OBJ_SET_NUM(page, "num_lines", page->num_lines); GTK_OBJECT_CLASS(parent_class)->destroy (object);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -