📄 gtktext.c
字号:
/* GTK - The GIMP Toolkit * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. *//* * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS * file for a list of people on the GTK+ Team. See the ChangeLog * files for a list of changes. These files are distributed with * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */#include <ctype.h>#include <string.h>#include "gdk/gdkkeysyms.h"#include "gdk/gdki18n.h"#include "gtkmain.h"#include "gtkselection.h"#include "gtksignal.h"#include "gtktext.h"#include "line-wrap.xbm"#include "line-arrow.xbm"#define INITIAL_BUFFER_SIZE 1024#define INITIAL_LINE_CACHE_SIZE 256#define MIN_GAP_SIZE 256#define LINE_DELIM '\n'#define MIN_TEXT_WIDTH_LINES 20#define MIN_TEXT_HEIGHT_LINES 10#define TEXT_BORDER_ROOM 1#define LINE_WRAP_ROOM 8 /* The bitmaps are 6 wide. */#define DEFAULT_TAB_STOP_WIDTH 4#define SCROLL_PIXELS 5#define KEY_SCROLL_PIXELS 10#define SCROLL_TIME 100#define FREEZE_LENGTH 1024 /* Freeze text when inserting or deleting more than this many characters */#define SET_PROPERTY_MARK(m, p, o) do { \ (m)->property = (p); \ (m)->offset = (o); \ } while (0)#define MARK_CURRENT_PROPERTY(mark) ((TextProperty*)(mark)->property->data)#define MARK_NEXT_PROPERTY(mark) ((TextProperty*)(mark)->property->next->data)#define MARK_PREV_PROPERTY(mark) ((TextProperty*)((mark)->property->prev ? \ (mark)->property->prev->data \ : NULL))#define MARK_PREV_LIST_PTR(mark) ((mark)->property->prev)#define MARK_LIST_PTR(mark) ((mark)->property)#define MARK_NEXT_LIST_PTR(mark) ((mark)->property->next)#define MARK_OFFSET(mark) ((mark)->offset)#define MARK_PROPERTY_LENGTH(mark) (MARK_CURRENT_PROPERTY(mark)->length)#define MARK_CURRENT_FONT(text, mark) \ ((MARK_CURRENT_PROPERTY(mark)->flags & PROPERTY_FONT) ? \ MARK_CURRENT_PROPERTY(mark)->font->gdk_font : \ GTK_WIDGET (text)->style->font)#define MARK_CURRENT_FORE(text, mark) \ ((MARK_CURRENT_PROPERTY(mark)->flags & PROPERTY_FOREGROUND) ? \ &MARK_CURRENT_PROPERTY(mark)->fore_color : \ &((GtkWidget *)text)->style->text[((GtkWidget *)text)->state])#define MARK_CURRENT_BACK(text, mark) \ ((MARK_CURRENT_PROPERTY(mark)->flags & PROPERTY_BACKGROUND) ? \ &MARK_CURRENT_PROPERTY(mark)->back_color : \ &((GtkWidget *)text)->style->base[((GtkWidget *)text)->state])#define MARK_CURRENT_TEXT_FONT(text, mark) \ ((MARK_CURRENT_PROPERTY(mark)->flags & PROPERTY_FONT) ? \ MARK_CURRENT_PROPERTY(mark)->font : \ text->current_font)#define TEXT_LENGTH(t) ((t)->text_end - (t)->gap_size)#define FONT_HEIGHT(f) ((f)->ascent + (f)->descent)#define LINE_HEIGHT(l) ((l).font_ascent + (l).font_descent)#define LINE_CONTAINS(l, i) ((l).start.index <= (i) && (l).end.index >= (i))#define LINE_STARTS_AT(l, i) ((l).start.index == (i))#define LINE_START_PIXEL(l) ((l).tab_cont.pixel_offset)#define LAST_INDEX(t, m) ((m).index == TEXT_LENGTH(t))#define CACHE_DATA(c) (*(LineParams*)(c)->data)enum { ARG_0, ARG_HADJUSTMENT, ARG_VADJUSTMENT, ARG_LINE_WRAP, ARG_WORD_WRAP};typedef struct _TextProperty TextProperty;typedef struct _TabStopMark TabStopMark;typedef struct _PrevTabCont PrevTabCont;typedef struct _FetchLinesData FetchLinesData;typedef struct _LineParams LineParams;typedef struct _SetVerticalScrollData SetVerticalScrollData;typedef gint (*LineIteratorFunction) (GtkText* text, LineParams* lp, void* data);typedef enum{ FetchLinesPixels, FetchLinesCount} FLType;struct _SetVerticalScrollData { gint pixel_height; gint last_didnt_wrap; gint last_line_start; GtkPropertyMark mark;};struct _GtkTextFont{ /* The actual font. */ GdkFont *gdk_font; guint ref_count; gint16 char_widths[256];};typedef enum { PROPERTY_FONT = 1 << 0, PROPERTY_FOREGROUND = 1 << 1, PROPERTY_BACKGROUND = 1 << 2} TextPropertyFlags;struct _TextProperty{ /* Font. */ GtkTextFont* font; /* Background Color. */ GdkColor back_color; /* Foreground Color. */ GdkColor fore_color; /* Show which properties are set */ TextPropertyFlags flags; /* Length of this property. */ guint length;};struct _TabStopMark{ GList* tab_stops; /* Index into list containing the next tab position. If * NULL, using default widths. */ gint to_next_tab;};struct _PrevTabCont{ guint pixel_offset; TabStopMark tab_start;};struct _FetchLinesData{ GList* new_lines; FLType fl_type; gint data; gint data_max;};struct _LineParams{ guint font_ascent; guint font_descent; guint pixel_width; guint displayable_chars; guint wraps : 1; PrevTabCont tab_cont; PrevTabCont tab_cont_next; GtkPropertyMark start; GtkPropertyMark end;};static void gtk_text_class_init (GtkTextClass *klass);static void gtk_text_set_arg (GtkObject *object, GtkArg *arg, guint arg_id);static void gtk_text_get_arg (GtkObject *object, GtkArg *arg, guint arg_id);static void gtk_text_init (GtkText *text);static void gtk_text_destroy (GtkObject *object);static void gtk_text_finalize (GtkObject *object);static void gtk_text_realize (GtkWidget *widget);static void gtk_text_unrealize (GtkWidget *widget);static void gtk_text_style_set (GtkWidget *widget, GtkStyle *previous_style);static void gtk_text_draw_focus (GtkWidget *widget);static void gtk_text_size_request (GtkWidget *widget, GtkRequisition *requisition);static void gtk_text_size_allocate (GtkWidget *widget, GtkAllocation *allocation);static void gtk_text_adjustment (GtkAdjustment *adjustment, GtkText *text);static void gtk_text_disconnect (GtkAdjustment *adjustment, GtkText *text);static void gtk_text_insert_text (GtkEditable *editable, const gchar *new_text, gint new_text_length, gint *position);static void gtk_text_delete_text (GtkEditable *editable, gint start_pos, gint end_pos);static void gtk_text_update_text (GtkEditable *editable, gint start_pos, gint end_pos);static gchar *gtk_text_get_chars (GtkEditable *editable, gint start, gint end);static void gtk_text_set_selection (GtkEditable *editable, gint start, gint end);static void gtk_text_real_set_editable (GtkEditable *editable, gboolean is_editable);/* Event handlers */static void gtk_text_draw (GtkWidget *widget, GdkRectangle *area);static gint gtk_text_expose (GtkWidget *widget, GdkEventExpose *event);static gint gtk_text_button_press (GtkWidget *widget, GdkEventButton *event);static gint gtk_text_button_release (GtkWidget *widget, GdkEventButton *event);static gint gtk_text_motion_notify (GtkWidget *widget, GdkEventMotion *event);static gint gtk_text_key_press (GtkWidget *widget, GdkEventKey *event);static gint gtk_text_focus_in (GtkWidget *widget, GdkEventFocus *event);static gint gtk_text_focus_out (GtkWidget *widget, GdkEventFocus *event);static void move_gap (GtkText* text, guint index);static void make_forward_space (GtkText* text, guint len);/* Property management */static GtkTextFont* get_text_font (GdkFont* gfont);static void text_font_unref (GtkTextFont *text_font);static void insert_text_property (GtkText* text, GdkFont* font, GdkColor *fore, GdkColor* back, guint len);static TextProperty* new_text_property (GtkText *text, GdkFont* font, GdkColor* fore, GdkColor* back, guint length);static void destroy_text_property (TextProperty *prop);static void init_properties (GtkText *text);static void realize_property (GtkText *text, TextProperty *prop);static void realize_properties (GtkText *text);static void unrealize_property (GtkText *text, TextProperty *prop);static void unrealize_properties (GtkText *text);static void delete_text_property (GtkText* text, guint len);static guint pixel_height_of (GtkText* text, GList* cache_line);/* Property Movement and Size Computations */static void advance_mark (GtkPropertyMark* mark);static void decrement_mark (GtkPropertyMark* mark);static void advance_mark_n (GtkPropertyMark* mark, gint n);static void decrement_mark_n (GtkPropertyMark* mark, gint n);static void move_mark_n (GtkPropertyMark* mark, gint n);static GtkPropertyMark find_mark (GtkText* text, guint mark_position);static GtkPropertyMark find_mark_near (GtkText* text, guint mark_position, const GtkPropertyMark* near);static void find_line_containing_point (GtkText* text, guint point, gboolean scroll);/* Display */static void compute_lines_pixels (GtkText* text, guint char_count, guint *lines, guint *pixels);static gint total_line_height (GtkText* text, GList* line, gint line_count);static LineParams find_line_params (GtkText* text, const GtkPropertyMark *mark, const PrevTabCont *tab_cont, PrevTabCont *next_cont);static void recompute_geometry (GtkText* text);static void insert_expose (GtkText* text, guint old_pixels, gint nchars, guint new_line_count);static void delete_expose (GtkText* text, guint nchars, guint old_lines, guint old_pixels);static GdkGC *create_bg_gc (GtkText *text);static void clear_area (GtkText *text, GdkRectangle *area);static void draw_line (GtkText* text, gint pixel_height, LineParams* lp);static void draw_line_wrap (GtkText* text, guint height);static void draw_cursor (GtkText* text, gint absolute);static void undraw_cursor (GtkText* text, gint absolute);static gint drawn_cursor_min (GtkText* text);static gint drawn_cursor_max (GtkText* text);static void expose_text (GtkText* text, GdkRectangle *area, gboolean cursor);/* Search and Placement. */static void find_cursor (GtkText* text, gboolean scroll);static void find_cursor_at_line (GtkText* text, const LineParams* start_line, gint pixel_height);static void find_mouse_cursor (GtkText* text, gint x, gint y);/* Scrolling. */static void adjust_adj (GtkText* text, GtkAdjustment* adj);static void scroll_up (GtkText* text, gint diff);static void scroll_down (GtkText* text, gint diff);static void scroll_int (GtkText* text, gint diff);static void process_exposes (GtkText *text);/* Cache Management. */static void free_cache (GtkText* text);static GList* remove_cache_line (GtkText* text, GList* list);/* Key Motion. */static void move_cursor_buffer_ver (GtkText *text, int dir);static void move_cursor_page_ver (GtkText *text, int dir);static void move_cursor_ver (GtkText *text, int count);static void move_cursor_hor (GtkText *text, int count);/* Binding actions */static void gtk_text_move_cursor (GtkEditable *editable, gint x, gint y);static void gtk_text_move_word (GtkEditable *editable, gint n);static void gtk_text_move_page (GtkEditable *editable, gint x, gint y);static void gtk_text_move_to_row (GtkEditable *editable, gint row);static void gtk_text_move_to_column (GtkEditable *editable, gint row);static void gtk_text_kill_char (GtkEditable *editable, gint direction);static void gtk_text_kill_word (GtkEditable *editable, gint direction);static void gtk_text_kill_line (GtkEditable *editable, gint direction);/* To be removed */static void gtk_text_move_forward_character (GtkText *text);static void gtk_text_move_backward_character (GtkText *text);static void gtk_text_move_forward_word (GtkText *text);static void gtk_text_move_backward_word (GtkText *text);static void gtk_text_move_beginning_of_line (GtkText *text);static void gtk_text_move_end_of_line (GtkText *text);static void gtk_text_move_next_line (GtkText *text);static void gtk_text_move_previous_line (GtkText *text);static void gtk_text_delete_forward_character (GtkText *text);static void gtk_text_delete_backward_character (GtkText *text);static void gtk_text_delete_forward_word (GtkText *text);static void gtk_text_delete_backward_word (GtkText *text);static void gtk_text_delete_line (GtkText *text);static void gtk_text_delete_to_line_end (GtkText *text);static void gtk_text_select_word (GtkText *text, guint32 time);static void gtk_text_select_line (GtkText *text, guint32 time);static void gtk_text_set_position (GtkEditable *editable, gint position);/* #define DEBUG_GTK_TEXT */#if defined(DEBUG_GTK_TEXT) && defined(__GNUC__)/* Debugging utilities. */static void gtk_text_assert_mark (GtkText *text, GtkPropertyMark *mark, GtkPropertyMark *before, GtkPropertyMark *after, const gchar *msg, const gchar *where, gint line);static void gtk_text_assert (GtkText *text, const gchar *msg, gint line);static void gtk_text_show_cache_line (GtkText *text, GList *cache, const char* what, const char* func, gint line);static void gtk_text_show_cache (GtkText *text, const char* func, gint line);static void gtk_text_show_adj (GtkText *text, GtkAdjustment *adj, const char* what, const char* func, gint line);static void gtk_text_show_props (GtkText* test, const char* func, int line);#define TDEBUG(args) g_message args#define TEXT_ASSERT(text) gtk_text_assert (text,__PRETTY_FUNCTION__,__LINE__)#define TEXT_ASSERT_MARK(text,mark,msg) gtk_text_assert_mark (text,mark, \ __PRETTY_FUNCTION__,msg,__LINE__)#define TEXT_SHOW(text) gtk_text_show_cache (text, __PRETTY_FUNCTION__,__LINE__)#define TEXT_SHOW_LINE(text,line,msg) gtk_text_show_cache_line (text,line,msg,\ __PRETTY_FUNCTION__,__LINE__)#define TEXT_SHOW_ADJ(text,adj,msg) gtk_text_show_adj (text,adj,msg, \ __PRETTY_FUNCTION__,__LINE__)#else#define TDEBUG(args)#define TEXT_ASSERT(text)#define TEXT_ASSERT_MARK(text,mark,msg)#define TEXT_SHOW(text)#define TEXT_SHOW_LINE(text,line,msg)#define TEXT_SHOW_ADJ(text,adj,msg)#endif/* Memory Management. */static GMemChunk *params_mem_chunk = NULL;static GMemChunk *text_property_chunk = NULL;static GtkWidgetClass *parent_class = NULL;static const GtkTextFunction control_keys[26] ={ (GtkTextFunction)gtk_text_move_beginning_of_line, /* a */ (GtkTextFunction)gtk_text_move_backward_character, /* b */ (GtkTextFunction)gtk_editable_copy_clipboard, /* c */ (GtkTextFunction)gtk_text_delete_forward_character, /* d */ (GtkTextFunction)gtk_text_move_end_of_line, /* e */ (GtkTextFunction)gtk_text_move_forward_character, /* f */ NULL, /* g */ (GtkTextFunction)gtk_text_delete_backward_character, /* h */ NULL, /* i */ NULL, /* j */ (GtkTextFunction)gtk_text_delete_to_line_end, /* k */ NULL, /* l */ NULL, /* m */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -