gtktextview.c 234 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
#define GTK_TEXT_USE_INTERNAL_UNSUPPORTED_API
30 31
#include "gtkbindings.h"
#include "gtkdnd.h"
32
#include "gtkimagemenuitem.h"
Owen Taylor's avatar
Owen Taylor committed
33
#include "gtkintl.h"
34
#include "gtkmain.h"
35
#include "gtkmarshalers.h"
Owen Taylor's avatar
Owen Taylor committed
36 37
#include "gtkmenu.h"
#include "gtkmenuitem.h"
38
#include "gtkseparatormenuitem.h"
39
#include "gtksettings.h"
40
#include "gtksignal.h"
41
#include "gtkstock.h"
42 43 44 45
#include "gtktextdisplay.h"
#include "gtktextview.h"
#include "gtkimmulticontext.h"
#include "gdk/gdkkeysyms.h"
46
#include "gtktextutil.h"
47
#include "gtkwindow.h"
48
#include <string.h>
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 79 80 81 82 83 84
/* 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.
 *
 */

85 86
#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)
87

88 89 90
#if 0
#define DEBUG_VALIDATION_AND_SCROLLING
#endif
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106

#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;
};
  
107 108
enum
{
Owen Taylor's avatar
Owen Taylor committed
109 110
  SET_SCROLL_ADJUSTMENTS,
  POPULATE_POPUP,
111
  MOVE_CURSOR,
112
  PAGE_HORIZONTALLY,
113
  SET_ANCHOR,
114
  INSERT_AT_CURSOR,
115
  DELETE_FROM_CURSOR,
116 117 118
  CUT_CLIPBOARD,
  COPY_CLIPBOARD,
  PASTE_CLIPBOARD,
119
  TOGGLE_OVERWRITE,
120
  MOVE_FOCUS,
121 122 123
  LAST_SIGNAL
};

124 125
enum
{
126 127 128 129 130 131 132 133 134 135 136 137 138
  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,
  LAST_PROP
139 140 141 142 143 144
};

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);
145 146 147 148 149 150 151 152
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);
153
static void gtk_text_view_size_request         (GtkWidget        *widget,
154
                                                GtkRequisition   *requisition);
155
static void gtk_text_view_size_allocate        (GtkWidget        *widget,
156
                                                GtkAllocation    *allocation);
157 158 159
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,
160
                                                GtkStyle         *previous_style);
161
static void gtk_text_view_direction_changed    (GtkWidget        *widget,
162
                                                GtkTextDirection  previous_direction);
163
static gint gtk_text_view_event                (GtkWidget        *widget,
164
                                                GdkEvent         *event);
165
static gint gtk_text_view_key_press_event      (GtkWidget        *widget,
166
                                                GdkEventKey      *event);
167
static gint gtk_text_view_key_release_event    (GtkWidget        *widget,
168
                                                GdkEventKey      *event);
169
static gint gtk_text_view_button_press_event   (GtkWidget        *widget,
170
                                                GdkEventButton   *event);
171
static gint gtk_text_view_button_release_event (GtkWidget        *widget,
172
                                                GdkEventButton   *event);
173
static gint gtk_text_view_focus_in_event       (GtkWidget        *widget,
174
                                                GdkEventFocus    *event);
175
static gint gtk_text_view_focus_out_event      (GtkWidget        *widget,
176
                                                GdkEventFocus    *event);
177
static gint gtk_text_view_motion_event         (GtkWidget        *widget,
178
                                                GdkEventMotion   *event);
179
static gint gtk_text_view_expose_event         (GtkWidget        *widget,
180
                                                GdkEventExpose   *expose);
181
static void gtk_text_view_draw_focus           (GtkWidget        *widget);
182
static void gtk_text_view_grab_focus           (GtkWidget        *widget);
183 184 185
static gboolean gtk_text_view_focus            (GtkWidget        *widget,
                                                GtkDirectionType  direction);

186 187 188

/* Source side drag signals */
static void gtk_text_view_drag_begin       (GtkWidget        *widget,
189
                                            GdkDragContext   *context);
190
static void gtk_text_view_drag_end         (GtkWidget        *widget,
191
                                            GdkDragContext   *context);
192
static void gtk_text_view_drag_data_get    (GtkWidget        *widget,
193 194 195 196
                                            GdkDragContext   *context,
                                            GtkSelectionData *selection_data,
                                            guint             info,
                                            guint             time);
197
static void gtk_text_view_drag_data_delete (GtkWidget        *widget,
198
                                            GdkDragContext   *context);
199 200 201

/* Target side drag signals */
static void     gtk_text_view_drag_leave         (GtkWidget        *widget,
202 203
                                                  GdkDragContext   *context,
                                                  guint             time);
204
static gboolean gtk_text_view_drag_motion        (GtkWidget        *widget,
205 206 207 208
                                                  GdkDragContext   *context,
                                                  gint              x,
                                                  gint              y,
                                                  guint             time);
209
static gboolean gtk_text_view_drag_drop          (GtkWidget        *widget,
210 211 212 213
                                                  GdkDragContext   *context,
                                                  gint              x,
                                                  gint              y,
                                                  guint             time);
214
static void     gtk_text_view_drag_data_received (GtkWidget        *widget,
215 216 217 218 219 220
                                                  GdkDragContext   *context,
                                                  gint              x,
                                                  gint              y,
                                                  GtkSelectionData *selection_data,
                                                  guint             info,
                                                  guint             time);
221 222

static void gtk_text_view_set_scroll_adjustments (GtkTextView   *text_view,
223 224
                                                  GtkAdjustment *hadj,
                                                  GtkAdjustment *vadj);
225
static gboolean gtk_text_view_popup_menu         (GtkWidget     *widget);
226

227 228 229 230 231 232 233
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);
234 235
static void gtk_text_view_set_anchor       (GtkTextView           *text_view);
static void gtk_text_view_scroll_pages     (GtkTextView           *text_view,
236
                                            gint                   count);
237 238
static void gtk_text_view_scroll_hpages    (GtkTextView           *text_view,
                                            gint                   count);
239
static void gtk_text_view_insert_at_cursor (GtkTextView           *text_view,
240
                                            const gchar           *str);
241 242 243
static void gtk_text_view_delete_from_cursor (GtkTextView           *text_view,
                                              GtkDeleteType          type,
                                              gint                   count);
244 245 246 247
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);
248 249
static void gtk_text_view_move_focus       (GtkTextView           *text_view,
                                            GtkDirectionType       direction_type);
250
static void gtk_text_view_unselect         (GtkTextView           *text_view);
251 252 253

static void     gtk_text_view_validate_onscreen     (GtkTextView        *text_view);
static void     gtk_text_view_get_first_para_iter   (GtkTextView        *text_view,
254
                                                     GtkTextIter        *iter);
255
static void     gtk_text_view_update_layout_width       (GtkTextView        *text_view);
256 257 258
static void     gtk_text_view_set_attributes_from_style (GtkTextView        *text_view,
                                                         GtkTextAttributes *values,
                                                         GtkStyle           *style);
259 260 261 262 263 264 265 266 267 268 269 270 271 272 273
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);
274

275 276 277 278 279
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);
280 281
static void     gtk_text_view_commit_text                  (GtkTextView   *text_view,
                                                            const gchar   *text);
282 283 284 285 286 287 288 289
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);
290 291

static void gtk_text_view_mark_set_handler       (GtkTextBuffer     *buffer,
292
                                                  const GtkTextIter *location,
Havoc Pennington's avatar
Havoc Pennington committed
293
                                                  GtkTextMark       *mark,
294
                                                  gpointer           data);
295
static void gtk_text_view_get_virtual_cursor_pos (GtkTextView       *text_view,
296 297
                                                  gint              *x,
                                                  gint              *y);
298
static void gtk_text_view_set_virtual_cursor_pos (GtkTextView       *text_view,
299 300
                                                  gint               x,
                                                  gint               y);
301

302 303 304
static GtkAdjustment* get_hadjustment            (GtkTextView       *text_view);
static GtkAdjustment* get_vadjustment            (GtkTextView       *text_view);

Owen Taylor's avatar
Owen Taylor committed
305
static void gtk_text_view_do_popup               (GtkTextView       *text_view,
Owen Taylor's avatar
Owen Taylor committed
306
						  GdkEventButton    *event);
307

308 309 310 311 312 313 314 315
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);
316
static void     gtk_text_view_update_adjustments (GtkTextView *text_view);
317
static void     gtk_text_view_invalidate         (GtkTextView *text_view);
318

319 320
static void gtk_text_view_update_im_spot_location (GtkTextView *text_view);

321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340
/* 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. */

typedef struct _GtkTextViewChild GtkTextViewChild;

struct _GtkTextViewChild
{
  GtkWidget *widget;

  GtkTextChildAnchor *anchor;

341 342 343
  gint from_top_of_line;
  gint from_left_of_buffer;
  
344 345 346 347 348 349
  /* These are ignored if anchor != NULL */
  GtkTextWindowType type;
  gint x;
  gint y;
};

350 351 352 353 354 355 356 357 358 359
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);
360

361 362 363 364 365 366 367 368 369 370
struct _GtkTextWindow
{
  GtkTextWindowType type;
  GtkWidget *widget;
  GdkWindow *window;
  GdkWindow *bin_window;
  GtkRequisition requisition;
  GdkRectangle allocation;
};

371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390
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);
391 392


393 394
enum
{
395 396 397
  TARGET_STRING,
  TARGET_TEXT,
  TARGET_COMPOUND_TEXT,
398 399
  TARGET_UTF8_STRING,
  TARGET_TEXT_BUFFER_CONTENTS
400 401 402
};

static GtkTargetEntry target_table[] = {
403 404
  { "GTK_TEXT_BUFFER_CONTENTS", GTK_TARGET_SAME_APP,
    TARGET_TEXT_BUFFER_CONTENTS },
405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433
  { "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
      };

434 435
      our_type = gtk_type_unique (GTK_TYPE_CONTAINER, &our_info);
    }
436 437 438 439 440

  return our_type;
}

static void
441
add_move_binding (GtkBindingSet  *binding_set,
442 443 444 445
                  guint           keyval,
                  guint           modmask,
                  GtkMovementStep step,
                  gint            count)
446 447
{
  g_return_if_fail ((modmask & GDK_SHIFT_MASK) == 0);
448

449
  gtk_binding_entry_add_signal (binding_set, keyval, modmask,
450
                                "move_cursor", 3,
451 452
                                GTK_TYPE_ENUM, step,
                                GTK_TYPE_INT, count,
453 454 455 456
                                GTK_TYPE_BOOL, FALSE);

  /* Selection-extending version */
  gtk_binding_entry_add_signal (binding_set, keyval, modmask | GDK_SHIFT_MASK,
457
                                "move_cursor", 3,
458 459
                                GTK_TYPE_ENUM, step,
                                GTK_TYPE_INT, count,
460 461 462 463 464 465 466 467 468
                                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);
469
  GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
470
  GtkBindingSet *binding_set;
471

472 473
  parent_class = gtk_type_class (GTK_TYPE_CONTAINER);

474 475
  /* Default handlers and virtual methods
   */
476 477
  gobject_class->set_property = gtk_text_view_set_property;
  gobject_class->get_property = gtk_text_view_get_property;
478 479 480 481 482 483 484 485 486 487 488 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;
  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;
497
  widget_class->grab_focus = gtk_text_view_grab_focus;
498
  widget_class->focus = gtk_text_view_focus;
499
  
500 501 502 503 504 505 506 507 508 509
  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
510 511
  widget_class->popup_menu = gtk_text_view_popup_menu;
  
512 513 514 515 516
  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;
517
  klass->page_horizontally = gtk_text_view_page_horizontally;
518 519 520 521 522 523 524
  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;
525
  klass->move_focus = gtk_text_view_move_focus;
526 527
  klass->set_scroll_adjustments = gtk_text_view_set_scroll_adjustments;

528
  /*
529
   * Properties
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 611 612 613 614 615 616 617 618 619 620 621 622
 
  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"),
623
                                                       PANGO_TYPE_TAB_ARRAY,
624 625 626 627 628 629 630 631 632
						       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));
633

634
  
635 636 637 638 639 640 641 642 643 644 645 646
  /*
   * Style properties
   */

  gtk_widget_class_install_style_property (widget_class,
					   g_param_spec_boxed ("cursor_color",
							       _("Cursor color"),
							       _("Color with which to draw insertion cursor"),
							       GDK_TYPE_COLOR,
							       G_PARAM_READABLE));


647 648 649 650
  /*
   * Signals
   */

651 652
  signals[MOVE_CURSOR] =
    gtk_signal_new ("move_cursor",
653 654
                    GTK_RUN_LAST | GTK_RUN_ACTION,
                    GTK_CLASS_TYPE (object_class),
655
                    GTK_SIGNAL_OFFSET (GtkTextViewClass, move_cursor),
656
                    _gtk_marshal_VOID__ENUM_INT_BOOLEAN,
657 658
                    GTK_TYPE_NONE, 3, GTK_TYPE_MOVEMENT_STEP, GTK_TYPE_INT, GTK_TYPE_BOOL);

659 660 661 662 663 664 665 666
  signals[PAGE_HORIZONTALLY] =
    gtk_signal_new ("page_horizontally",
                    GTK_RUN_LAST | GTK_RUN_ACTION,
                    GTK_CLASS_TYPE (object_class),
                    GTK_SIGNAL_OFFSET (GtkTextViewClass, page_horizontally),
                    _gtk_marshal_VOID__INT_BOOLEAN,
                    GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_BOOL);
  
667 668 669 670 671
  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),
672
                    _gtk_marshal_VOID__VOID,
673 674 675 676 677 678 679
                    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),
680
                    _gtk_marshal_VOID__STRING,
681 682
                    GTK_TYPE_NONE, 1, GTK_TYPE_STRING);

683 684
  signals[DELETE_FROM_CURSOR] =
    gtk_signal_new ("delete_from_cursor",
685 686
                    GTK_RUN_LAST | GTK_RUN_ACTION,
                    GTK_CLASS_TYPE (object_class),
687
                    GTK_SIGNAL_OFFSET (GtkTextViewClass, delete_from_cursor),
688
                    _gtk_marshal_VOID__ENUM_INT,
689
                    GTK_TYPE_NONE, 2, GTK_TYPE_DELETE_TYPE, GTK_TYPE_INT);
690

691 692
  signals[CUT_CLIPBOARD] =
    gtk_signal_new ("cut_clipboard",
693 694
                    GTK_RUN_LAST | GTK_RUN_ACTION,
                    GTK_CLASS_TYPE (object_class),
695
                    GTK_SIGNAL_OFFSET (GtkTextViewClass, cut_clipboard),
696
                    _gtk_marshal_VOID__VOID,
697 698
                    GTK_TYPE_NONE, 0);

699 700
  signals[COPY_CLIPBOARD] =
    gtk_signal_new ("copy_clipboard",
701 702
                    GTK_RUN_LAST | GTK_RUN_ACTION,
                    GTK_CLASS_TYPE (object_class),
703
                    GTK_SIGNAL_OFFSET (GtkTextViewClass, copy_clipboard),
704
                    _gtk_marshal_VOID__VOID,
705 706
                    GTK_TYPE_NONE, 0);

707 708
  signals[PASTE_CLIPBOARD] =
    gtk_signal_new ("paste_clipboard",
709 710
                    GTK_RUN_LAST | GTK_RUN_ACTION,
                    GTK_CLASS_TYPE (object_class),
711
                    GTK_SIGNAL_OFFSET (GtkTextViewClass, paste_clipboard),
712
                    _gtk_marshal_VOID__VOID,
713 714 715 716 717 718 719
                    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),
720
                    _gtk_marshal_VOID__VOID,
721 722
                    GTK_TYPE_NONE, 0);

723 724 725 726 727 728 729 730
  signals[MOVE_FOCUS] =
    gtk_signal_new ("move_focus",
                    GTK_RUN_LAST | GTK_RUN_ACTION,
                    GTK_CLASS_TYPE (object_class),
                    GTK_SIGNAL_OFFSET (GtkTextViewClass, move_focus),
                    _gtk_marshal_VOID__ENUM,
                    GTK_TYPE_NONE, 1, GTK_TYPE_DIRECTION_TYPE);
  
731
  signals[SET_SCROLL_ADJUSTMENTS] =
732
    gtk_signal_new ("set_scroll_adjustments",
733 734 735
                    GTK_RUN_LAST,
                    GTK_CLASS_TYPE (object_class),
                    GTK_SIGNAL_OFFSET (GtkTextViewClass, set_scroll_adjustments),
736
                    _gtk_marshal_VOID__OBJECT_OBJECT,
737
                    GTK_TYPE_NONE, 2, GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT);
738
  widget_class->set_scroll_adjustments_signal = signals[SET_SCROLL_ADJUSTMENTS];
739

Owen Taylor's avatar
Owen Taylor committed
740 741 742 743 744
  signals[POPULATE_POPUP] =
    gtk_signal_new ("populate_popup",
                    GTK_RUN_LAST,
                    GTK_CLASS_TYPE (object_class),
                    GTK_SIGNAL_OFFSET (GtkTextViewClass, populate_popup),
745
                    _gtk_marshal_VOID__OBJECT,
Owen Taylor's avatar
Owen Taylor committed
746 747
                    GTK_TYPE_NONE, 1, GTK_TYPE_MENU);
  
748 749 750 751 752
  /*
   * Key bindings
   */

  binding_set = gtk_binding_set_by_class (klass);
753
  
754
  /* Moving the insertion point */
755
  add_move_binding (binding_set, GDK_Right, 0,
756
                    GTK_MOVEMENT_VISUAL_POSITIONS, 1);
757

758 759 760
  add_move_binding (binding_set, GDK_KP_Right, 0,
                    GTK_MOVEMENT_VISUAL_POSITIONS, 1);
  
761
  add_move_binding (binding_set, GDK_Left, 0,
762
                    GTK_MOVEMENT_VISUAL_POSITIONS, -1);
763

764 765 766
  add_move_binding (binding_set, GDK_KP_Left, 0,
                    GTK_MOVEMENT_VISUAL_POSITIONS, -1);
  
767
  add_move_binding (binding_set, GDK_f, GDK_CONTROL_MASK,
768
                    GTK_MOVEMENT_LOGICAL_POSITIONS, 1);
769

770
  add_move_binding (binding_set, GDK_b, GDK_CONTROL_MASK,
771
                    GTK_MOVEMENT_LOGICAL_POSITIONS, -1);
772

773
  add_move_binding (binding_set, GDK_Right, GDK_CONTROL_MASK,
774
                    GTK_MOVEMENT_WORDS, 1);
775

776 777 778
  add_move_binding (binding_set, GDK_KP_Right, GDK_CONTROL_MASK,
                    GTK_MOVEMENT_WORDS, 1);
  
779
  add_move_binding (binding_set, GDK_Left, GDK_CONTROL_MASK,
780 781
                    GTK_MOVEMENT_WORDS, -1);

782 783 784
  add_move_binding (binding_set, GDK_KP_Left, GDK_CONTROL_MASK,
                    GTK_MOVEMENT_WORDS, 1);
  
785
  /* Eventually we want to move by display lines, not paragraphs */
786
  add_move_binding (binding_set, GDK_Up, 0,
787 788
                    GTK_MOVEMENT_DISPLAY_LINES, -1);

789 790 791
  add_move_binding (binding_set, GDK_KP_Up, 0,
                    GTK_MOVEMENT_DISPLAY_LINES, -1);
  
792
  add_move_binding (binding_set, GDK_Down, 0,
793
                    GTK_MOVEMENT_DISPLAY_LINES, 1);
794

795 796 797
  add_move_binding (binding_set, GDK_KP_Down, 0,
                    GTK_MOVEMENT_DISPLAY_LINES, 1);
  
798
  add_move_binding (binding_set, GDK_p, GDK_CONTROL_MASK,
799 800
                    GTK_MOVEMENT_DISPLAY_LINES, -1);

801
  add_move_binding (binding_set, GDK_n, GDK_CONTROL_MASK,
802 803
                    GTK_MOVEMENT_DISPLAY_LINES, 1);

804 805 806 807 808 809 810 811 812 813 814 815
  add_move_binding (binding_set, GDK_Up, GDK_CONTROL_MASK,
                    GTK_MOVEMENT_PARAGRAPHS, -1);

  add_move_binding (binding_set, GDK_KP_Up, GDK_CONTROL_MASK,
                    GTK_MOVEMENT_PARAGRAPHS, -1);
  
  add_move_binding (binding_set, GDK_Down, GDK_CONTROL_MASK,
                    GTK_MOVEMENT_PARAGRAPHS, 1);

  add_move_binding (binding_set, GDK_KP_Down, GDK_CONTROL_MASK,
                    GTK_MOVEMENT_PARAGRAPHS, 1);
  
816
  add_move_binding (binding_set, GDK_a, GDK_CONTROL_MASK,
817
                    GTK_MOVEMENT_PARAGRAPH_ENDS, -1);
818

819
  add_move_binding (binding_set, GDK_e, GDK_CONTROL_MASK,
820
                    GTK_MOVEMENT_PARAGRAPH_ENDS, 1);
821

822
  add_move_binding (binding_set, GDK_f, GDK_MOD1_MASK,
823
                    GTK_MOVEMENT_WORDS, 1);
824

825
  add_move_binding (binding_set, GDK_b, GDK_MOD1_MASK,
826
                    GTK_MOVEMENT_WORDS, -1);
827

828
  add_move_binding (binding_set, GDK_Home, 0,
829
                    GTK_MOVEMENT_DISPLAY_LINE_ENDS, -1);
830

831 832 833
  add_move_binding (binding_set, GDK_KP_Home, 0,
                    GTK_MOVEMENT_DISPLAY_LINE_ENDS, -1);
  
834
  add_move_binding (binding_set, GDK_End, 0,
835 836
                    GTK_MOVEMENT_DISPLAY_LINE_ENDS, 1);

837 838 839
  add_move_binding (binding_set, GDK_KP_End, 0,
                    GTK_MOVEMENT_DISPLAY_LINE_ENDS, 1);
  
840
  add_move_binding (binding_set, GDK_Home, GDK_CONTROL_MASK,
841
                    GTK_MOVEMENT_BUFFER_ENDS, -1);
842

843 844 845
  add_move_binding (binding_set, GDK_KP_Home, GDK_CONTROL_MASK,
                    GTK_MOVEMENT_BUFFER_ENDS, -1);
  
846
  add_move_binding (binding_set, GDK_End, GDK_CONTROL_MASK,
847
                    GTK_MOVEMENT_BUFFER_ENDS, 1);
848

849 850 851
  add_move_binding (binding_set, GDK_KP_End, GDK_CONTROL_MASK,
                    GTK_MOVEMENT_BUFFER_ENDS, 1);
  
852
  add_move_binding (binding_set, GDK_Page_Up, 0,
853
                    GTK_MOVEMENT_PAGES, -1);
854

855 856 857
  add_move_binding (binding_set, GDK_KP_Page_Up, 0,
                    GTK_MOVEMENT_PAGES, -1);
  
858
  add_move_binding (binding_set, GDK_Page_Down, 0,
859 860
                    GTK_MOVEMENT_PAGES, 1);

861 862
  add_move_binding (binding_set, GDK_KP_Page_Down, 0,
                    GTK_MOVEMENT_PAGES, 1);
863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902

  gtk_binding_entry_add_signal (binding_set, GDK_Page_Up, GDK_CONTROL_MASK,
                                "page_horizontally", 2,
                                GTK_TYPE_INT, -1,
                                GTK_TYPE_BOOL, FALSE);

  gtk_binding_entry_add_signal (binding_set, GDK_Page_Up, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
                                "page_horizontally", 2,
                                GTK_TYPE_INT, -1,
                                GTK_TYPE_BOOL, TRUE);

  gtk_binding_entry_add_signal (binding_set, GDK_KP_Page_Up, GDK_CONTROL_MASK,
                                "page_horizontally", 2,
                                GTK_TYPE_INT, -1,
                                GTK_TYPE_BOOL, FALSE);

  gtk_binding_entry_add_signal (binding_set, GDK_KP_Page_Up, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
                                "page_horizontally", 2,
                                GTK_TYPE_INT, -1,
                                GTK_TYPE_BOOL, TRUE);

  gtk_binding_entry_add_signal (binding_set, GDK_Page_Down, GDK_CONTROL_MASK,
                                "page_horizontally", 2,
                                GTK_TYPE_INT, 1,
                                GTK_TYPE_BOOL, FALSE);

  gtk_binding_entry_add_signal (binding_set, GDK_Page_Down, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
                                "page_horizontally", 2,
                                GTK_TYPE_INT, 1,
                                GTK_TYPE_BOOL, TRUE);

  gtk_binding_entry_add_signal (binding_set, GDK_KP_Page_Down, GDK_CONTROL_MASK,
                                "page_horizontally", 2,
                                GTK_TYPE_INT, 1,
                                GTK_TYPE_BOOL, FALSE);

  gtk_binding_entry_add_signal (binding_set, GDK_KP_Page_Down, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
                                "page_horizontally", 2,
                                GTK_TYPE_INT, 1,
                                GTK_TYPE_BOOL, TRUE);
903
  
904 905
  /* Setting the cut/paste/copy anchor */
  gtk_binding_entry_add_signal (binding_set, GDK_space, GDK_CONTROL_MASK,
906
                                "set_anchor", 0);
907 908 909
  gtk_binding_entry_add_signal (binding_set, GDK_KP_Space, GDK_CONTROL_MASK,
                                "set_anchor", 0);
  
910 911
  /* Deleting text */
  gtk_binding_entry_add_signal (binding_set, GDK_Delete, 0,
912
                                "delete_from_cursor", 2,
913 914 915
                                GTK_TYPE_ENUM, GTK_DELETE_CHARS,
                                GTK_TYPE_INT, 1);

916 917 918 919 920
  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);
  
921
  gtk_binding_entry_add_signal (binding_set, GDK_d, GDK_CONTROL_MASK,
922
                                "delete_from_cursor", 2,
923 924
                                GTK_TYPE_ENUM, GTK_DELETE_CHARS,
                                GTK_TYPE_INT, 1);
925 926

  gtk_binding_entry_add_signal (binding_set, GDK_BackSpace, 0,
927
                                "delete_from_cursor", 2,
928 929
                                GTK_TYPE_ENUM, GTK_DELETE_CHARS,
                                GTK_TYPE_INT, -1);
930 931

  gtk_binding_entry_add_signal (binding_set, GDK_Delete, GDK_CONTROL_MASK,
932
                                "delete_from_cursor", 2,
933 934
                                GTK_TYPE_ENUM, GTK_DELETE_WORD_ENDS,
                                GTK_TYPE_INT, 1);
935

936 937 938 939 940
  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);
  
941
  gtk_binding_entry_add_signal (binding_set, GDK_d, GDK_MOD1_MASK,
942
                                "delete_from_cursor", 2,
943 944
                                GTK_TYPE_ENUM, GTK_DELETE_WORD_ENDS,
                                GTK_TYPE_INT, 1);
945 946

  gtk_binding_entry_add_signal (binding_set, GDK_BackSpace, GDK_CONTROL_MASK,
947
                                "delete_from_cursor", 2,
948 949
                                GTK_TYPE_ENUM, GTK_DELETE_WORD_ENDS,
                                GTK_TYPE_INT, -1);
950 951

  gtk_binding_entry_add_signal (binding_set, GDK_k, GDK_CONTROL_MASK,
952
                                "delete_from_cursor", 2,
953 954
                                GTK_TYPE_ENUM, GTK_DELETE_PARAGRAPH_ENDS,
                                GTK_TYPE_INT, 1);
955 956

  gtk_binding_entry_add_signal (binding_set, GDK_u, GDK_CONTROL_MASK,
957
                                "delete_from_cursor", 2,
958 959
                                GTK_TYPE_ENUM, GTK_DELETE_PARAGRAPHS,
                                GTK_TYPE_INT, 1);
960 961

  gtk_binding_entry_add_signal (binding_set, GDK_space, GDK_MOD1_MASK,
962
                                "delete_from_cursor", 2,
963 964
                                GTK_TYPE_ENUM, GTK_DELETE_WHITESPACE,
                                GTK_TYPE_INT, 1);
965 966 967 968
  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);
969
  gtk_binding_entry_add_signal (binding_set, GDK_space, GDK_MOD1_MASK,
970 971
                                "insert_at_cursor", 1,
                                GTK_TYPE_STRING, " ");
972 973 974 975
  gtk_binding_entry_add_signal (binding_set, GDK_KP_Space, GDK_MOD1_MASK,
                                "insert_at_cursor", 1,
                                GTK_TYPE_STRING, " ");
  
976
  gtk_binding_entry_add_signal (binding_set, GDK_backslash, GDK_MOD1_MASK,
977
                                "delete_from_cursor", 2,
978 979 980
                                GTK_TYPE_ENUM, GTK_DELETE_WHITESPACE,
                                GTK_TYPE_INT, 1);

981 982 983
  /* Cut/copy/paste */

  gtk_binding_entry_add_signal (binding_set, GDK_x, GDK_CONTROL_MASK,
984
                                "cut_clipboard", 0);
985 986

  gtk_binding_entry_add_signal (binding_set, GDK_w, GDK_CONTROL_MASK,
987 988
                                "cut_clipboard", 0);

989
  gtk_binding_entry_add_signal (binding_set, GDK_c, GDK_CONTROL_MASK,
990 991
                                "copy_clipboard", 0);

992
  gtk_binding_entry_add_signal (binding_set, GDK_v, GDK_CONTROL_MASK,
993
                                "paste_clipboard", 0);
994

995
  gtk_binding_entry_add_signal (binding_set, GDK_y, GDK_CONTROL_MASK,
996
                                "paste_clipboard", 0);
997 998 999

  /* Overwrite */
  gtk_binding_entry_add_signal (binding_set, GDK_Insert, 0,
1000
                                "toggle_overwrite", 0);
1001 1002
  gtk_binding_entry_add_signal (binding_set, GDK_KP_Insert, 0,
                                "toggle_overwrite", 0);
1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023

  /* Control-tab focus motion */
  gtk_binding_entry_add_signal (binding_set, GDK_Tab, GDK_CONTROL_MASK,
                                "move_focus", 1,
                                GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_FORWARD);
  gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, GDK_CONTROL_MASK,
                                "move_focus", 1,
                                GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_FORWARD);
  gtk_binding_entry_add_signal (binding_set, GDK_ISO_Left_Tab, GDK_CONTROL_MASK,
                                "move_focus", 1,
                                GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_FORWARD);
  
  gtk_binding_entry_add_signal (binding_set, GDK_Tab, GDK_SHIFT_MASK | GDK_CONTROL_MASK,
                                "move_focus", 1,
                                GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_BACKWARD);
  gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, GDK_SHIFT_MASK | GDK_CONTROL_MASK,
                                "move_focus", 1,
                                GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_BACKWARD);
  gtk_binding_entry_add_signal (binding_set, GDK_ISO_Left_Tab, GDK_SHIFT_MASK | GDK_CONTROL_MASK,
                                "move_focus", 1,
                                GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_BACKWARD);
1024 1025
}

1026
static void
1027 1028 1029
gtk_text_view_init (GtkTextView *text_view)
{
  GtkWidget *widget;
1030

1031 1032 1033 1034
  widget = GTK_WIDGET (text_view);

  GTK_WIDGET_SET_FLAGS (widget, GTK_CAN_FOCUS);

1035
  /* Set up default style */
1036
  text_view->wrap_mode = GTK_WRAP_NONE;
1037 1038 1039 1040 1041 1042 1043 1044 1045
  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;
1046

1047
  gtk_drag_dest_set (widget,
1048
		     0,
1049 1050
                     target_table, G_N_ELEMENTS (target_table),
                     GDK_ACTION_COPY | GDK_ACTION_MOVE);
1051 1052 1053 1054 1055

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

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

1060 1061 1062 1063
  g_signal_connect (G_OBJECT (text_view->im_context), "commit",
                    G_CALLBACK (gtk_text_view_commit_handler), text_view);
  g_signal_connect (G_OBJECT (text_view->im_context), "preedit_changed",
 		    G_CALLBACK (gtk_text_view_preedit_changed_handler), text_view);
1064 1065 1066 1067
  g_signal_connect (G_OBJECT (text_view->im_context), "retrieve_surrounding",
 		    G_CALLBACK (gtk_text_view_retrieve_surrounding_handler), text_view);
  g_signal_connect (G_OBJECT (text_view->im_context), "delete_surrounding",
 		    G_CALLBACK (gtk_text_view_delete_surrounding_handler), text_view);
1068

1069
  text_view->cursor_visible = TRUE;
1070 1071 1072

  text_view->text_window = text_window_new (GTK_TEXT_WINDOW_TEXT,
                                            widget, 200, 200);
Havoc Pennington's avatar
Havoc Pennington committed
1073 1074 1075

  text_view->drag_start_x = -1;
  text_view->drag_start_y = -1;
Havoc Pennington's avatar
Havoc Pennington committed
1076 1077

  text_view->pending_place_cursor_button = 0;
1078 1079 1080

  /* We handle all our own redrawing */
  gtk_widget_set_redraw_on_allocate (widget, FALSE);
1081 1082
}

1083 1084
/**
 * gtk_text_view_new:
1085
 *
1086 1087 1088 1089 1090 1091 1092
 * 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
 **/
1093 1094 1095 1096 1097 1098
GtkWidget*
gtk_text_view_new (void)
{
  return GTK_WIDGET (gtk_type_new (gtk_text_view_get_type ()));
}

1099 1100 1101
/**
 * gtk_text_view_new_with_buffer:
 * @buffer: a #GtkTextBuffer
1102
 *
1103 1104 1105 1106 1107 1108
 * 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.
1109
 *
1110 1111
 * Return value: a new #GtkTextView.
 **/
1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123
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);
}

1124 1125 1126 1127 1128 1129 1130 1131 1132 1133
/**
 * 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.
1134
 *
1135
 **/
1136
void
1137
gtk_text_view_set_buffer (GtkTextView   *text_view,
1138
                          GtkTextBuffer *buffer)
1139 1140 1141
{
  g_return_if_fail (GTK_IS_TEXT_VIEW (text_view));
  g_return_if_fail (buffer == NULL || GTK_IS_TEXT_BUFFER (buffer));
1142

1143 1144 1145 1146 1147
  if (text_view->buffer == buffer)
    return;

  if (text_view->buffer != NULL)
    {
1148 1149 1150
      /* Destroy all anchored children */
      GSList *tmp_list;
      GSList *copy;
1151

1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162
      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! */
            }
1163

1164 1165 1166 1167
          tmp_list = g_slist_next (tmp_list);
        }

      g_slist_free (copy);
1168

1169 1170 1171
      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));
1172
      text_view->dnd_mark = NULL;
1173 1174 1175 1176

      if (GTK_WIDGET_REALIZED (text_view))
	gtk_text_buffer_remove_selection_clipboard (text_view->buffer,
						    gtk_clipboard_get (GDK_SELECTION_PRIMARY));
1177 1178 1179
    }

  text_view->buffer = buffer;
1180

1181 1182 1183
  if (buffer != NULL)
    {
      GtkTextIter start;
1184

1185
      g_object_ref (G_OBJECT (buffer));
1186 1187 1188 1189

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

1190
      gtk_text_buffer_get_iter_at_offset (text_view->buffer, &start, 0);
1191

1192
      text_view->dnd_mark = gtk_text_buffer_create_mark (text_view->buffer,
1193 1194
                                                         "gtk_drag_target",
                                                         &start, FALSE);
1195 1196

      text_view->first_para_mark = gtk_text_buffer_create_mark (text_view->buffer,
1197
                                                                NULL,
1198 1199
                                                                &start, TRUE);

1200
      text_view->first_para_pixels = 0;
1201

1202 1203
      g_signal_connect (G_OBJECT (text_view->buffer), "mark_set",
			G_CALLBACK (gtk_text_view_mark_set_handler), text_view);
Owen Taylor's avatar