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

29 30
#include "gtkbindings.h"
#include "gtkdnd.h"
Owen Taylor's avatar
Owen Taylor committed
31
#include "gtkintl.h"
32
#include "gtkmain.h"
Owen Taylor's avatar
Owen Taylor committed
33 34
#include "gtkmenu.h"
#include "gtkmenuitem.h"
35
#include "gtkseparatormenuitem.h"
36
#include "gtksettings.h"
37 38 39 40 41
#include "gtksignal.h"
#include "gtktextdisplay.h"
#include "gtktextview.h"
#include "gtkimmulticontext.h"
#include "gdk/gdkkeysyms.h"
42
#include <string.h>
43

44 45 46 47 48 49 50 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
/* 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.
 *
 */

79 80
#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)
81

82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
/* #define DEBUG_VALIDATION_AND_SCROLLING */

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

struct _GtkTextPendingScroll
{
  GtkTextMark   *mark;
  gdouble        within_margin;
  gboolean       use_align;
  gdouble        xalign;
  gdouble        yalign;
};
  
99 100
enum
{
Owen Taylor's avatar
Owen Taylor committed
101 102
  SET_SCROLL_ADJUSTMENTS,
  POPULATE_POPUP,
103
  MOVE_CURSOR,
104
  SET_ANCHOR,
105
  INSERT_AT_CURSOR,
106
  DELETE_FROM_CURSOR,
107 108 109
  CUT_CLIPBOARD,
  COPY_CLIPBOARD,
  PASTE_CLIPBOARD,
110 111 112 113
  TOGGLE_OVERWRITE,
  LAST_SIGNAL
};

114 115
enum
{
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
  PROP_0,
  PROP_HEIGHT_LINES,
  PROP_WIDTH_COLUMNS,
  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,
  LAST_PROP
131 132 133 134 135 136
};

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);
137 138 139 140 141 142 143 144
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);
145
static void gtk_text_view_size_request         (GtkWidget        *widget,
146
                                                GtkRequisition   *requisition);
147
static void gtk_text_view_size_allocate        (GtkWidget        *widget,
148
                                                GtkAllocation    *allocation);
149 150 151
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,
152
                                                GtkStyle         *previous_style);
153
static void gtk_text_view_direction_changed    (GtkWidget        *widget,
154
                                                GtkTextDirection  previous_direction);
155
static gint gtk_text_view_event                (GtkWidget        *widget,
156
                                                GdkEvent         *event);
157
static gint gtk_text_view_key_press_event      (GtkWidget        *widget,
158
                                                GdkEventKey      *event);
159
static gint gtk_text_view_key_release_event    (GtkWidget        *widget,
160
                                                GdkEventKey      *event);
161
static gint gtk_text_view_button_press_event   (GtkWidget        *widget,
162
                                                GdkEventButton   *event);
163
static gint gtk_text_view_button_release_event (GtkWidget        *widget,
164
                                                GdkEventButton   *event);
165
static gint gtk_text_view_focus_in_event       (GtkWidget        *widget,
166
                                                GdkEventFocus    *event);
167
static gint gtk_text_view_focus_out_event      (GtkWidget        *widget,
168
                                                GdkEventFocus    *event);
169
static gint gtk_text_view_motion_event         (GtkWidget        *widget,
170
                                                GdkEventMotion   *event);
171
static gint gtk_text_view_expose_event         (GtkWidget        *widget,
172
                                                GdkEventExpose   *expose);
173
static void gtk_text_view_draw_focus           (GtkWidget        *widget);
174 175 176

/* Source side drag signals */
static void gtk_text_view_drag_begin       (GtkWidget        *widget,
177
                                            GdkDragContext   *context);
178
static void gtk_text_view_drag_end         (GtkWidget        *widget,
179
                                            GdkDragContext   *context);
180
static void gtk_text_view_drag_data_get    (GtkWidget        *widget,
181 182 183 184
                                            GdkDragContext   *context,
                                            GtkSelectionData *selection_data,
                                            guint             info,
                                            guint             time);
185
static void gtk_text_view_drag_data_delete (GtkWidget        *widget,
186
                                            GdkDragContext   *context);
187 188 189

/* Target side drag signals */
static void     gtk_text_view_drag_leave         (GtkWidget        *widget,
190 191
                                                  GdkDragContext   *context,
                                                  guint             time);
192
static gboolean gtk_text_view_drag_motion        (GtkWidget        *widget,
193 194 195 196
                                                  GdkDragContext   *context,
                                                  gint              x,
                                                  gint              y,
                                                  guint             time);
197
static gboolean gtk_text_view_drag_drop          (GtkWidget        *widget,
198 199 200 201
                                                  GdkDragContext   *context,
                                                  gint              x,
                                                  gint              y,
                                                  guint             time);
202
static void     gtk_text_view_drag_data_received (GtkWidget        *widget,
203 204 205 206 207 208
                                                  GdkDragContext   *context,
                                                  gint              x,
                                                  gint              y,
                                                  GtkSelectionData *selection_data,
                                                  guint             info,
                                                  guint             time);
209 210

static void gtk_text_view_set_scroll_adjustments (GtkTextView   *text_view,
211 212
                                                  GtkAdjustment *hadj,
                                                  GtkAdjustment *vadj);
Owen Taylor's avatar
Owen Taylor committed
213
static void gtk_text_view_popup_menu             (GtkWidget     *widget);
214

215
static void gtk_text_view_move_cursor      (GtkTextView           *text_view,
216 217 218
                                            GtkMovementStep        step,
                                            gint                   count,
                                            gboolean               extend_selection);
219 220
static void gtk_text_view_set_anchor       (GtkTextView           *text_view);
static void gtk_text_view_scroll_pages     (GtkTextView           *text_view,
221
                                            gint                   count);
222
static void gtk_text_view_insert_at_cursor (GtkTextView           *text_view,
223
                                            const gchar           *str);
224 225 226
static void gtk_text_view_delete_from_cursor (GtkTextView           *text_view,
                                              GtkDeleteType          type,
                                              gint                   count);
227 228 229 230
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);
231
static void gtk_text_view_unselect         (GtkTextView           *text_view);
232 233 234

static void     gtk_text_view_validate_onscreen     (GtkTextView        *text_view);
static void     gtk_text_view_get_first_para_iter   (GtkTextView        *text_view,
235
                                                     GtkTextIter        *iter);
236
static void     gtk_text_view_update_layout_width       (GtkTextView        *text_view);
237 238 239
static void     gtk_text_view_set_attributes_from_style (GtkTextView        *text_view,
                                                         GtkTextAttributes *values,
                                                         GtkStyle           *style);
240 241 242 243 244 245 246 247 248 249 250 251 252 253 254
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);
255

Owen Taylor's avatar
Owen Taylor committed
256 257 258 259 260 261 262
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);
static void gtk_text_view_preedit_changed_handler (GtkIMContext  *context,
						   GtkTextView   *text_view);
263 264

static void gtk_text_view_mark_set_handler       (GtkTextBuffer     *buffer,
265
                                                  const GtkTextIter *location,
Havoc Pennington's avatar
Havoc Pennington committed
266
                                                  GtkTextMark       *mark,
267
                                                  gpointer           data);
268
static void gtk_text_view_get_virtual_cursor_pos (GtkTextView       *text_view,
269 270
                                                  gint              *x,
                                                  gint              *y);
271
static void gtk_text_view_set_virtual_cursor_pos (GtkTextView       *text_view,
272 273
                                                  gint               x,
                                                  gint               y);
274

275 276 277
static GtkAdjustment* get_hadjustment            (GtkTextView       *text_view);
static GtkAdjustment* get_vadjustment            (GtkTextView       *text_view);

Owen Taylor's avatar
Owen Taylor committed
278
static void gtk_text_view_do_popup               (GtkTextView       *text_view,
Owen Taylor's avatar
Owen Taylor committed
279
						  GdkEventButton    *event);
280

281 282 283 284 285 286 287 288 289
static void gtk_text_view_queue_scroll           (GtkTextView   *text_view,
                                                  GtkTextMark   *mark,
                                                  gdouble        within_margin,
                                                  gboolean       use_align,
                                                  gdouble        xalign,
                                                  gdouble        yalign);

static gboolean gtk_text_view_flush_scroll       (GtkTextView *text_view);

290 291 292 293 294 295 296 297 298 299 300 301
/* 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,
                                  GtkCallback   callback,
                                  gpointer      callback_data);

/* FIXME probably need the focus methods. */

302 303 304
/* Hack-around */
#define g_signal_handlers_disconnect_by_func(obj, func, data) g_signal_handlers_disconnect_matched (obj, G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, 0, 0, NULL, func, data)

305 306 307 308 309 310 311 312
typedef struct _GtkTextViewChild GtkTextViewChild;

struct _GtkTextViewChild
{
  GtkWidget *widget;

  GtkTextChildAnchor *anchor;

313 314 315
  gint from_top_of_line;
  gint from_left_of_buffer;
  
316 317 318 319 320 321 322
  /* These are ignored if anchor != NULL */
  GtkTextWindowType type;
  gint x;
  gint y;
};

static GtkTextViewChild* text_view_child_new_anchored (GtkWidget          *child,
323 324
                                                       GtkTextChildAnchor *anchor,
                                                       GtkTextLayout      *layout);
325 326 327 328 329 330 331 332 333
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_realize      (GtkTextView      *text_view,
                                                       GtkTextViewChild *child);

334 335 336 337 338 339 340 341 342 343
struct _GtkTextWindow
{
  GtkTextWindowType type;
  GtkWidget *widget;
  GdkWindow *window;
  GdkWindow *bin_window;
  GtkRequisition requisition;
  GdkRectangle allocation;
};

344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363
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);

static gint           text_window_get_width       (GtkTextWindow     *win);
static gint           text_window_get_height      (GtkTextWindow     *win);
static void           text_window_get_allocation  (GtkTextWindow     *win,
                                                   GdkRectangle      *rect);
364 365


366 367
enum
{
368 369 370
  TARGET_STRING,
  TARGET_TEXT,
  TARGET_COMPOUND_TEXT,
371 372
  TARGET_UTF8_STRING,
  TARGET_TEXT_BUFFER_CONTENTS
373 374 375
};

static GtkTargetEntry target_table[] = {
376 377
  { "GTK_TEXT_BUFFER_CONTENTS", GTK_TARGET_SAME_APP,
    TARGET_TEXT_BUFFER_CONTENTS },
378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406
  { "UTF8_STRING", 0, TARGET_UTF8_STRING },
  { "COMPOUND_TEXT", 0, TARGET_COMPOUND_TEXT },
  { "TEXT", 0, TARGET_TEXT },
  { "text/plain", 0, TARGET_STRING },
  { "STRING",     0, TARGET_STRING }
};

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

GtkType
gtk_text_view_get_type (void)
{
  static GtkType our_type = 0;

  if (our_type == 0)
    {
      static const GtkTypeInfo our_info =
      {
        "GtkTextView",
        sizeof (GtkTextView),
        sizeof (GtkTextViewClass),
        (GtkClassInitFunc) gtk_text_view_class_init,
        (GtkObjectInitFunc) gtk_text_view_init,
        /* reserved_1 */ NULL,
        /* reserved_2 */ NULL,
        (GtkClassInitFunc) NULL
      };

407 408
      our_type = gtk_type_unique (GTK_TYPE_CONTAINER, &our_info);
    }
409 410 411 412 413

  return our_type;
}

static void
414
add_move_binding (GtkBindingSet  *binding_set,
415 416 417 418
                  guint           keyval,
                  guint           modmask,
                  GtkMovementStep step,
                  gint            count)
419 420
{
  g_return_if_fail ((modmask & GDK_SHIFT_MASK) == 0);
421

422
  gtk_binding_entry_add_signal (binding_set, keyval, modmask,
423
                                "move_cursor", 3,
424 425
                                GTK_TYPE_ENUM, step,
                                GTK_TYPE_INT, count,
426 427 428 429
                                GTK_TYPE_BOOL, FALSE);

  /* Selection-extending version */
  gtk_binding_entry_add_signal (binding_set, keyval, modmask | GDK_SHIFT_MASK,
430
                                "move_cursor", 3,
431 432
                                GTK_TYPE_ENUM, step,
                                GTK_TYPE_INT, count,
433 434 435 436 437 438 439 440 441
                                GTK_TYPE_BOOL, TRUE);
}

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);
442
  GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
443
  GtkBindingSet *binding_set;
444

445 446
  parent_class = gtk_type_class (GTK_TYPE_CONTAINER);

447 448
  /* Default handlers and virtual methods
   */
449 450
  gobject_class->set_property = gtk_text_view_set_property;
  gobject_class->get_property = gtk_text_view_get_property;
451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480

  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;
  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;

  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
481 482
  widget_class->popup_menu = gtk_text_view_popup_menu;
  
483 484 485 486 487 488 489 490 491 492 493 494 495 496
  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;
  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;
  klass->set_scroll_adjustments = gtk_text_view_set_scroll_adjustments;

497
  /*
498
   * Properties
499
   */
500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610
  g_object_class_install_property (gobject_class,
                                   PROP_HEIGHT_LINES,
                                   g_param_spec_int ("height_lines",
						     _("Line Height"),
						     _("The height of a line"),
						     0,
						     G_MAXINT,
						     0,
						     G_PARAM_READWRITE));
 
  g_object_class_install_property (gobject_class,
                                   PROP_WIDTH_COLUMNS,
                                   g_param_spec_int ("width_columns",
						     _("Column Width"),
						     _("The width of a column"),
						     0,
						     G_MAXINT,
						     0,
						     G_PARAM_READWRITE));
 
  g_object_class_install_property (gobject_class,
                                   PROP_PIXELS_ABOVE_LINES,
                                   g_param_spec_int ("pixels_above_lines",
						     _("Pixels Above Lines"),
						     _("Pixels of blank space above paragraphs"),
						     0,
						     G_MAXINT,
						     0,
						     G_PARAM_READWRITE));
 
  g_object_class_install_property (gobject_class,
                                   PROP_PIXELS_BELOW_LINES,
                                   g_param_spec_int ("pixels_below_lines",
						     _("Pixels Below Lines"),
						     _("Pixels of blank space below paragraphs"),
						     0,
						     G_MAXINT,
						     0,
						     G_PARAM_READWRITE));
 
  g_object_class_install_property (gobject_class,
                                   PROP_PIXELS_INSIDE_WRAP,
                                   g_param_spec_int ("pixels_inside_wrap",
						     _("Pixels Inside Wrap"),
						     _("Pixels of blank space between wrapped lines in a paragraph"),
						     0,
						     G_MAXINT,
						     0,
						     G_PARAM_READWRITE));

  g_object_class_install_property (gobject_class,
                                   PROP_EDITABLE,
                                   g_param_spec_boolean ("editable",
							 _("Editable"),
							 _("Whether the text can be modified by the user"),
							 TRUE,
							 G_PARAM_READWRITE));

  g_object_class_install_property (gobject_class,
                                   PROP_WRAP_MODE,
                                   g_param_spec_enum ("wrap_mode",
						      _("Wrap Mode"),
						      _("Whether to wrap lines never, at word boundaries, or at character boundaries"),
						      GTK_TYPE_WRAP_MODE,
						      GTK_WRAP_NONE,
						      G_PARAM_READWRITE));
 
  g_object_class_install_property (gobject_class,
                                   PROP_JUSTIFICATION,
                                   g_param_spec_enum ("justification",
						      _("Justification"),
						      _("Left, right, or center justification"),
						      GTK_TYPE_JUSTIFICATION,
						      GTK_JUSTIFY_LEFT,
						      G_PARAM_READWRITE));
 
  g_object_class_install_property (gobject_class,
                                   PROP_LEFT_MARGIN,
                                   g_param_spec_int ("left_margin",
						     _("Left Margin"),
						     _("Width of the left margin in pixels"),
						     0,
						     G_MAXINT,
						     0,
						     G_PARAM_READWRITE));

  g_object_class_install_property (gobject_class,
                                   PROP_RIGHT_MARGIN,
                                   g_param_spec_int ("right_margin",
						     _("Right Margin"),
						     _("Width of the right margin in pixels"),
						     0,
						     G_MAXINT,
						     0,
						     G_PARAM_READWRITE));

  g_object_class_install_property (gobject_class,
                                   PROP_INDENT,
                                   g_param_spec_int ("indent",
						     _("Indent"),
						     _("Amount to indent the paragraph, in pixels"),
						     0,
						     G_MAXINT,
						     0,
						     G_PARAM_READWRITE));

  g_object_class_install_property (gobject_class,
                                   PROP_TABS,
                                   g_param_spec_boxed ("tabs",
                                                       _("Tabs"),
                                                       _("Custom tabs for this text"),
611
                                                       PANGO_TYPE_TAB_ARRAY,
612 613 614 615 616 617 618 619 620
						       G_PARAM_READWRITE));

  g_object_class_install_property (gobject_class,
                                   PROP_CURSOR_VISIBLE,
                                   g_param_spec_boolean ("cursor_visible",
							 _("Cursor Visible"),
							 _("If the insertion cursor is shown"),
							 TRUE,
							 G_PARAM_READWRITE));
621

622
  
623 624 625 626
  /*
   * Signals
   */

627 628
  signals[MOVE_CURSOR] =
    gtk_signal_new ("move_cursor",
629 630
                    GTK_RUN_LAST | GTK_RUN_ACTION,
                    GTK_CLASS_TYPE (object_class),
631
                    GTK_SIGNAL_OFFSET (GtkTextViewClass, move_cursor),
632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647
                    gtk_marshal_VOID__ENUM_INT_BOOLEAN,
                    GTK_TYPE_NONE, 3, GTK_TYPE_MOVEMENT_STEP, GTK_TYPE_INT, GTK_TYPE_BOOL);

  signals[SET_ANCHOR] =
    gtk_signal_new ("set_anchor",
                    GTK_RUN_LAST | GTK_RUN_ACTION,
                    GTK_CLASS_TYPE (object_class),
                    GTK_SIGNAL_OFFSET (GtkTextViewClass, set_anchor),
                    gtk_marshal_VOID__VOID,
                    GTK_TYPE_NONE, 0);

  signals[INSERT_AT_CURSOR] =
    gtk_signal_new ("insert_at_cursor",
                    GTK_RUN_LAST | GTK_RUN_ACTION,
                    GTK_CLASS_TYPE (object_class),
                    GTK_SIGNAL_OFFSET (GtkTextViewClass, insert_at_cursor),
Tim Janik's avatar
Tim Janik committed
648
                    gtk_marshal_VOID__STRING,
649 650
                    GTK_TYPE_NONE, 1, GTK_TYPE_STRING);

651 652
  signals[DELETE_FROM_CURSOR] =
    gtk_signal_new ("delete_from_cursor",
653 654
                    GTK_RUN_LAST | GTK_RUN_ACTION,
                    GTK_CLASS_TYPE (object_class),
655
                    GTK_SIGNAL_OFFSET (GtkTextViewClass, delete_from_cursor),
656 657
                    gtk_marshal_VOID__ENUM_INT,
                    GTK_TYPE_NONE, 2, GTK_TYPE_DELETE_TYPE, GTK_TYPE_INT);
658

659 660
  signals[CUT_CLIPBOARD] =
    gtk_signal_new ("cut_clipboard",
661 662
                    GTK_RUN_LAST | GTK_RUN_ACTION,
                    GTK_CLASS_TYPE (object_class),
663
                    GTK_SIGNAL_OFFSET (GtkTextViewClass, cut_clipboard),
664
                    gtk_marshal_VOID__VOID,
665 666
                    GTK_TYPE_NONE, 0);

667 668
  signals[COPY_CLIPBOARD] =
    gtk_signal_new ("copy_clipboard",
669 670
                    GTK_RUN_LAST | GTK_RUN_ACTION,
                    GTK_CLASS_TYPE (object_class),
671
                    GTK_SIGNAL_OFFSET (GtkTextViewClass, copy_clipboard),
672
                    gtk_marshal_VOID__VOID,
673 674
                    GTK_TYPE_NONE, 0);

675 676
  signals[PASTE_CLIPBOARD] =
    gtk_signal_new ("paste_clipboard",
677 678
                    GTK_RUN_LAST | GTK_RUN_ACTION,
                    GTK_CLASS_TYPE (object_class),
679
                    GTK_SIGNAL_OFFSET (GtkTextViewClass, paste_clipboard),
680
                    gtk_marshal_VOID__VOID,
681 682 683 684 685 686 687
                    GTK_TYPE_NONE, 0);

  signals[TOGGLE_OVERWRITE] =
    gtk_signal_new ("toggle_overwrite",
                    GTK_RUN_LAST | GTK_RUN_ACTION,
                    GTK_CLASS_TYPE (object_class),
                    GTK_SIGNAL_OFFSET (GtkTextViewClass, toggle_overwrite),
688
                    gtk_marshal_VOID__VOID,
689 690
                    GTK_TYPE_NONE, 0);

691
  signals[SET_SCROLL_ADJUSTMENTS] =
692
    gtk_signal_new ("set_scroll_adjustments",
693 694 695
                    GTK_RUN_LAST,
                    GTK_CLASS_TYPE (object_class),
                    GTK_SIGNAL_OFFSET (GtkTextViewClass, set_scroll_adjustments),
Tim Janik's avatar
Tim Janik committed
696
                    gtk_marshal_VOID__OBJECT_OBJECT,
697
                    GTK_TYPE_NONE, 2, GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT);
698
  widget_class->set_scroll_adjustments_signal = signals[SET_SCROLL_ADJUSTMENTS];
699

Owen Taylor's avatar
Owen Taylor committed
700 701 702 703 704 705 706 707
  signals[POPULATE_POPUP] =
    gtk_signal_new ("populate_popup",
                    GTK_RUN_LAST,
                    GTK_CLASS_TYPE (object_class),
                    GTK_SIGNAL_OFFSET (GtkTextViewClass, populate_popup),
                    gtk_marshal_VOID__OBJECT,
                    GTK_TYPE_NONE, 1, GTK_TYPE_MENU);
  
708 709 710 711 712 713 714
  /*
   * Key bindings
   */

  binding_set = gtk_binding_set_by_class (klass);

  /* Moving the insertion point */
715
  add_move_binding (binding_set, GDK_Right, 0,
716
                    GTK_MOVEMENT_VISUAL_POSITIONS, 1);
717

718 719 720
  add_move_binding (binding_set, GDK_KP_Right, 0,
                    GTK_MOVEMENT_VISUAL_POSITIONS, 1);
  
721
  add_move_binding (binding_set, GDK_Left, 0,
722
                    GTK_MOVEMENT_VISUAL_POSITIONS, -1);
723

724 725 726
  add_move_binding (binding_set, GDK_KP_Left, 0,
                    GTK_MOVEMENT_VISUAL_POSITIONS, -1);
  
727
  add_move_binding (binding_set, GDK_f, GDK_CONTROL_MASK,
728
                    GTK_MOVEMENT_LOGICAL_POSITIONS, 1);
729

730
  add_move_binding (binding_set, GDK_b, GDK_CONTROL_MASK,
731
                    GTK_MOVEMENT_LOGICAL_POSITIONS, -1);
732

733
  add_move_binding (binding_set, GDK_Right, GDK_CONTROL_MASK,
734
                    GTK_MOVEMENT_WORDS, 1);
735

736 737 738
  add_move_binding (binding_set, GDK_KP_Right, GDK_CONTROL_MASK,
                    GTK_MOVEMENT_WORDS, 1);
  
739
  add_move_binding (binding_set, GDK_Left, GDK_CONTROL_MASK,
740 741
                    GTK_MOVEMENT_WORDS, -1);

742 743 744
  add_move_binding (binding_set, GDK_KP_Left, GDK_CONTROL_MASK,
                    GTK_MOVEMENT_WORDS, 1);
  
745
  /* Eventually we want to move by display lines, not paragraphs */
746
  add_move_binding (binding_set, GDK_Up, 0,
747 748
                    GTK_MOVEMENT_DISPLAY_LINES, -1);

749 750 751
  add_move_binding (binding_set, GDK_KP_Up, 0,
                    GTK_MOVEMENT_DISPLAY_LINES, -1);
  
752
  add_move_binding (binding_set, GDK_Down, 0,
753
                    GTK_MOVEMENT_DISPLAY_LINES, 1);
754

755 756 757
  add_move_binding (binding_set, GDK_KP_Down, 0,
                    GTK_MOVEMENT_DISPLAY_LINES, 1);
  
758
  add_move_binding (binding_set, GDK_p, GDK_CONTROL_MASK,
759 760
                    GTK_MOVEMENT_DISPLAY_LINES, -1);

761
  add_move_binding (binding_set, GDK_n, GDK_CONTROL_MASK,
762 763
                    GTK_MOVEMENT_DISPLAY_LINES, 1);

764
  add_move_binding (binding_set, GDK_a, GDK_CONTROL_MASK,
765
                    GTK_MOVEMENT_PARAGRAPH_ENDS, -1);
766

767
  add_move_binding (binding_set, GDK_e, GDK_CONTROL_MASK,
768
                    GTK_MOVEMENT_PARAGRAPH_ENDS, 1);
769

770
  add_move_binding (binding_set, GDK_f, GDK_MOD1_MASK,
771
                    GTK_MOVEMENT_WORDS, 1);
772

773
  add_move_binding (binding_set, GDK_b, GDK_MOD1_MASK,
774
                    GTK_MOVEMENT_WORDS, -1);
775

776
  add_move_binding (binding_set, GDK_Home, 0,
777
                    GTK_MOVEMENT_DISPLAY_LINE_ENDS, -1);
778

779 780 781
  add_move_binding (binding_set, GDK_KP_Home, 0,
                    GTK_MOVEMENT_DISPLAY_LINE_ENDS, -1);
  
782
  add_move_binding (binding_set, GDK_End, 0,
783 784
                    GTK_MOVEMENT_DISPLAY_LINE_ENDS, 1);

785 786 787
  add_move_binding (binding_set, GDK_KP_End, 0,
                    GTK_MOVEMENT_DISPLAY_LINE_ENDS, 1);
  
788
  add_move_binding (binding_set, GDK_Home, GDK_CONTROL_MASK,
789
                    GTK_MOVEMENT_BUFFER_ENDS, -1);
790

791 792 793
  add_move_binding (binding_set, GDK_KP_Home, GDK_CONTROL_MASK,
                    GTK_MOVEMENT_BUFFER_ENDS, -1);
  
794
  add_move_binding (binding_set, GDK_End, GDK_CONTROL_MASK,
795
                    GTK_MOVEMENT_BUFFER_ENDS, 1);
796

797 798 799
  add_move_binding (binding_set, GDK_KP_End, GDK_CONTROL_MASK,
                    GTK_MOVEMENT_BUFFER_ENDS, 1);
  
800
  add_move_binding (binding_set, GDK_Page_Up, 0,
801
                    GTK_MOVEMENT_PAGES, -1);
802

803 804 805
  add_move_binding (binding_set, GDK_KP_Page_Up, 0,
                    GTK_MOVEMENT_PAGES, -1);
  
806
  add_move_binding (binding_set, GDK_Page_Down, 0,
807 808
                    GTK_MOVEMENT_PAGES, 1);

809 810 811
  add_move_binding (binding_set, GDK_KP_Page_Down, 0,
                    GTK_MOVEMENT_PAGES, 1);
  
812 813
  /* Setting the cut/paste/copy anchor */
  gtk_binding_entry_add_signal (binding_set, GDK_space, GDK_CONTROL_MASK,
814
                                "set_anchor", 0);
815 816 817
  gtk_binding_entry_add_signal (binding_set, GDK_KP_Space, GDK_CONTROL_MASK,
                                "set_anchor", 0);
  
818 819
  /* Deleting text */
  gtk_binding_entry_add_signal (binding_set, GDK_Delete, 0,
820
                                "delete_from_cursor", 2,
821 822 823
                                GTK_TYPE_ENUM, GTK_DELETE_CHARS,
                                GTK_TYPE_INT, 1);

824 825 826 827 828
  gtk_binding_entry_add_signal (binding_set, GDK_KP_Delete, 0,
                                "delete_from_cursor", 2,
                                GTK_TYPE_ENUM, GTK_DELETE_CHARS,
                                GTK_TYPE_INT, 1);
  
829
  gtk_binding_entry_add_signal (binding_set, GDK_d, GDK_CONTROL_MASK,
830
                                "delete_from_cursor", 2,
831 832
                                GTK_TYPE_ENUM, GTK_DELETE_CHARS,
                                GTK_TYPE_INT, 1);
833 834

  gtk_binding_entry_add_signal (binding_set, GDK_BackSpace, 0,
835
                                "delete_from_cursor", 2,
836 837
                                GTK_TYPE_ENUM, GTK_DELETE_CHARS,
                                GTK_TYPE_INT, -1);
838 839

  gtk_binding_entry_add_signal (binding_set, GDK_Delete, GDK_CONTROL_MASK,
840
                                "delete_from_cursor", 2,
841 842
                                GTK_TYPE_ENUM, GTK_DELETE_WORD_ENDS,
                                GTK_TYPE_INT, 1);
843

844 845 846 847 848
  gtk_binding_entry_add_signal (binding_set, GDK_KP_Delete, GDK_CONTROL_MASK,
                                "delete_from_cursor", 2,
                                GTK_TYPE_ENUM, GTK_DELETE_WORD_ENDS,
                                GTK_TYPE_INT, 1);
  
849
  gtk_binding_entry_add_signal (binding_set, GDK_d, GDK_MOD1_MASK,
850
                                "delete_from_cursor", 2,
851 852
                                GTK_TYPE_ENUM, GTK_DELETE_WORD_ENDS,
                                GTK_TYPE_INT, 1);
853 854

  gtk_binding_entry_add_signal (binding_set, GDK_BackSpace, GDK_CONTROL_MASK,
855
                                "delete_from_cursor", 2,
856 857
                                GTK_TYPE_ENUM, GTK_DELETE_WORD_ENDS,
                                GTK_TYPE_INT, -1);
858 859

  gtk_binding_entry_add_signal (binding_set, GDK_k, GDK_CONTROL_MASK,
860
                                "delete_from_cursor", 2,
861 862
                                GTK_TYPE_ENUM, GTK_DELETE_PARAGRAPH_ENDS,
                                GTK_TYPE_INT, 1);
863 864

  gtk_binding_entry_add_signal (binding_set, GDK_u, GDK_CONTROL_MASK,
865
                                "delete_from_cursor", 2,
866 867
                                GTK_TYPE_ENUM, GTK_DELETE_PARAGRAPHS,
                                GTK_TYPE_INT, 1);
868 869

  gtk_binding_entry_add_signal (binding_set, GDK_space, GDK_MOD1_MASK,
870
                                "delete_from_cursor", 2,
871 872
                                GTK_TYPE_ENUM, GTK_DELETE_WHITESPACE,
                                GTK_TYPE_INT, 1);
873 874 875 876
  gtk_binding_entry_add_signal (binding_set, GDK_KP_Space, GDK_MOD1_MASK,
                                "delete_from_cursor", 2,
                                GTK_TYPE_ENUM, GTK_DELETE_WHITESPACE,
                                GTK_TYPE_INT, 1);
877
  gtk_binding_entry_add_signal (binding_set, GDK_space, GDK_MOD1_MASK,
878 879
                                "insert_at_cursor", 1,
                                GTK_TYPE_STRING, " ");
880 881 882 883
  gtk_binding_entry_add_signal (binding_set, GDK_KP_Space, GDK_MOD1_MASK,
                                "insert_at_cursor", 1,
                                GTK_TYPE_STRING, " ");
  
884
  gtk_binding_entry_add_signal (binding_set, GDK_backslash, GDK_MOD1_MASK,
885
                                "delete_from_cursor", 2,
886 887 888
                                GTK_TYPE_ENUM, GTK_DELETE_WHITESPACE,
                                GTK_TYPE_INT, 1);

889 890 891
  /* Cut/copy/paste */

  gtk_binding_entry_add_signal (binding_set, GDK_x, GDK_CONTROL_MASK,
892
                                "cut_clipboard", 0);
893 894

  gtk_binding_entry_add_signal (binding_set, GDK_w, GDK_CONTROL_MASK,
895 896
                                "cut_clipboard", 0);

897
  gtk_binding_entry_add_signal (binding_set, GDK_c, GDK_CONTROL_MASK,
898 899
                                "copy_clipboard", 0);

900
  gtk_binding_entry_add_signal (binding_set, GDK_v, GDK_CONTROL_MASK,
901
                                "paste_clipboard", 0);
902

903
  gtk_binding_entry_add_signal (binding_set, GDK_y, GDK_CONTROL_MASK,
904
                                "paste_clipboard", 0);
905 906 907

  /* Overwrite */
  gtk_binding_entry_add_signal (binding_set, GDK_Insert, 0,
908
                                "toggle_overwrite", 0);
909 910
  gtk_binding_entry_add_signal (binding_set, GDK_KP_Insert, 0,
                                "toggle_overwrite", 0);
911 912 913 914 915 916
}

void
gtk_text_view_init (GtkTextView *text_view)
{
  GtkWidget *widget;
917

918 919 920 921
  widget = GTK_WIDGET (text_view);

  GTK_WIDGET_SET_FLAGS (widget, GTK_CAN_FOCUS);

922
  /* Set up default style */
923
  text_view->wrap_mode = GTK_WRAP_NONE;
924 925 926 927 928 929 930 931 932
  text_view->pixels_above_lines = 0;
  text_view->pixels_below_lines = 0;
  text_view->pixels_inside_wrap = 0;
  text_view->justify = GTK_JUSTIFY_LEFT;
  text_view->left_margin = 0;
  text_view->right_margin = 0;
  text_view->indent = 0;
  text_view->tabs = NULL;
  text_view->editable = TRUE;
933

934
  gtk_drag_dest_set (widget,
935 936 937
                     GTK_DEST_DEFAULT_DROP,
                     target_table, G_N_ELEMENTS (target_table),
                     GDK_ACTION_COPY | GDK_ACTION_MOVE);
938 939 940 941 942

  text_view->virtual_cursor_x = -1;
  text_view->virtual_cursor_y = -1;

  /* This object is completely private. No external entity can gain a reference
943
   * to it; so we create it here and destroy it in finalize ().
944 945
   */
  text_view->im_context = gtk_im_multicontext_new ();
946

947
  gtk_signal_connect (GTK_OBJECT (text_view->im_context), "commit",
948
                      GTK_SIGNAL_FUNC (gtk_text_view_commit_handler), text_view);
949

Owen Taylor's avatar
Owen Taylor committed
950 951
  gtk_signal_connect (GTK_OBJECT (text_view->im_context), "preedit_changed",
 		      GTK_SIGNAL_FUNC (gtk_text_view_preedit_changed_handler), text_view);
952

953
  text_view->cursor_visible = TRUE;
954 955 956

  text_view->text_window = text_window_new (GTK_TEXT_WINDOW_TEXT,
                                            widget, 200, 200);
Havoc Pennington's avatar
Havoc Pennington committed
957 958 959

  text_view->drag_start_x = -1;
  text_view->drag_start_y = -1;
960 961
}

962 963
/**
 * gtk_text_view_new:
964
 *
965 966 967 968 969 970 971
 * Creates a new #GtkTextView. If you don't call gtk_text_view_set_buffer()
 * before using the text view, an empty default buffer will be created
 * for you. Get the buffer with gtk_text_view_get_buffer(). If you want
 * to specify your own buffer, consider gtk_text_view_new_with_buffer().
 *
 * Return value: a new #GtkTextView
 **/
972 973 974 975 976 977
GtkWidget*
gtk_text_view_new (void)
{
  return GTK_WIDGET (gtk_type_new (gtk_text_view_get_type ()));
}

978 979 980
/**
 * gtk_text_view_new_with_buffer:
 * @buffer: a #GtkTextBuffer
981
 *
982 983 984 985 986 987
 * Creates a new #GtkTextView widget displaying the buffer
 * @buffer. One buffer can be shared among many widgets.
 * @buffer may be NULL to create a default buffer, in which case
 * this function is equivalent to gtk_text_view_new(). The
 * text view adds its own reference count to the buffer; it does not
 * take over an existing reference.
988
 *
989 990
 * Return value: a new #GtkTextView.
 **/
991 992 993 994 995 996 997 998 999 1000 1001 1002
GtkWidget*
gtk_text_view_new_with_buffer (GtkTextBuffer *buffer)
{
  GtkTextView *text_view;

  text_view = (GtkTextView*)gtk_text_view_new ();

  gtk_text_view_set_buffer (text_view, buffer);

  return GTK_WIDGET (text_view);
}

1003 1004 1005 1006 1007 1008 1009 1010 1011 1012
/**
 * gtk_text_view_set_buffer:
 * @text_view: a #GtkTextView
 * @buffer: a #GtkTextBuffer
 *
 * Sets @buffer as the buffer being displayed by @text_view. The previous
 * buffer displayed by the text view is unreferenced, and a reference is
 * added to @buffer. If you owned a reference to @buffer before passing it
 * to this function, you must remove that reference yourself; #GtkTextView
 * will not "adopt" it.
1013
 *
1014
 **/
1015
void
1016
gtk_text_view_set_buffer (GtkTextView   *text_view,
1017
                          GtkTextBuffer *buffer)
1018 1019 1020
{
  g_return_if_fail (GTK_IS_TEXT_VIEW (text_view));
  g_return_if_fail (buffer == NULL || GTK_IS_TEXT_BUFFER (buffer));
1021

1022 1023 1024 1025 1026
  if (text_view->buffer == buffer)
    return;

  if (text_view->buffer != NULL)
    {
1027 1028 1029
      /* Destroy all anchored children */
      GSList *tmp_list;
      GSList *copy;
1030

1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041
      copy = g_slist_copy (text_view->children);
      tmp_list = copy;
      while (tmp_list != NULL)
        {
          GtkTextViewChild *vc = tmp_list->data;

          if (vc->anchor)
            {
              gtk_widget_destroy (vc->widget);
              /* vc may now be invalid! */
            }
1042

1043 1044 1045 1046
          tmp_list = g_slist_next (tmp_list);
        }

      g_slist_free (copy);
1047

1048 1049 1050
      g_signal_handlers_disconnect_by_func (G_OBJECT (text_view->buffer),
                                            gtk_text_view_mark_set_handler, text_view);
      g_object_unref (G_OBJECT (text_view->buffer));
1051 1052 1053 1054
      text_view->dnd_mark = NULL;
    }

  text_view->buffer = buffer;
1055

1056 1057 1058
  if (buffer != NULL)
    {
      GtkTextIter start;
1059

1060
      g_object_ref (G_OBJECT (buffer));
1061 1062 1063 1064

      if (text_view->layout)
        gtk_text_layout_set_buffer (text_view->layout, buffer);

1065
      gtk_text_buffer_get_iter_at_offset (text_view->buffer, &start, 0);
1066

1067
      text_view->dnd_mark = gtk_text_buffer_create_mark (text_view->buffer,
1068 1069
                                                         "gtk_drag_target",
                                                         &start, FALSE);
1070 1071

      text_view->first_para_mark = gtk_text_buffer_create_mark (text_view->buffer,
1072
                                                                NULL,
1073 1074
                                                                &start, TRUE);