gtktextview.c 286 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 456
static void gtk_text_view_get_cursor_location    (GtkTextView       *text_view,
						  GdkRectangle      *pos);
457
static void gtk_text_view_get_virtual_cursor_pos (GtkTextView       *text_view,
458
                                                  GtkTextIter       *cursor,
459 460
                                                  gint              *x,
                                                  gint              *y);
461
static void gtk_text_view_set_virtual_cursor_pos (GtkTextView       *text_view,
462 463
                                                  gint               x,
                                                  gint               y);
464

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

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

476 477 478 479
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);
480

Tadej Borovšak's avatar
Tadej Borovšak committed
481 482 483 484 485 486 487
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);

488 489
static void gtk_text_view_update_im_spot_location (GtkTextView *text_view);

490 491 492 493 494 495 496
/* 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,
497
                                  GtkCallback   callback,
498 499 500 501 502 503 504 505 506 507 508 509
                                  gpointer      callback_data);

/* FIXME probably need the focus methods. */

typedef struct _GtkTextViewChild GtkTextViewChild;

struct _GtkTextViewChild
{
  GtkWidget *widget;

  GtkTextChildAnchor *anchor;

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

519 520 521 522 523 524 525 526 527 528
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);
529

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

540 541 542 543 544 545
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,
546
                                                   GtkWidget         *widget);
547 548 549 550 551 552 553 554
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);
555
static void           text_window_invalidate_cursors (GtkTextWindow  *win);
556 557 558

static gint           text_window_get_width       (GtkTextWindow     *win);
static gint           text_window_get_height      (GtkTextWindow     *win);
559 560


561 562
static guint signals[LAST_SIGNAL] = { 0 };

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

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

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

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

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

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

603
  widget_class->destroy = gtk_text_view_destroy;
604 605
  widget_class->realize = gtk_text_view_realize;
  widget_class->unrealize = gtk_text_view_unrealize;
606
  widget_class->style_updated = gtk_text_view_style_updated;
607
  widget_class->direction_changed = gtk_text_view_direction_changed;
608
  widget_class->grab_notify = gtk_text_view_grab_notify;
609
  widget_class->state_flags_changed = gtk_text_view_state_flags_changed;
610 611
  widget_class->get_preferred_width = gtk_text_view_get_preferred_width;
  widget_class->get_preferred_height = gtk_text_view_get_preferred_height;
612 613 614 615 616 617 618 619 620
  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
621
  widget_class->draw = gtk_text_view_draw;
622
  widget_class->focus = gtk_text_view_focus;
623 624 625 626 627 628 629 630 631 632
  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
633 634
  widget_class->popup_menu = gtk_text_view_popup_menu;
  
635 636 637 638 639 640 641 642
  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;
643
  klass->backspace = gtk_text_view_backspace;
644 645 646 647 648
  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;

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

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

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

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

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

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

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

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

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

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

779 780 781
   /**
    * GtkTextView:im-module:
    *
782 783
    * Which IM (input method) module should be used for this entry. 
    * See #GtkIMContext.
784 785
    *
    * Setting this to a non-%NULL value overrides the
786 787
    * system-wide IM module setting. See the GtkSettings 
    * #GtkSettings:gtk-im-module property.
788 789 790 791 792 793 794 795 796 797 798
    *
    * 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
799
   /* GtkScrollable interface */
800 801 802 803
   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
804

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

819 820
  /**
   * GtkTextView::move-cursor: 
Matthias Clasen's avatar
Matthias Clasen committed
821
   * @text_view: the object which received the signal
822 823 824 825
   * @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
826 827 828 829 830
   * 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.
831 832
   *
   * Applications should not connect to it, but may emit it with 
833
   * g_signal_emit_by_name() if they need to control the cursor
834
   * programmatically.
Matthias Clasen's avatar
Matthias Clasen committed
835 836 837 838 839 840 841 842 843 844 845 846
   *
   * 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>
847 848
   */
  signals[MOVE_CURSOR] = 
849
    g_signal_new (I_("move-cursor"),
850 851
		  G_OBJECT_CLASS_TYPE (gobject_class), 
		  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, 
Manish Singh's avatar
Manish Singh committed
852
		  G_STRUCT_OFFSET (GtkTextViewClass, move_cursor),
853 854
		  NULL, NULL, 
		  _gtk_marshal_VOID__ENUM_INT_BOOLEAN, 
Manish Singh's avatar
Manish Singh committed
855
		  G_TYPE_NONE, 3,
856 857
		  GTK_TYPE_MOVEMENT_STEP, 
		  G_TYPE_INT, 
Manish Singh's avatar
Manish Singh committed
858
		  G_TYPE_BOOLEAN);
859

Matthias Clasen's avatar
Matthias Clasen committed
860 861 862 863 864 865 866 867 868 869 870 871 872 873
  /**
   * 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.
   */
874
  signals[MOVE_VIEWPORT] =
875
    g_signal_new_class_handler (I_("move-viewport"),
876 877 878 879 880 881 882 883
                                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);
884

Matthias Clasen's avatar
Matthias Clasen committed
885 886 887 888 889 890 891 892 893 894 895 896
  /**
   * 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.
   */   
897
  signals[SET_ANCHOR] =
898
    g_signal_new (I_("set-anchor"),
Manish Singh's avatar
Manish Singh committed
899 900 901 902 903 904
		  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);
905

Matthias Clasen's avatar
Matthias Clasen committed
906 907 908 909 910 911 912 913 914 915 916 917
  /**
   * 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.
   */
918
  signals[INSERT_AT_CURSOR] =
919
    g_signal_new (I_("insert-at-cursor"),
Manish Singh's avatar
Manish Singh committed
920 921 922 923 924 925 926
		  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);
927

Matthias Clasen's avatar
Matthias Clasen committed
928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946
  /**
   * 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.
   */
947
  signals[DELETE_FROM_CURSOR] =
948
    g_signal_new (I_("delete-from-cursor"),
Manish Singh's avatar
Manish Singh committed
949 950 951 952 953 954 955 956
		  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);
957

Matthias Clasen's avatar
Matthias Clasen committed
958 959 960 961 962 963 964 965 966 967 968
  /**
   * 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.
   */
969
  signals[BACKSPACE] =
Matthias Clasen's avatar
Matthias Clasen committed
970
    g_signal_new (I_("backspace"),
971 972 973 974 975 976 977
		  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
978 979 980 981 982 983 984 985 986 987 988
  /**
   * 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.
   */
989
  signals[CUT_CLIPBOARD] =
990
    g_signal_new (I_("cut-clipboard"),
Manish Singh's avatar
Manish Singh committed
991 992 993 994 995 996
		  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);
997

Matthias Clasen's avatar
Matthias Clasen committed
998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008
  /**
   * 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.
   */
1009
  signals[COPY_CLIPBOARD] =
1010
    g_signal_new (I_("copy-clipboard"),
Manish Singh's avatar
Manish Singh committed
1011 1012 1013 1014 1015 1016
		  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);
1017

Matthias Clasen's avatar
Matthias Clasen committed
1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029
  /**
   * 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.
   */
1030
  signals[PASTE_CLIPBOARD] =
1031
    g_signal_new (I_("paste-clipboard"),
Manish Singh's avatar
Manish Singh committed
1032 1033 1034 1035 1036 1037
		  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);
1038

Matthias Clasen's avatar
Matthias Clasen committed
1039 1040 1041 1042 1043 1044
  /**
   * 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
1045
   * which gets emitted to toggle the overwrite mode of the text view.
Matthias Clasen's avatar
Matthias Clasen committed
1046 1047 1048
   * 
   * The default bindings for this signal is Insert.
   */ 
1049
  signals[TOGGLE_OVERWRITE] =
1050
    g_signal_new (I_("toggle-overwrite"),
Manish Singh's avatar
Manish Singh committed
1051 1052 1053 1054 1055 1056
		  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);
1057

Matthias Clasen's avatar
Matthias Clasen committed
1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068
  /**
   * 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
1069
  signals[POPULATE_POPUP] =
1070
    g_signal_new (I_("populate-popup"),
Manish Singh's avatar
Manish Singh committed
1071 1072 1073 1074 1075 1076 1077
		  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
1078
  
Matthias Clasen's avatar
Matthias Clasen committed
1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091
  /**
   * 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.
   */
1092
  signals[SELECT_ALL] =
1093
    g_signal_new_class_handler (I_("select-all"),
1094
                                G_OBJECT_CLASS_TYPE (gobject_class),
1095 1096 1097 1098 1099
                                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);
1100

Matthias Clasen's avatar
Matthias Clasen committed
1101 1102 1103 1104 1105 1106 1107 1108 1109 1110
  /**
   * 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.
   */ 
1111
  signals[TOGGLE_CURSOR_VISIBLE] =
1112
    g_signal_new_class_handler (I_("toggle-cursor-visible"),
1113
                                G_OBJECT_CLASS_TYPE (gobject_class),
1114 1115 1116 1117 1118
                                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);
1119

1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135
  /**
   * 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"),
1136
                                G_OBJECT_CLASS_TYPE (gobject_class),
1137 1138 1139 1140 1141 1142 1143
                                G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                                NULL,
                                NULL, NULL,
                                _gtk_marshal_VOID__STRING,
                                G_TYPE_NONE, 1,
                                G_TYPE_STRING);

1144 1145 1146 1147 1148
  /*
   * Key bindings
   */

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

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

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

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

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

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

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

1190
  add_move_binding (binding_set, GDK_KEY_KP_Up, GDK_CONTROL_MASK,
1191 1192
                    GTK_MOVEMENT_PARAGRAPHS, -1);
  
1193
  add_move_binding (binding_set, GDK_KEY_Down, GDK_CONTROL_MASK,
Padraig O'Briain's avatar