📄 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 <stdlib.h>#include <glib.h>#include <glib-object.h>#include "msg.h"#include "list.h"#include "dw_page.h"#include "dw_marshal.h"#include "dw_viewport.h"#include "prefs.h"#include "dw_table.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_finalize (GObject *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, HDC hdc, DwRectangle *area);static gboolean Dw_page_button_press (DwWidget *widget, gint32 x, gint32 y, DWORD flags);static gboolean Dw_page_button_release(DwWidget *widget, gint32 x, gint32 y, DWORD flags);static gboolean Dw_page_motion_notify (DwWidget *widget, gint32 x, gint32 y, DWORD flags);static gboolean Dw_page_leave_notify (DwWidget *widget, DwWidget *next_widget, DWORD flags);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) \ ((DW_PAGE_GET_CLASS(page))->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 */GType a_Dw_page_get_type (void){ static GType type = 0; if (!type) { static const GTypeInfo info = { sizeof (DwPageClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) Dw_page_class_init, (GClassFinalizeFunc) NULL, (gconstpointer) NULL, sizeof (DwPage), 0, (GInstanceInitFunc) Dw_page_init }; type = g_type_register_static (DW_TYPE_CONTAINER, "DwPage", &info, 0); } return type;}/* * Create a new DwPage */DwWidget* a_Dw_page_new (void){ GObject *object; object = g_object_new (DW_TYPE_PAGE, NULL); return DW_WIDGET (object);}/* * Initialize a DwPage */static void Dw_page_init (DwPage *page){ DBG_OBJ_CREATE (page, "DwPage"); 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;}/* * Initialize the DwPage's class */static void Dw_page_class_init (DwPageClass *klass){ GObjectClass *object_class; DwWidgetClass *widget_class; DwContainerClass *container_class; object_class = (GObjectClass*) klass; widget_class = (DwWidgetClass*) klass; container_class = (DwContainerClass*) klass; parent_class = g_type_class_peek_parent (klass); page_signals[LINK_ENTERED] = g_signal_new ("link_entered", G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (DwPageClass, link_entered), NULL, NULL, p_Dw_marshal_link_enter, G_TYPE_BOOLEAN, 3, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT); page_signals[LINK_PRESSED] = g_signal_new ("link_pressed", G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (DwPageClass, link_pressed), NULL, NULL, p_Dw_marshal_link_button, G_TYPE_BOOLEAN, 4, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_UINT); page_signals[LINK_RELEASED] = g_signal_new ("link_released", G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (DwPageClass, link_released), NULL, NULL, p_Dw_marshal_link_button, G_TYPE_BOOLEAN, 4, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_UINT); page_signals[LINK_CLICKED] = g_signal_new ("link_clicked", G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (DwPageClass, link_clicked), NULL, NULL, p_Dw_marshal_link_button, G_TYPE_BOOLEAN, 4, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_UINT); object_class->finalize = Dw_page_finalize; 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 GObject function) */static void Dw_page_finalize (GObject *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) g_object_unref (G_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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -