gtktextview.c 254 KB
Newer Older
1 2
/* GTK - The GIMP Toolkit
 * gtktextview.c Copyright (C) 2000 Red Hat, Inc.
3
 *
4 5 6 7
 * 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.
8
 *
9 10
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 13 14 15 16 17 18 19 20 21 22 23
 * 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
24
 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
25 26
 */

27
#include <config.h>
28 29
#include <string.h>

30
#define GTK_TEXT_USE_INTERNAL_UNSUPPORTED_API
31 32
#include "gtkbindings.h"
#include "gtkdnd.h"
33
#include "gtkimagemenuitem.h"
Owen Taylor's avatar
Owen Taylor committed
34
#include "gtkintl.h"
35
#include "gtkmain.h"
36
#include "gtkmarshalers.h"
Owen Taylor's avatar
Owen Taylor committed
37 38
#include "gtkmenu.h"
#include "gtkmenuitem.h"
39
#include "gtkseparatormenuitem.h"
40
#include "gtksettings.h"
41
#include "gtkstock.h"
42 43 44 45
#include "gtktextdisplay.h"
#include "gtktextview.h"
#include "gtkimmulticontext.h"
#include "gdk/gdkkeysyms.h"
46
#include "gtkprivate.h"
47
#include "gtksizegroup.h"          /* FIXME http://bugzilla.gnome.org/show_bug.cgi?id=72258 */
48
#include "gtktextutil.h"
49
#include "gtkwindow.h"
50
#include "gtkalias.h"
51

52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
/* 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.
 *
 */

87
#if 0
88 89
#define DEBUG_VALIDATION_AND_SCROLLING
#endif
90 91 92 93 94 95 96

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

97 98 99
#define SCREEN_WIDTH(widget) text_window_get_width (GTK_TEXT_VIEW (widget)->text_window)
#define SCREEN_HEIGHT(widget) text_window_get_height (GTK_TEXT_VIEW (widget)->text_window)

100 101
#define SPACE_FOR_CURSOR 1

102 103 104 105 106 107 108 109 110
struct _GtkTextPendingScroll
{
  GtkTextMark   *mark;
  gdouble        within_margin;
  gboolean       use_align;
  gdouble        xalign;
  gdouble        yalign;
};
  
111 112
enum
{
Owen Taylor's avatar
Owen Taylor committed
113 114
  SET_SCROLL_ADJUSTMENTS,
  POPULATE_POPUP,
115
  MOVE_CURSOR,
116
  PAGE_HORIZONTALLY,
117
  SET_ANCHOR,
118
  INSERT_AT_CURSOR,
119
  DELETE_FROM_CURSOR,
120
  BACKSPACE,
121 122 123
  CUT_CLIPBOARD,
  COPY_CLIPBOARD,
  PASTE_CLIPBOARD,
124
  TOGGLE_OVERWRITE,
125
  MOVE_FOCUS,
126
  MOVE_VIEWPORT,
127
  SELECT_ALL,
128 129 130
  LAST_SIGNAL
};

131 132
enum
{
133 134 135 136 137 138 139 140 141 142 143 144
  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,
145
  PROP_BUFFER,
146
  PROP_OVERWRITE,
147
  PROP_ACCEPTS_TAB,
148
  LAST_PROP
149 150 151 152 153 154
};

static void gtk_text_view_init                 (GtkTextView      *text_view);
static void gtk_text_view_class_init           (GtkTextViewClass *klass);
static void gtk_text_view_destroy              (GtkObject        *object);
static void gtk_text_view_finalize             (GObject          *object);
155 156 157 158 159 160 161 162
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);
163
static void gtk_text_view_size_request         (GtkWidget        *widget,
164
                                                GtkRequisition   *requisition);
165
static void gtk_text_view_size_allocate        (GtkWidget        *widget,
166
                                                GtkAllocation    *allocation);
167 168 169
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,
170
                                                GtkStyle         *previous_style);
171
static void gtk_text_view_direction_changed    (GtkWidget        *widget,
172
                                                GtkTextDirection  previous_direction);
173 174
static void gtk_text_view_grab_notify          (GtkWidget        *widget,
					        gboolean         was_grabbed);
175 176 177
static void gtk_text_view_state_changed        (GtkWidget        *widget,
					        GtkStateType      previous_state);

178
static gint gtk_text_view_event                (GtkWidget        *widget,
179
                                                GdkEvent         *event);
180
static gint gtk_text_view_key_press_event      (GtkWidget        *widget,
181
                                                GdkEventKey      *event);
182
static gint gtk_text_view_key_release_event    (GtkWidget        *widget,
183
                                                GdkEventKey      *event);
184
static gint gtk_text_view_button_press_event   (GtkWidget        *widget,
185
                                                GdkEventButton   *event);
186
static gint gtk_text_view_button_release_event (GtkWidget        *widget,
187
                                                GdkEventButton   *event);
188
static gint gtk_text_view_focus_in_event       (GtkWidget        *widget,
189
                                                GdkEventFocus    *event);
190
static gint gtk_text_view_focus_out_event      (GtkWidget        *widget,
191
                                                GdkEventFocus    *event);
192
static gint gtk_text_view_motion_event         (GtkWidget        *widget,
193
                                                GdkEventMotion   *event);
194
static gint gtk_text_view_expose_event         (GtkWidget        *widget,
195
                                                GdkEventExpose   *expose);
196
static void gtk_text_view_draw_focus           (GtkWidget        *widget);
197 198
static gboolean gtk_text_view_focus            (GtkWidget        *widget,
                                                GtkDirectionType  direction);
199 200
static void gtk_text_view_select_all           (GtkWidget        *widget,
                                                gboolean          select);
201

202 203 204

/* Source side drag signals */
static void gtk_text_view_drag_begin       (GtkWidget        *widget,
205
                                            GdkDragContext   *context);
206
static void gtk_text_view_drag_end         (GtkWidget        *widget,
207
                                            GdkDragContext   *context);
208
static void gtk_text_view_drag_data_get    (GtkWidget        *widget,
209 210 211 212
                                            GdkDragContext   *context,
                                            GtkSelectionData *selection_data,
                                            guint             info,
                                            guint             time);
213
static void gtk_text_view_drag_data_delete (GtkWidget        *widget,
214
                                            GdkDragContext   *context);
215 216 217

/* Target side drag signals */
static void     gtk_text_view_drag_leave         (GtkWidget        *widget,
218 219
                                                  GdkDragContext   *context,
                                                  guint             time);
220
static gboolean gtk_text_view_drag_motion        (GtkWidget        *widget,
221 222 223 224
                                                  GdkDragContext   *context,
                                                  gint              x,
                                                  gint              y,
                                                  guint             time);
225
static gboolean gtk_text_view_drag_drop          (GtkWidget        *widget,
226 227 228 229
                                                  GdkDragContext   *context,
                                                  gint              x,
                                                  gint              y,
                                                  guint             time);
230
static void     gtk_text_view_drag_data_received (GtkWidget        *widget,
231 232 233 234 235 236
                                                  GdkDragContext   *context,
                                                  gint              x,
                                                  gint              y,
                                                  GtkSelectionData *selection_data,
                                                  guint             info,
                                                  guint             time);
237 238

static void gtk_text_view_set_scroll_adjustments (GtkTextView   *text_view,
239 240
                                                  GtkAdjustment *hadj,
                                                  GtkAdjustment *vadj);
241
static gboolean gtk_text_view_popup_menu         (GtkWidget     *widget);
242

243 244 245 246 247 248 249
static void gtk_text_view_move_cursor       (GtkTextView           *text_view,
                                             GtkMovementStep        step,
                                             gint                   count,
                                             gboolean               extend_selection);
static void gtk_text_view_page_horizontally (GtkTextView          *text_view,
                                             gint                  count,
                                             gboolean              extend_selection);
250 251 252
static void gtk_text_view_move_viewport     (GtkTextView           *text_view,
                                             GtkScrollStep          step,
                                             gint                   count);
253 254
static void gtk_text_view_set_anchor       (GtkTextView           *text_view);
static void gtk_text_view_scroll_pages     (GtkTextView           *text_view,
255 256
                                            gint                   count,
                                            gboolean               extend_selection);
257
static void gtk_text_view_scroll_hpages    (GtkTextView           *text_view,
258 259
                                            gint                   count,
                                            gboolean               extend_selection);
260
static void gtk_text_view_insert_at_cursor (GtkTextView           *text_view,
261
                                            const gchar           *str);
262 263 264
static void gtk_text_view_delete_from_cursor (GtkTextView           *text_view,
                                              GtkDeleteType          type,
                                              gint                   count);
265
static void gtk_text_view_backspace        (GtkTextView           *text_view);
266 267 268 269
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);
270 271
static void gtk_text_view_move_focus       (GtkTextView           *text_view,
                                            GtkDirectionType       direction_type);
272
static void gtk_text_view_unselect         (GtkTextView           *text_view);
273 274 275

static void     gtk_text_view_validate_onscreen     (GtkTextView        *text_view);
static void     gtk_text_view_get_first_para_iter   (GtkTextView        *text_view,
276
                                                     GtkTextIter        *iter);
277
static void     gtk_text_view_update_layout_width       (GtkTextView        *text_view);
278 279 280
static void     gtk_text_view_set_attributes_from_style (GtkTextView        *text_view,
                                                         GtkTextAttributes *values,
                                                         GtkStyle           *style);
281 282 283 284 285 286 287 288 289 290 291 292 293 294 295
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_reset_im_context       (GtkTextView        *text_view);
static void     gtk_text_view_start_selection_drag   (GtkTextView        *text_view,
                                                      const GtkTextIter  *iter,
                                                      GdkEventButton     *event);
static gboolean gtk_text_view_end_selection_drag     (GtkTextView        *text_view,
                                                      GdkEventButton     *event);
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);
296

297 298 299 300 301
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);
302 303
static void     gtk_text_view_commit_text                  (GtkTextView   *text_view,
                                                            const gchar   *text);
304 305 306 307 308 309 310 311
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);
312 313

static void gtk_text_view_mark_set_handler       (GtkTextBuffer     *buffer,
314
                                                  const GtkTextIter *location,
Havoc Pennington's avatar
Havoc Pennington committed
315
                                                  GtkTextMark       *mark,
316
                                                  gpointer           data);
317 318
static void gtk_text_view_get_cursor_location    (GtkTextView       *text_view,
						  GdkRectangle      *pos);
319
static void gtk_text_view_get_virtual_cursor_pos (GtkTextView       *text_view,
320 321
                                                  gint              *x,
                                                  gint              *y);
322
static void gtk_text_view_set_virtual_cursor_pos (GtkTextView       *text_view,
323 324
                                                  gint               x,
                                                  gint               y);
325

326 327 328
static GtkAdjustment* get_hadjustment            (GtkTextView       *text_view);
static GtkAdjustment* get_vadjustment            (GtkTextView       *text_view);

Owen Taylor's avatar
Owen Taylor committed
329
static void gtk_text_view_do_popup               (GtkTextView       *text_view,
Owen Taylor's avatar
Owen Taylor committed
330
						  GdkEventButton    *event);
331

332 333 334 335 336 337 338
static void gtk_text_view_queue_scroll           (GtkTextView   *text_view,
                                                  GtkTextMark   *mark,
                                                  gdouble        within_margin,
                                                  gboolean       use_align,
                                                  gdouble        xalign,
                                                  gdouble        yalign);

339 340 341 342
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);
343

344 345
static void gtk_text_view_update_im_spot_location (GtkTextView *text_view);

346 347 348 349 350 351 352
/* 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,
353
                                  GtkCallback   callback,
354 355 356 357 358 359 360 361 362 363 364 365
                                  gpointer      callback_data);

/* FIXME probably need the focus methods. */

typedef struct _GtkTextViewChild GtkTextViewChild;

struct _GtkTextViewChild
{
  GtkWidget *widget;

  GtkTextChildAnchor *anchor;

366 367 368
  gint from_top_of_line;
  gint from_left_of_buffer;
  
369 370 371 372 373 374
  /* These are ignored if anchor != NULL */
  GtkTextWindowType type;
  gint x;
  gint y;
};

375 376 377 378 379 380 381 382 383 384
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);
385

386 387 388 389 390 391 392 393 394 395
struct _GtkTextWindow
{
  GtkTextWindowType type;
  GtkWidget *widget;
  GdkWindow *window;
  GdkWindow *bin_window;
  GtkRequisition requisition;
  GdkRectangle allocation;
};

396 397 398 399 400 401 402 403 404 405 406 407 408 409 410
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,
                                                   GdkWindow         *parent);
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);
411
static void           text_window_invalidate_cursors (GtkTextWindow  *win);
412 413 414

static gint           text_window_get_width       (GtkTextWindow     *win);
static gint           text_window_get_height      (GtkTextWindow     *win);
415 416


417
static const GtkTargetEntry target_table[] = {
418
  { "GTK_TEXT_BUFFER_CONTENTS", GTK_TARGET_SAME_APP, 0 },
419 420 421 422 423
};

static GtkContainerClass *parent_class = NULL;
static guint signals[LAST_SIGNAL] = { 0 };

Manish Singh's avatar
Manish Singh committed
424
GType
425 426
gtk_text_view_get_type (void)
{
Manish Singh's avatar
Manish Singh committed
427
  static GType our_type = 0;
428 429 430

  if (our_type == 0)
    {
Manish Singh's avatar
Manish Singh committed
431
      static const GTypeInfo our_info =
432
      {
Manish Singh's avatar
Manish Singh committed
433 434 435 436 437 438 439 440 441
	sizeof (GtkTextViewClass),
	NULL,		/* base_init */
	NULL,		/* base_finalize */
	(GClassInitFunc) gtk_text_view_class_init,
	NULL,		/* class_finalize */
	NULL,		/* class_data */
	sizeof (GtkTextView),
	0,		/* n_preallocs */
	(GInstanceInitFunc) gtk_text_view_init,
442 443
      };

Matthias Clasen's avatar
Matthias Clasen committed
444
      our_type = g_type_register_static (GTK_TYPE_CONTAINER, I_("GtkTextView"),
Manish Singh's avatar
Manish Singh committed
445
					 &our_info, 0);
446
    }
447 448 449 450 451

  return our_type;
}

static void
452
add_move_binding (GtkBindingSet  *binding_set,
453 454 455 456
                  guint           keyval,
                  guint           modmask,
                  GtkMovementStep step,
                  gint            count)
457
{
458
  g_assert ((modmask & GDK_SHIFT_MASK) == 0);
459

460
  gtk_binding_entry_add_signal (binding_set, keyval, modmask,
461
                                "move_cursor", 3,
Manish Singh's avatar
Manish Singh committed
462 463 464
                                G_TYPE_ENUM, step,
                                G_TYPE_INT, count,
                                G_TYPE_BOOLEAN, FALSE);
465 466 467

  /* Selection-extending version */
  gtk_binding_entry_add_signal (binding_set, keyval, modmask | GDK_SHIFT_MASK,
468
                                "move_cursor", 3,
Manish Singh's avatar
Manish Singh committed
469 470 471
                                G_TYPE_ENUM, step,
                                G_TYPE_INT, count,
                                G_TYPE_BOOLEAN, TRUE);
472 473 474 475 476 477 478 479
}

static void
gtk_text_view_class_init (GtkTextViewClass *klass)
{
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
  GtkObjectClass *object_class = GTK_OBJECT_CLASS (klass);
  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
480
  GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
481
  GtkBindingSet *binding_set;
482

Manish Singh's avatar
Manish Singh committed
483
  parent_class = g_type_class_peek_parent (klass);
484

485 486
  /* Default handlers and virtual methods
   */
487 488
  gobject_class->set_property = gtk_text_view_set_property;
  gobject_class->get_property = gtk_text_view_get_property;
489 490 491 492 493 494 495 496

  object_class->destroy = gtk_text_view_destroy;
  gobject_class->finalize = gtk_text_view_finalize;

  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;
497
  widget_class->grab_notify = gtk_text_view_grab_notify;
498
  widget_class->state_changed = gtk_text_view_state_changed;
499 500 501 502 503 504 505 506 507 508 509
  widget_class->size_request = gtk_text_view_size_request;
  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;
  widget_class->expose_event = gtk_text_view_expose_event;
510
  widget_class->focus = gtk_text_view_focus;
511
  
512 513 514 515 516 517 518 519 520 521
  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
522 523
  widget_class->popup_menu = gtk_text_view_popup_menu;
  
524 525 526 527 528
  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;
529
  klass->page_horizontally = gtk_text_view_page_horizontally;
530 531 532
  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;
533
  klass->backspace = gtk_text_view_backspace;
534 535 536 537
  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;
538
  klass->move_focus = gtk_text_view_move_focus;
539 540
  klass->set_scroll_adjustments = gtk_text_view_set_scroll_adjustments;

541
  /*
542
   * Properties
543
   */
544 545 546
 
  g_object_class_install_property (gobject_class,
                                   PROP_PIXELS_ABOVE_LINES,
Matthias Clasen's avatar
x  
Matthias Clasen committed
547
                                   g_param_spec_int ("pixels-above-lines",
548 549
						     P_("Pixels Above Lines"),
						     P_("Pixels of blank space above paragraphs"),
550 551 552
						     0,
						     G_MAXINT,
						     0,
553
						     GTK_PARAM_READWRITE));
554 555 556
 
  g_object_class_install_property (gobject_class,
                                   PROP_PIXELS_BELOW_LINES,
Matthias Clasen's avatar
x  
Matthias Clasen committed
557
                                   g_param_spec_int ("pixels-below-lines",
558 559
						     P_("Pixels Below Lines"),
						     P_("Pixels of blank space below paragraphs"),
560 561 562
						     0,
						     G_MAXINT,
						     0,
563
						     GTK_PARAM_READWRITE));
564 565 566
 
  g_object_class_install_property (gobject_class,
                                   PROP_PIXELS_INSIDE_WRAP,
Matthias Clasen's avatar
x  
Matthias Clasen committed
567
                                   g_param_spec_int ("pixels-inside-wrap",
568 569
						     P_("Pixels Inside Wrap"),
						     P_("Pixels of blank space between wrapped lines in a paragraph"),
570 571 572
						     0,
						     G_MAXINT,
						     0,
573
						     GTK_PARAM_READWRITE));
574 575 576 577

  g_object_class_install_property (gobject_class,
                                   PROP_EDITABLE,
                                   g_param_spec_boolean ("editable",
578 579
							 P_("Editable"),
							 P_("Whether the text can be modified by the user"),
580
							 TRUE,
581
							 GTK_PARAM_READWRITE));
582 583 584

  g_object_class_install_property (gobject_class,
                                   PROP_WRAP_MODE,
Matthias Clasen's avatar
x  
Matthias Clasen committed
585
                                   g_param_spec_enum ("wrap-mode",
586 587
						      P_("Wrap Mode"),
						      P_("Whether to wrap lines never, at word boundaries, or at character boundaries"),
588 589
						      GTK_TYPE_WRAP_MODE,
						      GTK_WRAP_NONE,
590
						      GTK_PARAM_READWRITE));
591 592 593 594
 
  g_object_class_install_property (gobject_class,
                                   PROP_JUSTIFICATION,
                                   g_param_spec_enum ("justification",
595 596
						      P_("Justification"),
						      P_("Left, right, or center justification"),
597 598
						      GTK_TYPE_JUSTIFICATION,
						      GTK_JUSTIFY_LEFT,
599
						      GTK_PARAM_READWRITE));
600 601 602
 
  g_object_class_install_property (gobject_class,
                                   PROP_LEFT_MARGIN,
Matthias Clasen's avatar
x  
Matthias Clasen committed
603
                                   g_param_spec_int ("left-margin",
604 605
						     P_("Left Margin"),
						     P_("Width of the left margin in pixels"),
606 607 608
						     0,
						     G_MAXINT,
						     0,
609
						     GTK_PARAM_READWRITE));
610 611 612

  g_object_class_install_property (gobject_class,
                                   PROP_RIGHT_MARGIN,
Matthias Clasen's avatar
x  
Matthias Clasen committed
613
                                   g_param_spec_int ("right-margin",
614 615
						     P_("Right Margin"),
						     P_("Width of the right margin in pixels"),
616 617 618
						     0,
						     G_MAXINT,
						     0,
619
						     GTK_PARAM_READWRITE));
620 621 622 623

  g_object_class_install_property (gobject_class,
                                   PROP_INDENT,
                                   g_param_spec_int ("indent",
624 625
						     P_("Indent"),
						     P_("Amount to indent the paragraph, in pixels"),
626 627 628
						     0,
						     G_MAXINT,
						     0,
629
						     GTK_PARAM_READWRITE));
630 631 632 633

  g_object_class_install_property (gobject_class,
                                   PROP_TABS,
                                   g_param_spec_boxed ("tabs",
634 635
                                                       P_("Tabs"),
                                                       P_("Custom tabs for this text"),
636
                                                       PANGO_TYPE_TAB_ARRAY,
637
						       GTK_PARAM_READWRITE));
638 639 640

  g_object_class_install_property (gobject_class,
                                   PROP_CURSOR_VISIBLE,
Matthias Clasen's avatar
x  
Matthias Clasen committed
641
                                   g_param_spec_boolean ("cursor-visible",
642 643
							 P_("Cursor Visible"),
							 P_("If the insertion cursor is shown"),
644
							 TRUE,
645
							 GTK_PARAM_READWRITE));
646

647 648 649
  g_object_class_install_property (gobject_class,
                                   PROP_BUFFER,
                                   g_param_spec_object ("buffer",
650 651
							P_("Buffer"),
							P_("The buffer which is displayed"),
652
							GTK_TYPE_TEXT_BUFFER,
653
							GTK_PARAM_READWRITE));
654

655 656 657
  g_object_class_install_property (gobject_class,
                                   PROP_OVERWRITE,
                                   g_param_spec_boolean ("overwrite",
658 659
							 P_("Overwrite mode"),
							 P_("Whether entered text overwrites existing contents"),
660
							 FALSE,
661
							 GTK_PARAM_READWRITE));
662

663
  g_object_class_install_property (gobject_class,
664
                                   PROP_ACCEPTS_TAB,
Matthias Clasen's avatar
x  
Matthias Clasen committed
665
                                   g_param_spec_boolean ("accepts-tab",
666 667
							 P_("Accepts tab"),
							 P_("Whether Tab will result in a tab character being entered"),
668
							 TRUE,
669
							 GTK_PARAM_READWRITE));
670

671 672 673 674 675
  /*
   * Style properties
   */
  gtk_widget_class_install_style_property (widget_class,
					   g_param_spec_boxed ("error-underline-color",
676
							       P_("Error underline color"),
Owen Taylor's avatar
Owen Taylor committed
677
							       P_("Color with which to draw error-indication underlines"),
678
							       GDK_TYPE_COLOR,
679
							       GTK_PARAM_READABLE));
680
  
681 682 683 684
  /*
   * Signals
   */

685 686 687 688 689 690 691 692
  /**
   * GtkTextView::move-cursor: 
   * @widget: the object which received the signal
   * @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
   *  
   * The ::move-cursor signal is a keybinding signal which gets emitted
693 694 695 696 697 698
   * when the user initiates a cursor movement. 
   *
   * Applications should not connect to it, but may emit it with 
   * g_signal_emit_by_name() if they need to control scrolling 
   * programmatically.
   *
699 700
   */
  signals[MOVE_CURSOR] = 
Matthias Clasen's avatar
Matthias Clasen committed
701
    g_signal_new (I_("move_cursor"),
702 703
		  G_OBJECT_CLASS_TYPE (gobject_class), 
		  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, 
Manish Singh's avatar
Manish Singh committed
704
		  G_STRUCT_OFFSET (GtkTextViewClass, move_cursor),
705 706
		  NULL, NULL, 
		  _gtk_marshal_VOID__ENUM_INT_BOOLEAN, 
Manish Singh's avatar
Manish Singh committed
707
		  G_TYPE_NONE, 3,
708 709
		  GTK_TYPE_MOVEMENT_STEP, 
		  G_TYPE_INT, 
Manish Singh's avatar
Manish Singh committed
710
		  G_TYPE_BOOLEAN);
711

712
  signals[PAGE_HORIZONTALLY] =
Matthias Clasen's avatar
Matthias Clasen committed
713
    g_signal_new (I_("page_horizontally"),
Manish Singh's avatar
Manish Singh committed
714 715 716 717 718 719 720 721
		  G_OBJECT_CLASS_TYPE (gobject_class),
		  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
		  G_STRUCT_OFFSET (GtkTextViewClass, page_horizontally),
		  NULL, NULL,
		  _gtk_marshal_VOID__INT_BOOLEAN,
		  G_TYPE_NONE, 2,
		  G_TYPE_INT,
		  G_TYPE_BOOLEAN);
722
  
723
  signals[MOVE_VIEWPORT] =
Matthias Clasen's avatar
Matthias Clasen committed
724
    _gtk_binding_signal_new (I_("move_viewport"),
725 726 727 728 729 730 731 732 733
			     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);

734
  signals[SET_ANCHOR] =
Matthias Clasen's avatar
Matthias Clasen committed
735
    g_signal_new (I_("set_anchor"),
Manish Singh's avatar
Manish Singh committed
736 737 738 739 740 741
		  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);
742 743

  signals[INSERT_AT_CURSOR] =
Matthias Clasen's avatar
Matthias Clasen committed
744
    g_signal_new (I_("insert_at_cursor"),
Manish Singh's avatar
Manish Singh committed
745 746 747 748 749 750 751
		  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);
752

753
  signals[DELETE_FROM_CURSOR] =
Matthias Clasen's avatar
Matthias Clasen committed
754
    g_signal_new (I_("delete_from_cursor"),
Manish Singh's avatar
Manish Singh committed
755 756 757 758 759 760 761 762
		  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);
763

764
  signals[BACKSPACE] =
Matthias Clasen's avatar
Matthias Clasen committed
765
    g_signal_new (I_("backspace"),
766 767 768 769 770 771 772
		  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);

773
  signals[CUT_CLIPBOARD] =
Matthias Clasen's avatar
Matthias Clasen committed
774
    g_signal_new (I_("cut_clipboard"),
Manish Singh's avatar
Manish Singh committed
775 776 777 778 779 780
		  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);
781

782
  signals[COPY_CLIPBOARD] =
Matthias Clasen's avatar
Matthias Clasen committed
783
    g_signal_new (I_("copy_clipboard"),
Manish Singh's avatar
Manish Singh committed
784 785 786 787 788 789
		  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);
790

791
  signals[PASTE_CLIPBOARD] =
Matthias Clasen's avatar
Matthias Clasen committed
792
    g_signal_new (I_("paste_clipboard"),
Manish Singh's avatar
Manish Singh committed
793 794 795 796 797 798
		  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);
799 800

  signals[TOGGLE_OVERWRITE] =
Matthias Clasen's avatar
Matthias Clasen committed
801
    g_signal_new (I_("toggle_overwrite"),
Manish Singh's avatar
Manish Singh committed
802 803 804 805 806 807
		  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);
808

809
  signals[MOVE_FOCUS] =
Matthias Clasen's avatar
Matthias Clasen committed
810
    g_signal_new (I_("move_focus"),
Manish Singh's avatar
Manish Singh committed
811 812 813 814 815 816 817
		  G_OBJECT_CLASS_TYPE (gobject_class),
		  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
		  G_STRUCT_OFFSET (GtkTextViewClass, move_focus),
		  NULL, NULL,
		  _gtk_marshal_VOID__ENUM,
		  G_TYPE_NONE, 1,
		  GTK_TYPE_DIRECTION_TYPE);
818
  
819
  signals[SET_SCROLL_ADJUSTMENTS] =
Matthias Clasen's avatar
Matthias Clasen committed
820
    g_signal_new (I_("set_scroll_adjustments"),
Manish Singh's avatar
Manish Singh committed
821 822 823 824 825 826 827 828
		  G_OBJECT_CLASS_TYPE (gobject_class),
		  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
		  G_STRUCT_OFFSET (GtkTextViewClass, set_scroll_adjustments),
		  NULL, NULL,
		  _gtk_marshal_VOID__OBJECT_OBJECT,
		  G_TYPE_NONE, 2,
		  GTK_TYPE_ADJUSTMENT,
		  GTK_TYPE_ADJUSTMENT);
829
  widget_class->set_scroll_adjustments_signal = signals[SET_SCROLL_ADJUSTMENTS];
830

Owen Taylor's avatar
Owen Taylor committed
831
  signals[POPULATE_POPUP] =
Matthias Clasen's avatar
Matthias Clasen committed
832
    g_signal_new (I_("populate_popup"),
Manish Singh's avatar
Manish Singh committed
833 834 835 836 837 838 839
		  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
840
  
841
  signals[SELECT_ALL] =
Matthias Clasen's avatar
Matthias Clasen committed
842
    _gtk_binding_signal_new (I_("select_all"),
843 844 845 846 847 848 849 850 851
			     G_OBJECT_CLASS_TYPE (object_class),
			     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, TRUE);

  
852 853 854 855 856
  /*
   * Key bindings
   */

  binding_set = gtk_binding_set_by_class (klass);
857
  
858
  /* Moving the insertion point */
859
  add_move_binding (binding_set, GDK_Right, 0,
860
                    GTK_MOVEMENT_VISUAL_POSITIONS, 1);
861

862 863 864
  add_move_binding (binding_set, GDK_KP_Right, 0,
                    GTK_MOVEMENT_VISUAL_POSITIONS, 1);
  
865
  add_move_binding (binding_set, GDK_Left, 0,
866
                    GTK_MOVEMENT_VISUAL_POSITIONS, -1);
867

868 869 870
  add_move_binding (binding_set, GDK_KP_Left, 0,
                    GTK_MOVEMENT_VISUAL_POSITIONS, -1);
  
871
  add_move_binding (binding_set, GDK_Right, GDK_CONTROL_MASK,
872
                    GTK_MOVEMENT_WORDS, 1);
873

874 875 876
  add_move_binding (binding_set, GDK_KP_Right, GDK_CONTROL_MASK,
                    GTK_MOVEMENT_WORDS, 1);
  
877
  add_move_binding (binding_set, GDK_Left, GDK_CONTROL_MASK,
878 879
                    GTK_MOVEMENT_WORDS, -1);

880 881 882
  add_move_binding (binding_set, GDK_KP_Left, GDK_CONTROL_MASK,
                    GTK_MOVEMENT_WORDS, 1);
  
883
  add_move_binding (binding_set, GDK_Up, 0,
884 885
                    GTK_MOVEMENT_DISPLAY_LINES, -1);

886 887 888
  add_move_binding (binding_set, GDK_KP_Up, 0,
                    GTK_MOVEMENT_DISPLAY_LINES, -1);
  
889
  add_move_binding (binding_set, GDK_Down, 0,
890
                    GTK_MOVEMENT_DISPLAY_LINES, 1);
891