gtktextview.c 285 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 "gtkstock.h"
44
#include "gtktextbufferrichtext.h"
45 46 47
#include "gtktextdisplay.h"
#include "gtktextview.h"
#include "gtkimmulticontext.h"
48
#include "gtkprivate.h"
49
#include "gtktextutil.h"
Emmanuele Bassi's avatar
Emmanuele Bassi committed
50
#include "gtkwidgetprivate.h"
51
#include "gtkwindow.h"
52
#include "gtkscrollable.h"
53
#include "gtktypebuiltins.h"
54

55

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


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 102
/* 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.
 *
 */

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

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

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

116 117
#define SPACE_FOR_CURSOR 1

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

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

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

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

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

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

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 224
  /* 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;

225
  guint scroll_after_paste : 1;
226 227 228 229 230

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

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

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

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

static void gtk_text_view_finalize             (GObject          *object);
287 288 289 290 291 292 293 294
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);
295
static void gtk_text_view_destroy              (GtkWidget        *widget);
296
static void gtk_text_view_size_request         (GtkWidget        *widget,
297
                                                GtkRequisition   *requisition);
298 299 300 301 302 303
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);
304
static void gtk_text_view_size_allocate        (GtkWidget        *widget,
305
                                                GtkAllocation    *allocation);
306 307
static void gtk_text_view_realize              (GtkWidget        *widget);
static void gtk_text_view_unrealize            (GtkWidget        *widget);
308
static void gtk_text_view_style_updated        (GtkWidget        *widget);
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
static void gtk_text_view_state_flags_changed  (GtkWidget        *widget,
					        GtkStateFlags     previous_state);
315

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);
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
static void     gtk_text_view_set_attributes_from_style (GtkTextView        *text_view,
412
                                                         GtkTextAttributes  *values);
413 414 415 416 417 418
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);
419
static gboolean gtk_text_view_end_selection_drag     (GtkTextView        *text_view);
420 421 422 423 424 425
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);
426
static void     gtk_text_view_reset_blink_time       (GtkTextView        *text_view);
427

428 429 430 431 432
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);
433 434
static void     gtk_text_view_commit_text                  (GtkTextView   *text_view,
                                                            const gchar   *text);
435 436 437 438 439 440 441 442
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);
443 444

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

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

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

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

480 481 482 483 484 485 486
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);

487 488
static void gtk_text_view_update_im_spot_location (GtkTextView *text_view);

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

/* FIXME probably need the focus methods. */

typedef struct _GtkTextViewChild GtkTextViewChild;

struct _GtkTextViewChild
{
  GtkWidget *widget;

  GtkTextChildAnchor *anchor;

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

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

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

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

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


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

562 563
G_DEFINE_TYPE_WITH_CODE (GtkTextView, gtk_text_view, GTK_TYPE_CONTAINER,
			 G_IMPLEMENT_INTERFACE (GTK_TYPE_SCROLLABLE, NULL))
564 565

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

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

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

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

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

602
  widget_class->destroy = gtk_text_view_destroy;
603 604
  widget_class->realize = gtk_text_view_realize;
  widget_class->unrealize = gtk_text_view_unrealize;
605
  widget_class->style_updated = gtk_text_view_style_updated;
606
  widget_class->direction_changed = gtk_text_view_direction_changed;
607
  widget_class->grab_notify = gtk_text_view_grab_notify;
608
  widget_class->state_flags_changed = gtk_text_view_state_flags_changed;
609 610
  widget_class->get_preferred_width = gtk_text_view_get_preferred_width;
  widget_class->get_preferred_height = gtk_text_view_get_preferred_height;
611 612 613 614 615 616 617 618 619
  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;
620
  widget_class->draw = gtk_text_view_draw;
621
  widget_class->focus = gtk_text_view_focus;
622 623 624 625 626 627 628 629 630 631
  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;

632 633
  widget_class->popup_menu = gtk_text_view_popup_menu;
  
634 635 636 637 638 639 640 641
  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;
642
  klass->backspace = gtk_text_view_backspace;
643 644 645 646 647
  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;

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

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

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

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

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

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

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

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

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

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

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

798
   /* GtkScrollable interface */
799 800 801 802
   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");
803

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1201
  add_move_binding (binding_set, GDK_KEY_KP_Home, 0,
1202 1203
                    GTK_MOVEMENT_DISPLAY_LINE_ENDS, -1);
  
1204
  add_move_binding (binding_set, GDK_KEY_End, 0,
1205 1206
                    GTK_MOVEMENT_DISPLAY_LINE_ENDS, 1);

1207
  add_move_binding (binding_set, GDK_KEY_KP_End, 0,
1208 1209
                    GTK_MOVEMENT_DISPLAY_LINE_ENDS, 1);
  
1210
  add_move_binding (binding_set, GDK_KEY_Home, GDK_CONTROL_MASK,
1211
                    GTK_MOVEMENT_BUFFER_ENDS, -1);
1212

1213
  add_move_binding (binding_set, GDK_KEY_KP_Home, GDK_CONTROL_MASK,
1214 1215
                    GTK_MOVEMENT_BUFFER_ENDS, -1);
  
1216
  add_move_binding (binding_set, GDK_KEY_End, GDK_CONTROL_MASK,
1217
                    GTK_MOVEMENT_BUFFER_ENDS, 1);
1218

1219
  add_move_binding (binding_set, GDK_KEY_KP_End, GDK_CONTROL_MASK,
1220 1221
                    GTK_MOVEMENT_BUFFER_ENDS, 1);
  
1222
  add_move_binding (binding_set, GDK_KEY_Page_Up, 0,
1223
                    GTK_MOVEMENT_PAGES, -1);
1224

1225
  add_move_binding (binding_set, GDK_KEY_KP_Page_Up, 0,
1226 1227
                    GTK_MOVEMENT_PAGES, -1);
  
1228
  add_move_binding (binding_set, GDK_KEY_Page_Down, 0,
1229 1230
                    GTK_MOVEMENT_PAGES, 1);

1231
  add_move_binding (binding_set, GDK_KEY_KP_Page_Down, 0,
1232
                    GTK_MOVEMENT_PAGES, 1);
1233

1234
  add_move_binding (binding_set, GDK_KEY_Page_Up, GDK_CONTROL_MASK,
1235 1236
                    GTK_MOVEMENT_HORIZONTAL_PAGES, -1);

1237
  add_move_binding (binding_set, GDK_KEY_KP_Page_Up, GDK_CONTROL_MASK,
1238 1239
                    GTK_MOVEMENT_HORIZONTAL_PAGES, -1);
  
1240
  add_move_binding (binding_set, GDK_KEY_Page_Down, GDK_CONTROL_MASK,
1241 1242
                    GTK_MOVEMENT_HORIZONTAL_PAGES, 1);

1243
  add_move_binding (binding_set, GDK_KEY_KP_Page_Down, GDK_CONTROL_MASK,
1244 1245
                    GTK_MOVEMENT_HORIZONTAL_PAGES, 1);

1246
  /* Select all */
1247
  gtk_binding_entry_add_signal (binding_set, GDK_KEY_a, GDK_CONTROL_MASK,
1248
				"select-all", 1,
1249
  				G_TYPE_BOOLEAN, TRUE);
1250

1251
  gtk_binding_entry_add_signal (binding_set, GDK_KEY_slash, GDK_CONTROL_MASK,
1252
				"select-all", 1,
1253 1254 1255
  				G_TYPE_BOOLEAN, TRUE);
  
  /* Unselect all */
1256
  gtk_binding_entry_add_signal (binding_set, GDK_KEY_backslash, GDK_CONTROL_MASK,
1257
				 "select-all", 1,
1258
				 G_TYPE_BOOLEAN, FALSE);
1259

1260
  gtk_binding_entry_add_signal (binding_set, GDK_KEY_a, GDK_SHIFT_MASK | GDK_CONTROL_MASK,
1261
				 "select-all", 1,
1262 1263
				 G_TYPE_BOOLEAN, FALSE);

1264
  /* Deleting text */
1265
  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Delete, 0,
1266
				"delete-from-cursor", 2,
Manish Singh's avatar
Manish Singh committed
1267 1268
				G_TYPE_ENUM, GTK_DELETE_CHARS,
				G_TYPE_INT, 1);
1269

1270
  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Delete, 0,
1271
				"delete-from-cursor", 2,
Manish Singh's avatar
Manish Singh committed
1272 1273
				G_TYPE_ENUM, GTK_DELETE_CHARS,
				G_TYPE_INT, 1);
1274
  
1275
  gtk_binding_entry_add_signal (binding_set, GDK_KEY_BackSpace, 0,
1276
				"backspace", 0);
1277

1278
  /* Make this do the same as Backspace, to help with mis-typing */
1279
  gtk_binding_entry_add_signal (binding_set, GDK_KEY_BackSpace, GDK_SHIFT_MASK,
1280
				"backspace", 0);
1281

1282
  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Delete, GDK_CONTROL_MASK,
1283
				"delete-from-cursor", 2,
Manish Singh's avatar
Manish Singh committed
1284 1285
				G_TYPE_ENUM, GTK_DELETE_WORD_ENDS,
				G_TYPE_INT, 1);
1286

1287
  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Delete, GDK_CONTROL_MASK,
1288
				"delete-from-cursor", 2,
Manish Singh's avatar
Manish Singh committed
1289 1290
				G_TYPE_ENUM, GTK_DELETE_WORD_ENDS,
				G_TYPE_INT, 1);
1291