gtktextview.c 284 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
#include <string.h>

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

54

55 56 57 58 59 60 61 62 63 64 65 66
/**
 * 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.
 */


67 68 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
/* 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.
 *
 */

102
#if 0
103 104
#define DEBUG_VALIDATION_AND_SCROLLING
#endif
105 106 107 108 109 110 111

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

112 113
#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)
114

115 116
#define SPACE_FOR_CURSOR 1

117 118
#define GTK_TEXT_VIEW_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_TEXT_VIEW, GtkTextViewPrivate))

119 120 121
typedef struct _GtkTextWindow GtkTextWindow;
typedef struct _GtkTextPendingScroll GtkTextPendingScroll;

122 123
struct _GtkTextViewPrivate 
{
124 125 126
  GtkTextLayout *layout;
  GtkTextBuffer *buffer;

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

133
  gulong selection_drag_handler;
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
  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;

150 151 152 153 154 155 156
  /* 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
157
   * to be changed to use GtkWidget     Iface and deserves
158 159 160 161
   * more attention.
   */
  GtkRequisition cached_size_request;

162 163 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
  /* 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;

224
  guint scroll_after_paste : 1;
225 226 227 228 229

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

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

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

261 262
enum
{
263 264 265 266 267 268 269 270 271 272 273 274
  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,
275
  PROP_BUFFER,
276
  PROP_OVERWRITE,
277
  PROP_ACCEPTS_TAB,
Tadej Borovšak's avatar
Tadej Borovšak committed
278 279
  PROP_IM_MODULE,
  PROP_HADJUSTMENT,
280 281 282
  PROP_VADJUSTMENT,
  PROP_HSCROLL_POLICY,
  PROP_VSCROLL_POLICY
283 284 285
};

static void gtk_text_view_finalize             (GObject          *object);
286 287 288 289 290 291 292 293
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);
294
static void gtk_text_view_destroy              (GtkWidget        *widget);
295
static void gtk_text_view_size_request         (GtkWidget        *widget,
296
                                                GtkRequisition   *requisition);
297 298 299 300 301 302
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);
303
static void gtk_text_view_size_allocate        (GtkWidget        *widget,
304
                                                GtkAllocation    *allocation);
305 306 307
static void gtk_text_view_realize              (GtkWidget        *widget);
static void gtk_text_view_unrealize            (GtkWidget        *widget);
static void gtk_text_view_style_set            (GtkWidget        *widget,
308
                                                GtkStyle         *previous_style);
309
static void gtk_text_view_direction_changed    (GtkWidget        *widget,
310
                                                GtkTextDirection  previous_direction);
311 312
static void gtk_text_view_grab_notify          (GtkWidget        *widget,
					        gboolean         was_grabbed);
313 314 315
static void gtk_text_view_state_changed        (GtkWidget        *widget,
					        GtkStateType      previous_state);

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

341 342 343

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

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

377
static gboolean gtk_text_view_popup_menu         (GtkWidget     *widget);
378

379 380 381 382
static void gtk_text_view_move_cursor       (GtkTextView           *text_view,
                                             GtkMovementStep        step,
                                             gint                   count,
                                             gboolean               extend_selection);
383
static gboolean gtk_text_view_move_viewport (GtkTextView           *text_view,
384 385
                                             GtkScrollStep          step,
                                             gint                   count);
386
static void gtk_text_view_set_anchor       (GtkTextView           *text_view);
387
static gboolean gtk_text_view_scroll_pages (GtkTextView           *text_view,
388 389
                                            gint                   count,
                                            gboolean               extend_selection);
390
static gboolean gtk_text_view_scroll_hpages(GtkTextView           *text_view,
391 392
                                            gint                   count,
                                            gboolean               extend_selection);
393
static void gtk_text_view_insert_at_cursor (GtkTextView           *text_view,
394
                                            const gchar           *str);
395 396 397
static void gtk_text_view_delete_from_cursor (GtkTextView           *text_view,
                                              GtkDeleteType          type,
                                              gint                   count);
398
static void gtk_text_view_backspace        (GtkTextView           *text_view);
399 400 401 402
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);
403
static void gtk_text_view_toggle_cursor_visible (GtkTextView      *text_view);
404

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

static void     gtk_text_view_validate_onscreen     (GtkTextView        *text_view);
static void     gtk_text_view_get_first_para_iter   (GtkTextView        *text_view,
409
                                                     GtkTextIter        *iter);
410
static void     gtk_text_view_update_layout_width       (GtkTextView        *text_view);
411 412 413
static void     gtk_text_view_set_attributes_from_style (GtkTextView        *text_view,
                                                         GtkTextAttributes *values,
                                                         GtkStyle           *style);
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 430 431 432 433
static void     gtk_text_view_value_changed                (GtkAdjustment *adj,
							    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 606 607
  widget_class->realize = gtk_text_view_realize;
  widget_class->unrealize = gtk_text_view_unrealize;
  widget_class->style_set = gtk_text_view_style_set;
  widget_class->direction_changed = gtk_text_view_direction_changed;
608
  widget_class->grab_notify = gtk_text_view_grab_notify;
609
  widget_class->state_changed = gtk_text_view_state_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,
1194 1195
                    GTK_MOVEMENT_PARAGRAPHS, 1);

1196
  add_move_binding (binding_set, GDK_KEY_KP_Down, GDK_CONTROL_MASK,
1197 1198
                    GTK_MOVEMENT_PARAGRAPHS, 1);
  
1199
  add_move_binding (binding_set, GDK_KEY_Home, 0,
1200
                    GTK_MOVEMENT_DISPLAY_LINE_ENDS, -1);