📄 selection.c
字号:
/* * File: selection.c * * Copyright 2003 Sebastian Geerken <s.geerken@ping.de>, * Eric Gaudet <eric@rti-zone.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. *//* * See doc/Selection.txt for informations about this module. */#include "selection.h"#include "strbuf.h"#include "dw_gtk_viewport.h"#include <stdio.h>#include <string.h>#include <gtk/gtk.h>/*#define DEBUG_LEVEL 2*/#include "debug.h"static void Selection_reset_selection (Selection *selection);static void Selection_reset_link (Selection *selection);static void Selection_switch_link_to_selection (Selection *selection, DwIterator *it, gint32 char_pos);static void Selection_adjust_selection (Selection *selection, DwIterator *it, gint32 char_pos);static gint Selection_correct_char_pos (DwExtIterator *it, gint32 char_pos);static void Selection_highlight (Selection *selection, gboolean fl);static void Selection_highlight0 (gboolean fl, DwExtIterator *from, gint from_char, DwExtIterator *to, gint to_char);static void Selection_copy (Selection *selection);/* Not defined as static, to avoid compiler warnings. */char *selection_state_descr[] = { "none", "selecting", "selected" };Selection *a_Selection_new (void){ Selection *selection; selection = g_new (Selection, 1); selection->selection_state = SELECTION_NONE; selection->from = NULL; selection->to = NULL; selection->link_state = SELECTION_LINK_NONE; selection->link = NULL; selection->dclick_callback = NULL; selection->callback_data = NULL; selection->owner = NULL; return selection;}/* * Sets a callback function for double click, this is normally * the function toggling the full screen mode. * (More than one is never needed, so this instead of a signal.) */void a_Selection_set_dclick_callback (Selection *selection, void (*fn) (gpointer data), gpointer data){ g_return_if_fail (selection->dclick_callback == NULL); selection->dclick_callback = fn; selection->callback_data = data;}/* * Set the widget that owns the selection. */void a_Selection_set_owner(Selection *selection, gpointer owner){ selection->owner = owner; a_Selection_init_selection(owner);}void a_Selection_reset (Selection *selection){ Selection_reset_selection (selection); Selection_reset_link (selection);}void a_Selection_free (Selection *selection){ a_Selection_reset (selection); g_free (selection);}static void Selection_reset_selection (Selection *selection){ if (selection->from) a_Dw_ext_iterator_free(selection->from); selection->from = NULL; if (selection->to) a_Dw_ext_iterator_free(selection->to); selection->to = NULL; selection->selection_state = SELECTION_NONE;}static void Selection_reset_link (Selection *selection){ if (selection->link) a_Dw_ext_iterator_free(selection->link); selection->link = NULL; selection->link_state = SELECTION_LINK_NONE;}gint a_Selection_button_press (Selection *selection, DwIterator *it, gint char_pos, gint link, GdkEventButton *event, gboolean within_content){ DwWidget *it_widget = it->widget; gboolean ret = FALSE, dummy; DEBUG_MSG (3, "PRESS%s(%s, %d, %d): %s -> ...\n", (event && event->type == GDK_2BUTTON_PRESS) ? "2" : "", a_Dw_iterator_text (it), char_pos, link, selection_state_descr[selection->selection_state]);#if defined (DEBUG_LEVEL) && 1 >= DEBUG_LEVEL a_Dw_widget_print_tree (GTK_DW_VIEWPORT(it->widget->viewport)->child);#endif if (event && event->button == 1 && !within_content && event->type == GDK_2BUTTON_PRESS) { /* When the user double-clicks on empty parts, call the callback * function instead of normal processing. Used for full screen * mode. */ if (selection->dclick_callback) selection->dclick_callback (selection->callback_data); /* Reset everything, so that a_Selection_release will ignore the * "release" event following soon. */ Selection_highlight (selection, FALSE); a_Selection_reset (selection); ret = TRUE; } else { if (link != -1) { /* link handling */ if (event) { gtk_signal_emit_by_name (GTK_OBJECT (it_widget), "link_pressed", link, -1, -1, event, &dummy); Selection_reset_link (selection); selection->link_state = SELECTION_LINK_PRESSED; selection->link_button = event->button; selection->link = a_Dw_ext_iterator_new (it); /* It may be that the user has pressed on something activatable * (link != -1), but there is no contents, e.g. with images * without ALTernative text. */ if (selection->link) { selection->link_char = Selection_correct_char_pos (selection->link, char_pos); selection->link_number = link; } /* We do not return the value of the signal function (dummy), * but we do actually process this event. */ ret = TRUE; } } else { /* normal selection handling */ if (event && event->button == 1) { Selection_highlight (selection, FALSE); Selection_reset_selection (selection); selection->from = a_Dw_ext_iterator_new (it); /* a_Dw_ext_iterator_new may return NULL, if the page has no * contents. */ if (selection->from) { selection->selection_state = SELECTION_SELECTING; selection->from_char = Selection_correct_char_pos (selection->from, char_pos); selection->to = a_Dw_ext_iterator_clone (selection->from); selection->to_char = Selection_correct_char_pos (selection->to, char_pos); ret = TRUE; } else /* if there is no content */ ret = FALSE; } } } DEBUG_MSG (3, " ... -> %s, processed = %s\n", selection_state_descr[selection->selection_state], ret ? "TRUE" : "FALSE"); return ret;}gint a_Selection_button_release (Selection *selection, DwIterator *it, gint char_pos, gint link, GdkEventButton *event, gboolean within_content){ DwWidget *it_widget = it->widget; gboolean ret = FALSE, dummy; DEBUG_MSG (3, "RELEASE(%s, %d, %d): %s -> ...\n", a_Dw_iterator_text (it), char_pos, link, selection_state_descr[selection->selection_state]); if (selection->link_state == SELECTION_LINK_PRESSED && event && event->button == selection->link_button) { /* link handling */ ret = TRUE; if (link != -1) gtk_signal_emit_by_name (GTK_OBJECT (it_widget), "link_released", link, -1, -1, event, &dummy); /* The link where the user clicked the mouse button? */ if (link == selection->link_number) { Selection_reset_link (selection); gtk_signal_emit_by_name (GTK_OBJECT (it_widget), "link_clicked", link, -1, -1, event, &dummy); } else { if (event->button == 1) /* Reset links and switch to selection mode. The selection * state will be set to SELECTING, which is handled some lines * below. */ Selection_switch_link_to_selection (selection, it, char_pos); } } if (selection->selection_state == SELECTION_SELECTING && event && event->button == 1) { /* normal selection */ ret = TRUE; Selection_adjust_selection (selection, it, char_pos); if (a_Dw_ext_iterator_compare (selection->from, selection->to) == 0 && selection->from_char == selection->to_char) /* nothing selected */ Selection_reset_selection (selection); else { Selection_copy (selection); selection->selection_state = SELECTION_SELECTED; } } DEBUG_MSG (3, " ... -> %s, processed = %s\n", selection_state_descr[selection->selection_state], ret ? "TRUE" : "FALSE"); return ret;}gint a_Selection_button_motion (Selection *selection, DwIterator *it, gint char_pos, gint link, GdkEventButton *event, gboolean within_content){ DEBUG_MSG (3, "MOTION (%s, %d, %d): %s -> ...\n", a_Dw_iterator_text (it), char_pos, link, selection_state_descr[selection->selection_state]); if (selection->link_state == SELECTION_LINK_PRESSED) { /* link handling */ if (link != selection->link_number) /* No longer the link where the user clicked the mouse button. * Reset links and switch to selection mode. */ Selection_switch_link_to_selection (selection, it, char_pos); /* Still in link: do nothing. */ } else if (selection->selection_state == SELECTION_SELECTING) { /* selection */ Selection_adjust_selection (selection, it, char_pos); } DEBUG_MSG (3, " ... -> %s, processed = TRUE\n", selection_state_descr[selection->selection_state]); return TRUE;}/* * This function is called when the user decides not to activate a link, * but instead select text. */static void Selection_switch_link_to_selection (Selection *selection, DwIterator *it, gint32 char_pos){ /* It may be that selection->link is NULL, see a_Selection_button_press. */ if (selection->link) { /* Reset old selection. */ Selection_highlight (selection, FALSE); Selection_reset_selection (selection); /* Transfer link state into selection state. */ selection->from = a_Dw_ext_iterator_clone (selection->link); selection->from_char = selection->link_char; selection->to = a_Dw_ext_iterator_new_variant (selection->from, it); selection->to_char = Selection_correct_char_pos (selection->to, char_pos); selection->selection_state = SELECTION_SELECTING; /* Reset link status. */ Selection_reset_link (selection); Selection_highlight (selection, TRUE); DEBUG_MSG (2, " after switching: from (%s, %d) to (%s, %d)\n", a_Dw_ext_iterator_text (selection->from), selection->from_char, a_Dw_ext_iterator_text (selection->to), selection->to_char); } else { /* A link was pressed on, but there is nothing to select. Reset * everything. */ Selection_reset_selection (selection);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -