gtktextview.c 288 KB
Newer Older
Matthias Clasen's avatar
Matthias Clasen committed
1
/* -*- Mode: C; c-file-style: "gnu"; tab-width: 8 -*- */
Cody Russell's avatar
Cody Russell committed
2
/* GTK - The GIMP Toolkit
3
 * gtktextview.c Copyright (C) 2000 Red Hat, Inc.
4
 *
5 6 7 8
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
9
 *
10 11
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 14 15 16 17 18 19 20 21 22 23 24
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser 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-2000.  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
25
 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
26 27
 */

28
#include "config.h"
29

30 31
#include <string.h>

32
#define GTK_TEXT_USE_INTERNAL_UNSUPPORTED_API
33 34
#include "gtkbindings.h"
#include "gtkdnd.h"
35
#include "gtkimagemenuitem.h"
Owen Taylor's avatar
Owen Taylor committed
36
#include "gtkintl.h"
37
#include "gtkmain.h"
38
#include "gtkmarshalers.h"
Owen Taylor's avatar
Owen Taylor committed
39 40
#include "gtkmenu.h"
#include "gtkmenuitem.h"
41
#include "gtkseparatormenuitem.h"
42
#include "gtksettings.h"
43
#include "gtkselectionprivate.h"
44
#include "gtkstock.h"
45
#include "gtktextbufferrichtext.h"
46 47 48
#include "gtktextdisplay.h"
#include "gtktextview.h"
#include "gtkimmulticontext.h"
49
#include "gtkprivate.h"
50
#include "gtktextutil.h"
Emmanuele Bassi's avatar
Emmanuele Bassi committed
51
#include "gtkwidgetprivate.h"
52
#include "gtkwindow.h"
Tadej Borovšak's avatar
Tadej Borovšak committed
53
#include "gtkscrollable.h"
54
#include "gtktypebuiltins.h"
55

56

57 58 59 60 61 62 63 64 65 66 67 68
/**
 * SECTION:gtktextview
 * @Short_description: Widget that displays a GtkTextBuffer
 * @Title: GtkTextView
 * @See_also: #GtkTextBuffer, #GtkTextIter
 *
 * You may wish to begin by reading the <link linkend="TextWidget">text widget
 * conceptual overview</link> which gives an overview of all the objects and data
 * types related to the text widget and how they work together.
 */


69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
/* How scrolling, validation, exposes, etc. work.
 *
 * The expose_event handler has the invariant that the onscreen lines
 * have been validated.
 *
 * There are two ways that onscreen lines can become invalid. The first
 * is to change which lines are onscreen. This happens when the value
 * of a scroll adjustment changes. So the code path begins in
 * gtk_text_view_value_changed() and goes like this:
 *   - gdk_window_scroll() to reflect the new adjustment value
 *   - validate the lines that were moved onscreen
 *   - gdk_window_process_updates() to handle the exposes immediately
 *
 * The second way is that you get the "invalidated" signal from the layout,
 * indicating that lines have become invalid. This code path begins in
 * invalidated_handler() and goes like this:
 *   - install high-priority idle which does the rest of the steps
 *   - if a scroll is pending from scroll_to_mark(), do the scroll,
 *     jumping to the gtk_text_view_value_changed() code path
 *   - otherwise, validate the onscreen lines
 *   - DO NOT process updates
 *
 * In both cases, validating the onscreen lines can trigger a scroll
 * due to maintaining the first_para on the top of the screen.
 * If validation triggers a scroll, we jump to the top of the code path
 * for value_changed, and bail out of the current code path.
 *
 * Also, in size_allocate, if we invalidate some lines from changing
 * the layout width, we need to go ahead and run the high-priority idle,
 * because GTK sends exposes right after doing the size allocates without
 * returning to the main loop. This is also why the high-priority idle
 * is at a higher priority than resizing.
 *
 */

104
#if 0
105 106
#define DEBUG_VALIDATION_AND_SCROLLING
#endif
107 108 109 110 111 112 113

#ifdef DEBUG_VALIDATION_AND_SCROLLING
#define DV(x) (x)
#else
#define DV(x)
#endif

114 115
#define SCREEN_WIDTH(widget) text_window_get_width (GTK_TEXT_VIEW (widget)->priv->text_window)
#define SCREEN_HEIGHT(widget) text_window_get_height (GTK_TEXT_VIEW (widget)->priv->text_window)
116

117 118
#define SPACE_FOR_CURSOR 1

119 120
#define GTK_TEXT_VIEW_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_TEXT_VIEW, GtkTextViewPrivate))

121 122 123
typedef struct _GtkTextWindow GtkTextWindow;
typedef struct _GtkTextPendingScroll GtkTextPendingScroll;

124 125
struct _GtkTextViewPrivate 
{
126 127 128
  GtkTextLayout *layout;
  GtkTextBuffer *buffer;

129
  guint blink_time;  /* time in msec the cursor has blinked since last user event */
130
  guint im_spot_idle;
131
  gchar *im_module;
132
  GdkDevice *grab_device;
133
  GdkDevice *dnd_device;
134

135
  gulong selection_drag_handler;
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
  guint scroll_timeout;

  GtkTextWindow *text_window;
  GtkTextWindow *left_window;
  GtkTextWindow *right_window;
  GtkTextWindow *top_window;
  GtkTextWindow *bottom_window;

  GtkAdjustment *hadjustment;
  GtkAdjustment *vadjustment;

  gint xoffset;         /* Offsets between widget coordinates and buffer coordinates */
  gint yoffset;
  gint width;           /* Width and height of the buffer */
  gint height;

152 153 154 155 156 157 158
  /* This is used to monitor the overall size request 
   * and decide whether we need to queue resizes when
   * the buffer content changes. 
   *
   * FIXME: This could be done in a simpler way by 
   * consulting the above width/height of the buffer + some
   * padding values, however all of this request code needs
159
   * to be changed to use GtkWidget     Iface and deserves
160 161 162 163
   * more attention.
   */
  GtkRequisition cached_size_request;

164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225
  /* The virtual cursor position is normally the same as the
   * actual (strong) cursor position, except in two circumstances:
   *
   * a) When the cursor is moved vertically with the keyboard
   * b) When the text view is scrolled with the keyboard
   *
   * In case a), virtual_cursor_x is preserved, but not virtual_cursor_y
   * In case b), both virtual_cursor_x and virtual_cursor_y are preserved.
   */
  gint virtual_cursor_x;   /* -1 means use actual cursor position */
  gint virtual_cursor_y;   /* -1 means use actual cursor position */

  GtkTextMark *first_para_mark; /* Mark at the beginning of the first onscreen paragraph */
  gint first_para_pixels;       /* Offset of top of screen in the first onscreen paragraph */

  GtkTextMark *dnd_mark;
  guint blink_timeout;

  guint first_validate_idle;        /* Idle to revalidate onscreen portion, runs before resize */
  guint incremental_validate_idle;  /* Idle to revalidate offscreen portions, runs after redraw */

  GtkIMContext *im_context;
  GtkWidget *popup_menu;

  gint drag_start_x;
  gint drag_start_y;

  GSList *children;

  GtkTextPendingScroll *pending_scroll;

  gint pending_place_cursor_button;

  /* Default style settings */
  gint pixels_above_lines;
  gint pixels_below_lines;
  gint pixels_inside_wrap;
  GtkWrapMode wrap_mode;
  GtkJustification justify;
  gint left_margin;
  gint right_margin;
  gint indent;
  PangoTabArray *tabs;
  guint editable : 1;

  guint overwrite_mode : 1;
  guint cursor_visible : 1;

  /* if we have reset the IM since the last character entered */  
  guint need_im_reset : 1;

  guint accepts_tab : 1;

  guint width_changed : 1;

  /* debug flag - means that we've validated onscreen since the
   * last "invalidate" signal from the layout
   */
  guint onscreen_validated : 1;

  guint mouse_cursor_obscured : 1;

226
  guint scroll_after_paste : 1;
227 228 229 230 231

  /* GtkScrollablePolicy needs to be checked when
   * driving the scrollable adjustment values */
  guint hscroll_policy : 1;
  guint vscroll_policy : 1;
232 233
};

234 235 236 237 238 239 240 241
struct _GtkTextPendingScroll
{
  GtkTextMark   *mark;
  gdouble        within_margin;
  gboolean       use_align;
  gdouble        xalign;
  gdouble        yalign;
};
242

243 244
enum
{
Owen Taylor's avatar
Owen Taylor committed
245
  POPULATE_POPUP,
246
  MOVE_CURSOR,
247
  PAGE_HORIZONTALLY,
248
  SET_ANCHOR,
249
  INSERT_AT_CURSOR,
250
  DELETE_FROM_CURSOR,
251
  BACKSPACE,
252 253 254
  CUT_CLIPBOARD,
  COPY_CLIPBOARD,
  PASTE_CLIPBOARD,
255
  TOGGLE_OVERWRITE,
256
  MOVE_VIEWPORT,
257
  SELECT_ALL,
258
  TOGGLE_CURSOR_VISIBLE,
259
  PREEDIT_CHANGED,
260 261 262
  LAST_SIGNAL
};

263 264
enum
{
265 266 267 268 269 270 271 272 273 274 275 276
  PROP_0,
  PROP_PIXELS_ABOVE_LINES,
  PROP_PIXELS_BELOW_LINES,
  PROP_PIXELS_INSIDE_WRAP,
  PROP_EDITABLE,
  PROP_WRAP_MODE,
  PROP_JUSTIFICATION,
  PROP_LEFT_MARGIN,
  PROP_RIGHT_MARGIN,
  PROP_INDENT,
  PROP_TABS,
  PROP_CURSOR_VISIBLE,
277
  PROP_BUFFER,
278
  PROP_OVERWRITE,
279
  PROP_ACCEPTS_TAB,
Tadej Borovšak's avatar
Tadej Borovšak committed
280 281
  PROP_IM_MODULE,
  PROP_HADJUSTMENT,
282 283 284
  PROP_VADJUSTMENT,
  PROP_HSCROLL_POLICY,
  PROP_VSCROLL_POLICY
285 286 287
};

static void gtk_text_view_finalize             (GObject          *object);
288 289 290 291 292 293 294 295
static void gtk_text_view_set_property         (GObject         *object,
						guint            prop_id,
						const GValue    *value,
						GParamSpec      *pspec);
static void gtk_text_view_get_property         (GObject         *object,
						guint            prop_id,
						GValue          *value,
						GParamSpec      *pspec);
296
static void gtk_text_view_destroy              (GtkWidget        *widget);
297
static void gtk_text_view_size_request         (GtkWidget        *widget,
298
                                                GtkRequisition   *requisition);
299 300 301 302 303 304
static void gtk_text_view_get_preferred_width  (GtkWidget        *widget,
						gint             *minimum,
						gint             *natural);
static void gtk_text_view_get_preferred_height (GtkWidget        *widget,
						gint             *minimum,
						gint             *natural);
305
static void gtk_text_view_size_allocate        (GtkWidget        *widget,
306
                                                GtkAllocation    *allocation);
307 308
static void gtk_text_view_realize              (GtkWidget        *widget);
static void gtk_text_view_unrealize            (GtkWidget        *widget);
309
static void gtk_text_view_style_updated        (GtkWidget        *widget);
310
static void gtk_text_view_direction_changed    (GtkWidget        *widget,
311
                                                GtkTextDirection  previous_direction);
312 313
static void gtk_text_view_grab_notify          (GtkWidget        *widget,
					        gboolean         was_grabbed);
314 315
static void gtk_text_view_state_flags_changed  (GtkWidget        *widget,
					        GtkStateFlags     previous_state);
316

317
static gint gtk_text_view_event                (GtkWidget        *widget,
318
                                                GdkEvent         *event);
319
static gint gtk_text_view_key_press_event      (GtkWidget        *widget,
320
                                                GdkEventKey      *event);
321
static gint gtk_text_view_key_release_event    (GtkWidget        *widget,
322
                                                GdkEventKey      *event);
323
static gint gtk_text_view_button_press_event   (GtkWidget        *widget,
324
                                                GdkEventButton   *event);
325
static gint gtk_text_view_button_release_event (GtkWidget        *widget,
326
                                                GdkEventButton   *event);
327
static gint gtk_text_view_focus_in_event       (GtkWidget        *widget,
328
                                                GdkEventFocus    *event);
329
static gint gtk_text_view_focus_out_event      (GtkWidget        *widget,
330
                                                GdkEventFocus    *event);
331
static gint gtk_text_view_motion_event         (GtkWidget        *widget,
332
                                                GdkEventMotion   *event);
Benjamin Otte's avatar
Benjamin Otte committed
333 334 335 336
static gint gtk_text_view_draw                 (GtkWidget        *widget,
                                                cairo_t          *cr);
static void gtk_text_view_draw_focus           (GtkWidget        *widget,
                                                cairo_t          *cr);
337 338
static gboolean gtk_text_view_focus            (GtkWidget        *widget,
                                                GtkDirectionType  direction);
339 340
static void gtk_text_view_select_all           (GtkWidget        *widget,
                                                gboolean          select);
341

342 343 344

/* Source side drag signals */
static void gtk_text_view_drag_begin       (GtkWidget        *widget,
345
                                            GdkDragContext   *context);
346
static void gtk_text_view_drag_end         (GtkWidget        *widget,
347
                                            GdkDragContext   *context);
348
static void gtk_text_view_drag_data_get    (GtkWidget        *widget,
349 350 351 352
                                            GdkDragContext   *context,
                                            GtkSelectionData *selection_data,
                                            guint             info,
                                            guint             time);
353
static void gtk_text_view_drag_data_delete (GtkWidget        *widget,
354
                                            GdkDragContext   *context);
355 356 357

/* Target side drag signals */
static void     gtk_text_view_drag_leave         (GtkWidget        *widget,
358 359
                                                  GdkDragContext   *context,
                                                  guint             time);
360
static gboolean gtk_text_view_drag_motion        (GtkWidget        *widget,
361 362 363 364
                                                  GdkDragContext   *context,
                                                  gint              x,
                                                  gint              y,
                                                  guint             time);
365
static gboolean gtk_text_view_drag_drop          (GtkWidget        *widget,
366 367 368 369
                                                  GdkDragContext   *context,
                                                  gint              x,
                                                  gint              y,
                                                  guint             time);
370
static void     gtk_text_view_drag_data_received (GtkWidget        *widget,
371 372 373 374 375 376
                                                  GdkDragContext   *context,
                                                  gint              x,
                                                  gint              y,
                                                  GtkSelectionData *selection_data,
                                                  guint             info,
                                                  guint             time);
377

378
static gboolean gtk_text_view_popup_menu         (GtkWidget     *widget);
379

380 381 382 383
static void gtk_text_view_move_cursor       (GtkTextView           *text_view,
                                             GtkMovementStep        step,
                                             gint                   count,
                                             gboolean               extend_selection);
384
static void gtk_text_view_move_viewport     (GtkTextView           *text_view,
385 386
                                             GtkScrollStep          step,
                                             gint                   count);
387
static void gtk_text_view_set_anchor       (GtkTextView           *text_view);
388
static gboolean gtk_text_view_scroll_pages (GtkTextView           *text_view,
389 390
                                            gint                   count,
                                            gboolean               extend_selection);
391
static gboolean gtk_text_view_scroll_hpages(GtkTextView           *text_view,
392 393
                                            gint                   count,
                                            gboolean               extend_selection);
394
static void gtk_text_view_insert_at_cursor (GtkTextView           *text_view,
395
                                            const gchar           *str);
396 397 398
static void gtk_text_view_delete_from_cursor (GtkTextView           *text_view,
                                              GtkDeleteType          type,
                                              gint                   count);
399
static void gtk_text_view_backspace        (GtkTextView           *text_view);
400 401 402 403
static void gtk_text_view_cut_clipboard    (GtkTextView           *text_view);
static void gtk_text_view_copy_clipboard   (GtkTextView           *text_view);
static void gtk_text_view_paste_clipboard  (GtkTextView           *text_view);
static void gtk_text_view_toggle_overwrite (GtkTextView           *text_view);
404
static void gtk_text_view_toggle_cursor_visible (GtkTextView      *text_view);
405

406
static void gtk_text_view_unselect         (GtkTextView           *text_view);
407 408 409

static void     gtk_text_view_validate_onscreen     (GtkTextView        *text_view);
static void     gtk_text_view_get_first_para_iter   (GtkTextView        *text_view,
410
                                                     GtkTextIter        *iter);
411
static void     gtk_text_view_update_layout_width       (GtkTextView        *text_view);
412
static void     gtk_text_view_set_attributes_from_style (GtkTextView        *text_view,
413
                                                         GtkTextAttributes  *values);
414 415 416 417 418 419
static void     gtk_text_view_ensure_layout          (GtkTextView        *text_view);
static void     gtk_text_view_destroy_layout         (GtkTextView        *text_view);
static void     gtk_text_view_check_keymap_direction (GtkTextView        *text_view);
static void     gtk_text_view_start_selection_drag   (GtkTextView        *text_view,
                                                      const GtkTextIter  *iter,
                                                      GdkEventButton     *event);
420
static gboolean gtk_text_view_end_selection_drag     (GtkTextView        *text_view);
421 422 423 424 425 426
static void     gtk_text_view_start_selection_dnd    (GtkTextView        *text_view,
                                                      const GtkTextIter  *iter,
                                                      GdkEventMotion     *event);
static void     gtk_text_view_check_cursor_blink     (GtkTextView        *text_view);
static void     gtk_text_view_pend_cursor_blink      (GtkTextView        *text_view);
static void     gtk_text_view_stop_cursor_blink      (GtkTextView        *text_view);
427
static void     gtk_text_view_reset_blink_time       (GtkTextView        *text_view);
428

429
static void     gtk_text_view_value_changed                (GtkAdjustment *adjustment,
430 431 432 433
							    GtkTextView   *view);
static void     gtk_text_view_commit_handler               (GtkIMContext  *context,
							    const gchar   *str,
							    GtkTextView   *text_view);
434 435
static void     gtk_text_view_commit_text                  (GtkTextView   *text_view,
                                                            const gchar   *text);
436 437 438 439 440 441 442 443
static void     gtk_text_view_preedit_changed_handler      (GtkIMContext  *context,
							    GtkTextView   *text_view);
static gboolean gtk_text_view_retrieve_surrounding_handler (GtkIMContext  *context,
							    GtkTextView   *text_view);
static gboolean gtk_text_view_delete_surrounding_handler   (GtkIMContext  *context,
							    gint           offset,
							    gint           n_chars,
							    GtkTextView   *text_view);
444 445

static void gtk_text_view_mark_set_handler       (GtkTextBuffer     *buffer,
446
                                                  const GtkTextIter *location,
Havoc Pennington's avatar
Havoc Pennington committed
447
                                                  GtkTextMark       *mark,
448
                                                  gpointer           data);
449 450 451
static void gtk_text_view_target_list_notify     (GtkTextBuffer     *buffer,
                                                  const GParamSpec  *pspec,
                                                  gpointer           data);
452 453 454
static void gtk_text_view_paste_done_handler     (GtkTextBuffer     *buffer,
                                                  GtkClipboard      *clipboard,
                                                  gpointer           data);
455
static void gtk_text_view_get_virtual_cursor_pos (GtkTextView       *text_view,
456
                                                  GtkTextIter       *cursor,
457 458
                                                  gint              *x,
                                                  gint              *y);
459
static void gtk_text_view_set_virtual_cursor_pos (GtkTextView       *text_view,
460 461
                                                  gint               x,
                                                  gint               y);
462

Owen Taylor's avatar
Owen Taylor committed
463
static void gtk_text_view_do_popup               (GtkTextView       *text_view,
Owen Taylor's avatar
Owen Taylor committed
464
						  GdkEventButton    *event);
465

466
static void cancel_pending_scroll                (GtkTextView   *text_view);
467 468 469 470 471 472 473
static void gtk_text_view_queue_scroll           (GtkTextView   *text_view,
                                                  GtkTextMark   *mark,
                                                  gdouble        within_margin,
                                                  gboolean       use_align,
                                                  gdouble        xalign,
                                                  gdouble        yalign);

474 475 476 477
static gboolean gtk_text_view_flush_scroll         (GtkTextView *text_view);
static void     gtk_text_view_update_adjustments   (GtkTextView *text_view);
static void     gtk_text_view_invalidate           (GtkTextView *text_view);
static void     gtk_text_view_flush_first_validate (GtkTextView *text_view);
478

Tadej Borovšak's avatar
Tadej Borovšak committed
479 480 481 482 483 484 485
static void     gtk_text_view_set_hadjustment        (GtkTextView   *text_view,
                                                      GtkAdjustment *adjustment);
static void     gtk_text_view_set_vadjustment        (GtkTextView   *text_view,
                                                      GtkAdjustment *adjustment);
static void     gtk_text_view_set_hadjustment_values (GtkTextView   *text_view);
static void     gtk_text_view_set_vadjustment_values (GtkTextView   *text_view);

486 487
static void gtk_text_view_update_im_spot_location (GtkTextView *text_view);

488 489 490 491 492 493 494
/* Container methods */
static void gtk_text_view_add    (GtkContainer *container,
                                  GtkWidget    *child);
static void gtk_text_view_remove (GtkContainer *container,
                                  GtkWidget    *child);
static void gtk_text_view_forall (GtkContainer *container,
                                  gboolean      include_internals,
495
                                  GtkCallback   callback,
496 497 498 499 500 501 502 503 504 505 506 507
                                  gpointer      callback_data);

/* FIXME probably need the focus methods. */

typedef struct _GtkTextViewChild GtkTextViewChild;

struct _GtkTextViewChild
{
  GtkWidget *widget;

  GtkTextChildAnchor *anchor;

508 509 510
  gint from_top_of_line;
  gint from_left_of_buffer;
  
511 512 513 514 515 516
  /* These are ignored if anchor != NULL */
  GtkTextWindowType type;
  gint x;
  gint y;
};

517 518 519 520 521 522 523 524 525 526
static GtkTextViewChild* text_view_child_new_anchored      (GtkWidget          *child,
							    GtkTextChildAnchor *anchor,
							    GtkTextLayout      *layout);
static GtkTextViewChild* text_view_child_new_window        (GtkWidget          *child,
							    GtkTextWindowType   type,
							    gint                x,
							    gint                y);
static void              text_view_child_free              (GtkTextViewChild   *child);
static void              text_view_child_set_parent_window (GtkTextView        *text_view,
							    GtkTextViewChild   *child);
527

528 529 530 531 532 533 534 535 536 537
struct _GtkTextWindow
{
  GtkTextWindowType type;
  GtkWidget *widget;
  GdkWindow *window;
  GdkWindow *bin_window;
  GtkRequisition requisition;
  GdkRectangle allocation;
};

538 539 540 541 542 543
static GtkTextWindow *text_window_new             (GtkTextWindowType  type,
                                                   GtkWidget         *widget,
                                                   gint               width_request,
                                                   gint               height_request);
static void           text_window_free            (GtkTextWindow     *win);
static void           text_window_realize         (GtkTextWindow     *win,
544
                                                   GtkWidget         *widget);
545 546 547 548 549 550 551 552
static void           text_window_unrealize       (GtkTextWindow     *win);
static void           text_window_size_allocate   (GtkTextWindow     *win,
                                                   GdkRectangle      *rect);
static void           text_window_scroll          (GtkTextWindow     *win,
                                                   gint               dx,
                                                   gint               dy);
static void           text_window_invalidate_rect (GtkTextWindow     *win,
                                                   GdkRectangle      *rect);
553
static void           text_window_invalidate_cursors (GtkTextWindow  *win);
554 555 556

static gint           text_window_get_width       (GtkTextWindow     *win);
static gint           text_window_get_height      (GtkTextWindow     *win);
557 558


559 560
static guint signals[LAST_SIGNAL] = { 0 };

Tadej Borovšak's avatar
Tadej Borovšak committed
561 562
G_DEFINE_TYPE_WITH_CODE (GtkTextView, gtk_text_view, GTK_TYPE_CONTAINER,
			 G_IMPLEMENT_INTERFACE (GTK_TYPE_SCROLLABLE, NULL))
563 564

static void
565
add_move_binding (GtkBindingSet  *binding_set,
566 567 568 569
                  guint           keyval,
                  guint           modmask,
                  GtkMovementStep step,
                  gint            count)
570
{
571
  g_assert ((modmask & GDK_SHIFT_MASK) == 0);
572

573
  gtk_binding_entry_add_signal (binding_set, keyval, modmask,
574
                                "move-cursor", 3,
Manish Singh's avatar
Manish Singh committed
575 576 577
                                G_TYPE_ENUM, step,
                                G_TYPE_INT, count,
                                G_TYPE_BOOLEAN, FALSE);
578 579 580

  /* Selection-extending version */
  gtk_binding_entry_add_signal (binding_set, keyval, modmask | GDK_SHIFT_MASK,
581
                                "move-cursor", 3,
Manish Singh's avatar
Manish Singh committed
582 583 584
                                G_TYPE_ENUM, step,
                                G_TYPE_INT, count,
                                G_TYPE_BOOLEAN, TRUE);
585 586 587 588 589 590 591
}

static void
gtk_text_view_class_init (GtkTextViewClass *klass)
{
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
592
  GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
593
  GtkBindingSet *binding_set;
594

595 596
  /* Default handlers and virtual methods
   */
597 598
  gobject_class->set_property = gtk_text_view_set_property;
  gobject_class->get_property = gtk_text_view_get_property;
599 600
  gobject_class->finalize = gtk_text_view_finalize;

601
  widget_class->destroy = gtk_text_view_destroy;
602 603
  widget_class->realize = gtk_text_view_realize;
  widget_class->unrealize = gtk_text_view_unrealize;
604
  widget_class->style_updated = gtk_text_view_style_updated;
605
  widget_class->direction_changed = gtk_text_view_direction_changed;
606
  widget_class->grab_notify = gtk_text_view_grab_notify;
607
  widget_class->state_flags_changed = gtk_text_view_state_flags_changed;
608 609
  widget_class->get_preferred_width = gtk_text_view_get_preferred_width;
  widget_class->get_preferred_height = gtk_text_view_get_preferred_height;
610 611 612 613 614 615 616 617 618
  widget_class->size_allocate = gtk_text_view_size_allocate;
  widget_class->event = gtk_text_view_event;
  widget_class->key_press_event = gtk_text_view_key_press_event;
  widget_class->key_release_event = gtk_text_view_key_release_event;
  widget_class->button_press_event = gtk_text_view_button_press_event;
  widget_class->button_release_event = gtk_text_view_button_release_event;
  widget_class->focus_in_event = gtk_text_view_focus_in_event;
  widget_class->focus_out_event = gtk_text_view_focus_out_event;
  widget_class->motion_notify_event = gtk_text_view_motion_event;
Benjamin Otte's avatar
Benjamin Otte committed
619
  widget_class->draw = gtk_text_view_draw;
620
  widget_class->focus = gtk_text_view_focus;
621 622 623 624 625 626 627 628 629 630
  widget_class->drag_begin = gtk_text_view_drag_begin;
  widget_class->drag_end = gtk_text_view_drag_end;
  widget_class->drag_data_get = gtk_text_view_drag_data_get;
  widget_class->drag_data_delete = gtk_text_view_drag_data_delete;

  widget_class->drag_leave = gtk_text_view_drag_leave;
  widget_class->drag_motion = gtk_text_view_drag_motion;
  widget_class->drag_drop = gtk_text_view_drag_drop;
  widget_class->drag_data_received = gtk_text_view_drag_data_received;

Owen Taylor's avatar
Owen Taylor committed
631 632
  widget_class->popup_menu = gtk_text_view_popup_menu;
  
633 634 635 636 637 638 639 640
  container_class->add = gtk_text_view_add;
  container_class->remove = gtk_text_view_remove;
  container_class->forall = gtk_text_view_forall;

  klass->move_cursor = gtk_text_view_move_cursor;
  klass->set_anchor = gtk_text_view_set_anchor;
  klass->insert_at_cursor = gtk_text_view_insert_at_cursor;
  klass->delete_from_cursor = gtk_text_view_delete_from_cursor;
641
  klass->backspace = gtk_text_view_backspace;
642 643 644 645 646
  klass->cut_clipboard = gtk_text_view_cut_clipboard;
  klass->copy_clipboard = gtk_text_view_copy_clipboard;
  klass->paste_clipboard = gtk_text_view_paste_clipboard;
  klass->toggle_overwrite = gtk_text_view_toggle_overwrite;

647
  /*
648
   * Properties
649
   */
650 651 652
 
  g_object_class_install_property (gobject_class,
                                   PROP_PIXELS_ABOVE_LINES,
Matthias Clasen's avatar
x  
Matthias Clasen committed
653
                                   g_param_spec_int ("pixels-above-lines",
654 655
						     P_("Pixels Above Lines"),
						     P_("Pixels of blank space above paragraphs"),
656 657 658
						     0,
						     G_MAXINT,
						     0,
659
						     GTK_PARAM_READWRITE));
660 661 662
 
  g_object_class_install_property (gobject_class,
                                   PROP_PIXELS_BELOW_LINES,
Matthias Clasen's avatar
x  
Matthias Clasen committed
663
                                   g_param_spec_int ("pixels-below-lines",
664 665
						     P_("Pixels Below Lines"),
						     P_("Pixels of blank space below paragraphs"),
666 667 668
						     0,
						     G_MAXINT,
						     0,
669
						     GTK_PARAM_READWRITE));
670 671 672
 
  g_object_class_install_property (gobject_class,
                                   PROP_PIXELS_INSIDE_WRAP,
Matthias Clasen's avatar
x  
Matthias Clasen committed
673
                                   g_param_spec_int ("pixels-inside-wrap",
674 675
						     P_("Pixels Inside Wrap"),
						     P_("Pixels of blank space between wrapped lines in a paragraph"),
676 677 678
						     0,
						     G_MAXINT,
						     0,
679
						     GTK_PARAM_READWRITE));
680 681 682 683

  g_object_class_install_property (gobject_class,
                                   PROP_EDITABLE,
                                   g_param_spec_boolean ("editable",
684 685
							 P_("Editable"),
							 P_("Whether the text can be modified by the user"),
686
							 TRUE,
687
							 GTK_PARAM_READWRITE));
688 689 690

  g_object_class_install_property (gobject_class,
                                   PROP_WRAP_MODE,
Matthias Clasen's avatar
x  
Matthias Clasen committed
691
                                   g_param_spec_enum ("wrap-mode",
692 693
						      P_("Wrap Mode"),
						      P_("Whether to wrap lines never, at word boundaries, or at character boundaries"),
694 695
						      GTK_TYPE_WRAP_MODE,
						      GTK_WRAP_NONE,
696
						      GTK_PARAM_READWRITE));
697 698 699 700
 
  g_object_class_install_property (gobject_class,
                                   PROP_JUSTIFICATION,
                                   g_param_spec_enum ("justification",
701 702
						      P_("Justification"),
						      P_("Left, right, or center justification"),
703 704
						      GTK_TYPE_JUSTIFICATION,
						      GTK_JUSTIFY_LEFT,
705
						      GTK_PARAM_READWRITE));
706 707 708
 
  g_object_class_install_property (gobject_class,
                                   PROP_LEFT_MARGIN,
Matthias Clasen's avatar
x  
Matthias Clasen committed
709
                                   g_param_spec_int ("left-margin",
710 711
						     P_("Left Margin"),
						     P_("Width of the left margin in pixels"),
712 713 714
						     0,
						     G_MAXINT,
						     0,
715
						     GTK_PARAM_READWRITE));
716 717 718

  g_object_class_install_property (gobject_class,
                                   PROP_RIGHT_MARGIN,
Matthias Clasen's avatar
x  
Matthias Clasen committed
719
                                   g_param_spec_int ("right-margin",
720 721
						     P_("Right Margin"),
						     P_("Width of the right margin in pixels"),
722 723 724
						     0,
						     G_MAXINT,
						     0,
725
						     GTK_PARAM_READWRITE));
726 727 728 729

  g_object_class_install_property (gobject_class,
                                   PROP_INDENT,
                                   g_param_spec_int ("indent",
730 731
						     P_("Indent"),
						     P_("Amount to indent the paragraph, in pixels"),
732
						     G_MININT,
733 734
						     G_MAXINT,
						     0,
735
						     GTK_PARAM_READWRITE));
736 737 738 739

  g_object_class_install_property (gobject_class,
                                   PROP_TABS,
                                   g_param_spec_boxed ("tabs",
740 741
                                                       P_("Tabs"),
                                                       P_("Custom tabs for this text"),
742
                                                       PANGO_TYPE_TAB_ARRAY,
743
						       GTK_PARAM_READWRITE));
744 745 746

  g_object_class_install_property (gobject_class,
                                   PROP_CURSOR_VISIBLE,
Matthias Clasen's avatar
x  
Matthias Clasen committed
747
                                   g_param_spec_boolean ("cursor-visible",
748 749
							 P_("Cursor Visible"),
							 P_("If the insertion cursor is shown"),
750
							 TRUE,
751
							 GTK_PARAM_READWRITE));
752

753 754 755
  g_object_class_install_property (gobject_class,
                                   PROP_BUFFER,
                                   g_param_spec_object ("buffer",
756 757
							P_("Buffer"),
							P_("The buffer which is displayed"),
758
							GTK_TYPE_TEXT_BUFFER,
759
							GTK_PARAM_READWRITE));
760

761 762 763
  g_object_class_install_property (gobject_class,
                                   PROP_OVERWRITE,
                                   g_param_spec_boolean ("overwrite",
764 765
							 P_("Overwrite mode"),
							 P_("Whether entered text overwrites existing contents"),
766
							 FALSE,
767
							 GTK_PARAM_READWRITE));
768

769
  g_object_class_install_property (gobject_class,
770
                                   PROP_ACCEPTS_TAB,
Matthias Clasen's avatar
x  
Matthias Clasen committed
771
                                   g_param_spec_boolean ("accepts-tab",
772 773
							 P_("Accepts tab"),
							 P_("Whether Tab will result in a tab character being entered"),
774
							 TRUE,
775
							 GTK_PARAM_READWRITE));
776

777 778 779
   /**
    * GtkTextView:im-module:
    *
780 781
    * Which IM (input method) module should be used for this entry. 
    * See #GtkIMContext.
782 783
    *
    * Setting this to a non-%NULL value overrides the
784 785
    * system-wide IM module setting. See the GtkSettings 
    * #GtkSettings:gtk-im-module property.
786 787 788 789 790 791 792 793 794 795 796
    *
    * Since: 2.16
    */
   g_object_class_install_property (gobject_class,
                                    PROP_IM_MODULE,
                                    g_param_spec_string ("im-module",
                                                         P_("IM module"),
                                                         P_("Which IM module should be used"),
                                                         NULL,
                                                         GTK_PARAM_READWRITE));

Tadej Borovšak's avatar
Tadej Borovšak committed
797
   /* GtkScrollable interface */
798 799 800 801
   g_object_class_override_property (gobject_class, PROP_HADJUSTMENT,    "hadjustment");
   g_object_class_override_property (gobject_class, PROP_VADJUSTMENT,    "vadjustment");
   g_object_class_override_property (gobject_class, PROP_HSCROLL_POLICY, "hscroll-policy");
   g_object_class_override_property (gobject_class, PROP_VSCROLL_POLICY, "vscroll-policy");
Tadej Borovšak's avatar
Tadej Borovšak committed
802

803 804 805 806 807
  /*
   * Style properties
   */
  gtk_widget_class_install_style_property (widget_class,
					   g_param_spec_boxed ("error-underline-color",
808
							       P_("Error underline color"),
Owen Taylor's avatar
Owen Taylor committed
809
							       P_("Color with which to draw error-indication underlines"),
810
							       GDK_TYPE_COLOR,
811
							       GTK_PARAM_READABLE));
812
  
813 814 815 816
  /*
   * Signals
   */

817 818
  /**
   * GtkTextView::move-cursor: 
Matthias Clasen's avatar
Matthias Clasen committed
819
   * @text_view: the object which received the signal
820 821 822 823
   * @step: the granularity of the move, as a #GtkMovementStep
   * @count: the number of @step units to move
   * @extend_selection: %TRUE if the move should extend the selection
   *  
Matthias Clasen's avatar
Matthias Clasen committed
824 825 826 827 828
   * The ::move-cursor signal is a 
   * <link linkend="keybinding-signals">keybinding signal</link> 
   * which gets emitted when the user initiates a cursor movement. 
   * If the cursor is not visible in @text_view, this signal causes
   * the viewport to be moved instead.
829 830
   *
   * Applications should not connect to it, but may emit it with 
831
   * g_signal_emit_by_name() if they need to control the cursor
832
   * programmatically.
Matthias Clasen's avatar
Matthias Clasen committed
833 834 835 836 837 838 839 840 841 842 843 844
   *
   * The default bindings for this signal come in two variants,
   * the variant with the Shift modifier extends the selection,
   * the variant without the Shift modifer does not.
   * There are too many key combinations to list them all here.
   * <itemizedlist>
   * <listitem>Arrow keys move by individual characters/lines</listitem>
   * <listitem>Ctrl-arrow key combinations move by words/paragraphs</listitem>
   * <listitem>Home/End keys move to the ends of the buffer</listitem>
   * <listitem>PageUp/PageDown keys move vertically by pages</listitem>
   * <listitem>Ctrl-PageUp/PageDown keys move horizontally by pages</listitem>
   * </itemizedlist>
845 846
   */
  signals[MOVE_CURSOR] = 
847
    g_signal_new (I_("move-cursor"),
848 849
		  G_OBJECT_CLASS_TYPE (gobject_class), 
		  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, 
Manish Singh's avatar
Manish Singh committed
850
		  G_STRUCT_OFFSET (GtkTextViewClass, move_cursor),
851 852
		  NULL, NULL, 
		  _gtk_marshal_VOID__ENUM_INT_BOOLEAN, 
Manish Singh's avatar
Manish Singh committed
853
		  G_TYPE_NONE, 3,
854 855
		  GTK_TYPE_MOVEMENT_STEP, 
		  G_TYPE_INT, 
Manish Singh's avatar
Manish Singh committed
856
		  G_TYPE_BOOLEAN);
857

Matthias Clasen's avatar
Matthias Clasen committed
858 859 860 861 862 863 864 865 866 867 868 869 870 871
  /**
   * GtkTextView::move-viewport:
   * @text_view: the object which received the signal
   * @step: the granularity of the move, as a #GtkMovementStep
   * @count: the number of @step units to move
   *
   * The ::move-viewport signal is a 
   * <link linkend="keybinding-signals">keybinding signal</link> 
   * which can be bound to key combinations to allow the user
   * to move the viewport, i.e. change what part of the text view
   * is visible in a containing scrolled window.
   *
   * There are no default bindings for this signal.
   */
872
  signals[MOVE_VIEWPORT] =
873
    g_signal_new_class_handler (I_("move-viewport"),
874 875 876 877 878 879 880 881
                                G_OBJECT_CLASS_TYPE (gobject_class),
                                G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                                G_CALLBACK (gtk_text_view_move_viewport),
                                NULL, NULL,
                                _gtk_marshal_VOID__ENUM_INT,
                                G_TYPE_NONE, 2,
                                GTK_TYPE_SCROLL_STEP,
                                G_TYPE_INT);
882

Matthias Clasen's avatar
Matthias Clasen committed
883 884 885 886 887 888 889 890 891 892 893 894
  /**
   * GtkTextView::set-anchor:
   * @text_view: the object which received the signal
   *
   * The ::set-anchor signal is a
   * <link linkend="keybinding-signals">keybinding signal</link>
   * which gets emitted when the user initiates setting the "anchor" 
   * mark. The "anchor" mark gets placed at the same position as the
   * "insert" mark.
   *
   * This signal has no default bindings.
   */   
895
  signals[SET_ANCHOR] =
896
    g_signal_new (I_("set-anchor"),
Manish Singh's avatar
Manish Singh committed
897 898 899 900 901 902
		  G_OBJECT_CLASS_TYPE (gobject_class),
		  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
		  G_STRUCT_OFFSET (GtkTextViewClass, set_anchor),
		  NULL, NULL,
		  _gtk_marshal_VOID__VOID,
		  G_TYPE_NONE, 0);
903

Matthias Clasen's avatar
Matthias Clasen committed
904 905 906 907 908 909 910 911 912 913 914 915
  /**
   * GtkTextView::insert-at-cursor:
   * @text_view: the object which received the signal
   * @string: the string to insert
   *
   * The ::insert-at-cursor signal is a
   * <link linkend="keybinding-signals">keybinding signal</link>
   * which gets emitted when the user initiates the insertion of a 
   * fixed string at the cursor.
   *
   * This signal has no default bindings.
   */
916
  signals[INSERT_AT_CURSOR] =
917
    g_signal_new (I_("insert-at-cursor"),
Manish Singh's avatar
Manish Singh committed
918 919 920 921 922 923 924
		  G_OBJECT_CLASS_TYPE (gobject_class),
		  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
		  G_STRUCT_OFFSET (GtkTextViewClass, insert_at_cursor),
		  NULL, NULL,
		  _gtk_marshal_VOID__STRING,
		  G_TYPE_NONE, 1,
		  G_TYPE_STRING);
925

Matthias Clasen's avatar
Matthias Clasen committed
926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944
  /**
   * GtkTextView::delete-from-cursor:
   * @text_view: the object which received the signal
   * @type: the granularity of the deletion, as a #GtkDeleteType
   * @count: the number of @type units to delete
   *
   * The ::delete-from-cursor signal is a 
   * <link linkend="keybinding-signals">keybinding signal</link> 
   * which gets emitted when the user initiates a text deletion.
   *
   * If the @type is %GTK_DELETE_CHARS, GTK+ deletes the selection
   * if there is one, otherwise it deletes the requested number
   * of characters.
   *
   * The default bindings for this signal are
   * Delete for deleting a character, Ctrl-Delete for 
   * deleting a word and Ctrl-Backspace for deleting a word 
   * backwords.
   */
945
  signals[DELETE_FROM_CURSOR] =
946
    g_signal_new (I_("delete-from-cursor"),
Manish Singh's avatar
Manish Singh committed
947 948 949 950 951 952 953 954
		  G_OBJECT_CLASS_TYPE (gobject_class),
		  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
		  G_STRUCT_OFFSET (GtkTextViewClass, delete_from_cursor),
		  NULL, NULL,
		  _gtk_marshal_VOID__ENUM_INT,
		  G_TYPE_NONE, 2,
		  GTK_TYPE_DELETE_TYPE,
		  G_TYPE_INT);
955

Matthias Clasen's avatar
Matthias Clasen committed
956 957 958 959 960 961 962 963 964 965 966
  /**
   * GtkTextView::backspace:
   * @text_view: the object which received the signal
   *
   * The ::backspace signal is a 
   * <link linkend="keybinding-signals">keybinding signal</link> 
   * which gets emitted when the user asks for it.
   * 
   * The default bindings for this signal are
   * Backspace and Shift-Backspace.
   */
967
  signals[BACKSPACE] =
Matthias Clasen's avatar
Matthias Clasen committed
968
    g_signal_new (I_("backspace"),
969 970 971 972 973 974 975
		  G_OBJECT_CLASS_TYPE (gobject_class),
		  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
		  G_STRUCT_OFFSET (GtkTextViewClass, backspace),
		  NULL, NULL,
		  _gtk_marshal_VOID__VOID,
		  G_TYPE_NONE, 0);

Matthias Clasen's avatar
Matthias Clasen committed
976 977 978 979 980 981 982 983 984 985 986
  /**
   * GtkTextView::cut-clipboard:
   * @text_view: the object which received the signal
   *
   * The ::cut-clipboard signal is a 
   * <link linkend="keybinding-signals">keybinding signal</link> 
   * which gets emitted to cut the selection to the clipboard.
   * 
   * The default bindings for this signal are
   * Ctrl-x and Shift-Delete.
   */
987
  signals[CUT_CLIPBOARD] =
988
    g_signal_new (I_("cut-clipboard"),
Manish Singh's avatar
Manish Singh committed
989 990 991 992 993 994
		  G_OBJECT_CLASS_TYPE (gobject_class),
		  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
		  G_STRUCT_OFFSET (GtkTextViewClass, cut_clipboard),
		  NULL, NULL,
		  _gtk_marshal_VOID__VOID,
		  G_TYPE_NONE, 0);
995

Matthias Clasen's avatar
Matthias Clasen committed
996 997 998 999 1000 1001 1002 1003 1004 1005 1006
  /**
   * GtkTextView::copy-clipboard:
   * @text_view: the object which received the signal
   *
   * The ::copy-clipboard signal is a 
   * <link linkend="keybinding-signals">keybinding signal</link> 
   * which gets emitted to copy the selection to the clipboard.
   * 
   * The default bindings for this signal are
   * Ctrl-c and Ctrl-Insert.
   */
1007
  signals[COPY_CLIPBOARD] =
1008
    g_signal_new (I_("copy-clipboard"),
Manish Singh's avatar
Manish Singh committed
1009 1010 1011 1012 1013 1014
		  G_OBJECT_CLASS_TYPE (gobject_class),
		  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
		  G_STRUCT_OFFSET (GtkTextViewClass, copy_clipboard),
		  NULL, NULL,
		  _gtk_marshal_VOID__VOID,
		  G_TYPE_NONE, 0);
1015

Matthias Clasen's avatar
Matthias Clasen committed
1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027
  /**
   * GtkTextView::paste-clipboard:
   * @text_view: the object which received the signal
   *
   * The ::paste-clipboard signal is a 
   * <link linkend="keybinding-signals">keybinding signal</link> 
   * which gets emitted to paste the contents of the clipboard 
   * into the text view.
   * 
   * The default bindings for this signal are
   * Ctrl-v and Shift-Insert.
   */
1028
  signals[PASTE_CLIPBOARD] =
1029
    g_signal_new (I_("paste-clipboard"),
Manish Singh's avatar
Manish Singh committed
1030 1031 1032 1033 1034 1035
		  G_OBJECT_CLASS_TYPE (gobject_class),
		  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
		  G_STRUCT_OFFSET (GtkTextViewClass, paste_clipboard),
		  NULL, NULL,
		  _gtk_marshal_VOID__VOID,
		  G_TYPE_NONE, 0);
1036

Matthias Clasen's avatar
Matthias Clasen committed
1037 1038 1039 1040 1041 1042
  /**
   * GtkTextView::toggle-overwrite:
   * @text_view: the object which received the signal
   *
   * The ::toggle-overwrite signal is a 
   * <link linkend="keybinding-signals">keybinding signal</link> 
Matthias Clasen's avatar
Matthias Clasen committed
1043
   * which gets emitted to toggle the overwrite mode of the text view.
Matthias Clasen's avatar
Matthias Clasen committed
1044 1045 1046
   * 
   * The default bindings for this signal is Insert.
   */ 
1047
  signals[TOGGLE_OVERWRITE] =
1048
    g_signal_new (I_("toggle-overwrite"),
Manish Singh's avatar
Manish Singh committed
1049 1050 1051 1052 1053 1054
		  G_OBJECT_CLASS_TYPE (gobject_class),
		  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
		  G_STRUCT_OFFSET (GtkTextViewClass, toggle_overwrite),
		  NULL, NULL,
		  _gtk_marshal_VOID__VOID,
		  G_TYPE_NONE, 0);
1055

Matthias Clasen's avatar
Matthias Clasen committed
1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066
  /**
   * GtkTextView::populate-popup:
   * @entry: The text view on which the signal is emitted
   * @menu: the menu that is being populated
   *
   * The ::populate-popup signal gets emitted before showing the 
   * context menu of the text view.
   *
   * If you need to add items to the context menu, connect
   * to this signal and append your menuitems to the @menu.
   */
Owen Taylor's avatar
Owen Taylor committed
1067
  signals[POPULATE_POPUP] =
1068
    g_signal_new (I_("populate-popup"),
Manish Singh's avatar
Manish Singh committed
1069 1070 1071 1072 1073 1074 1075
		  G_OBJECT_CLASS_TYPE (gobject_class),
		  G_SIGNAL_RUN_LAST,
		  G_STRUCT_OFFSET (GtkTextViewClass, populate_popup),
		  NULL, NULL,
		  _gtk_marshal_VOID__OBJECT,
		  G_TYPE_NONE, 1,
		  GTK_TYPE_MENU);
Owen Taylor's avatar
Owen Taylor committed
1076
  
Matthias Clasen's avatar
Matthias Clasen committed
1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089
  /**
   * GtkTextView::select-all:
   * @text_view: the object which received the signal
   * @select: %TRUE to select, %FALSE to unselect
   *
   * The ::select-all signal is a 
   * <link linkend="keybinding-signals">keybinding signal</link> 
   * which gets emitted to select or unselect the complete
   * contents of the text view.
   *
   * The default bindings for this signal are Ctrl-a and Ctrl-/ 
   * for selecting and Shift-Ctrl-a and Ctrl-\ for unselecting.
   */
1090
  signals[SELECT_ALL] =
1091
    g_signal_new_class_handler (I_("select-all"),
1092
                                G_OBJECT_CLASS_TYPE (gobject_class),
1093 1094 1095 1096 1097
                                G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                                G_CALLBACK (gtk_text_view_select_all),
                                NULL, NULL,
                                _gtk_marshal_VOID__BOOLEAN,
                                G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
1098

Matthias Clasen's avatar
Matthias Clasen committed
1099 1100 1101 1102 1103 1104 1105 1106 1107 1108
  /**
   * GtkTextView::toggle-cursor-visible:
   * @text_view: the object which received the signal
   *
   * The ::toggle-cursor-visible signal is a 
   * <link linkend="keybinding-signals">keybinding signal</link> 
   * which gets emitted to toggle the visibility of the cursor.
   *
   * The default binding for this signal is F7.
   */ 
1109
  signals[TOGGLE_CURSOR_VISIBLE] =
1110
    g_signal_new_class_handler (I_("toggle-cursor-visible"),
1111
                                G_OBJECT_CLASS_TYPE (gobject_class),
1112 1113 1114 1115 1116
                                G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                                G_CALLBACK (gtk_text_view_toggle_cursor_visible),
                                NULL, NULL,
                                _gtk_marshal_VOID__VOID,
                                G_TYPE_NONE, 0);
1117

1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133
  /**
   * GtkTextView::preedit-changed:
   * @text_view: the object which received the signal
   * @preedit: the current preedit string
   *
   * If an input method is used, the typed text will not immediately
   * be committed to the buffer. So if you are interested in the text,
   * connect to this signal.
   *
   * This signal is only emitted if the text at the given position
   * is actually editable.
   *
   * Since: 2.20
   */
  signals[PREEDIT_CHANGED] =
    g_signal_new_class_handler (I_("preedit-changed"),
1134
                                G_OBJECT_CLASS_TYPE (gobject_class),
1135 1136 1137 1138 1139 1140 1141
                                G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                                NULL,
                                NULL, NULL,
                                _gtk_marshal_VOID__STRING,
                                G_TYPE_NONE, 1,
                                G_TYPE_STRING);

1142 1143 1144 1145 1146
  /*
   * Key bindings
   */

  binding_set = gtk_binding_set_by_class (klass);
1147
  
1148
  /* Moving the insertion point */
1149
  add_move_binding (binding_set, GDK_KEY_Right, 0,
1150
                    GTK_MOVEMENT_VISUAL_POSITIONS, 1);
1151

1152
  add_move_binding (binding_set, GDK_KEY_KP_Right, 0,
1153 1154
                    GTK_MOVEMENT_VISUAL_POSITIONS, 1);
  
1155
  add_move_binding (binding_set, GDK_KEY_Left, 0,
1156
                    GTK_MOVEMENT_VISUAL_POSITIONS, -1);
1157

1158
  add_move_binding (binding_set, GDK_KEY_KP_Left, 0,
1159 1160
                    GTK_MOVEMENT_VISUAL_POSITIONS, -1);
  
1161
  add_move_binding (binding_set, GDK_KEY_Right, GDK_CONTROL_MASK,
1162
                    GTK_MOVEMENT_WORDS, 1);
1163

1164
  add_move_binding (binding_set, GDK_KEY_KP_Right, GDK_CONTROL_MASK,
1165 1166
                    GTK_MOVEMENT_WORDS, 1);
  
1167
  add_move_binding (binding_set, GDK_KEY_Left, GDK_CONTROL_MASK,
1168 1169
                    GTK_MOVEMENT_WORDS, -1);

1170
  add_move_binding (binding_set, GDK_KEY_KP_Left, GDK_CONTROL_MASK,
1171
                    GTK_MOVEMENT_WORDS, -1);
1172
  
1173
  add_move_binding (binding_set, GDK_KEY_Up, 0,
1174 1175
                    GTK_MOVEMENT_DISPLAY_LINES, -1);

1176
  add_move_binding (binding_set, GDK_KEY_KP_Up, 0,
1177 1178
                    GTK_MOVEMENT_DISPLAY_LINES, -1);
  
1179
  add_move_binding (binding_set, GDK_KEY_Down, 0,
1180
                    GTK_MOVEMENT_DISPLAY_LINES, 1);
1181

1182
  add_move_binding (binding_set, GDK_KEY_KP_Down, 0,
1183 1184
                    GTK_MOVEMENT_DISPLAY_LINES, 1);
  
1185
  add_move_binding (binding_set, GDK_KEY_Up, GDK_CONTROL_MASK,
1186 1187
                    GTK_MOVEMENT_PARAGRAPHS, -1);

1188
  add_move_binding (binding_set, GDK_KEY_KP_Up, GDK_CONTROL_MASK,
1189 1190
                    GTK_MOVEMENT_PARAGRAPHS, -1);
  
1191
  add_move_binding (binding_set, GDK_KEY_Down, GDK_CONTROL_MASK,
1192 1193
                    GTK_MOVEMENT_PARAGRAPHS, 1);