gtktext.c 144 KB
Newer Older
Elliot Lee's avatar
Elliot Lee committed
1 2 3 4
/* GTK - The GIMP Toolkit
 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
 *
 * This library is free software; you can redistribute it and/or
5
 * modify it under the terms of the GNU Lesser General Public
Elliot Lee's avatar
Elliot Lee committed
6 7 8 9 10 11
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
 * Lesser General Public License for more details.
Elliot Lee's avatar
Elliot Lee committed
13
 *
14
 * You should have received a copy of the GNU Lesser General Public
15 16 17
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
Elliot Lee's avatar
Elliot Lee committed
18
 */
19 20

/*
21
 * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
22 23 24 25 26
 * file for a list of people on the GTK+ Team.  See the ChangeLog
 * files for a list of changes.  These files are distributed with
 * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
 */

Manish Singh's avatar
Manish Singh committed
27
#undef GDK_DISABLE_DEPRECATED
28
#undef GTK_DISABLE_DEPRECATED
Manish Singh's avatar
Manish Singh committed
29

Elliot Lee's avatar
Elliot Lee committed
30 31 32
#include <ctype.h>
#include <string.h>
#include "gdk/gdkkeysyms.h"
33
#include "gdk/gdki18n.h"
Elliot Lee's avatar
Elliot Lee committed
34
#include "gtkmain.h"
35
#include "gtkmarshalers.h"
36
#include "gtkselection.h"
Elliot Lee's avatar
Elliot Lee committed
37
#include "gtksignal.h"
38
#define GTK_ENABLE_BROKEN
Elliot Lee's avatar
Elliot Lee committed
39 40 41
#include "gtktext.h"
#include "line-wrap.xbm"
#include "line-arrow.xbm"
42
#include "gtkintl.h"
Elliot Lee's avatar
Elliot Lee committed
43 44 45 46 47 48 49 50


#define INITIAL_BUFFER_SIZE      1024
#define INITIAL_LINE_CACHE_SIZE  256
#define MIN_GAP_SIZE             256
#define LINE_DELIM               '\n'
#define MIN_TEXT_WIDTH_LINES     20
#define MIN_TEXT_HEIGHT_LINES    10
51
#define TEXT_BORDER_ROOM         1
Elliot Lee's avatar
Elliot Lee committed
52 53 54 55
#define LINE_WRAP_ROOM           8           /* The bitmaps are 6 wide. */
#define DEFAULT_TAB_STOP_WIDTH   4
#define SCROLL_PIXELS            5
#define KEY_SCROLL_PIXELS        10
56
#define SCROLL_TIME              100
Owen Taylor's avatar
Owen Taylor committed
57 58
#define FREEZE_LENGTH            1024        
/* Freeze text when inserting or deleting more than this many characters */
Elliot Lee's avatar
Elliot Lee committed
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73

#define SET_PROPERTY_MARK(m, p, o)  do {                   \
                                      (m)->property = (p); \
			              (m)->offset = (o);   \
			            } while (0)
#define MARK_CURRENT_PROPERTY(mark) ((TextProperty*)(mark)->property->data)
#define MARK_NEXT_PROPERTY(mark)    ((TextProperty*)(mark)->property->next->data)
#define MARK_PREV_PROPERTY(mark)    ((TextProperty*)((mark)->property->prev ?     \
						     (mark)->property->prev->data \
						     : NULL))
#define MARK_PREV_LIST_PTR(mark)    ((mark)->property->prev)
#define MARK_LIST_PTR(mark)         ((mark)->property)
#define MARK_NEXT_LIST_PTR(mark)    ((mark)->property->next)
#define MARK_OFFSET(mark)           ((mark)->offset)
#define MARK_PROPERTY_LENGTH(mark)  (MARK_CURRENT_PROPERTY(mark)->length)
74

75 76 77 78

#define MARK_CURRENT_FONT(text, mark) \
  ((MARK_CURRENT_PROPERTY(mark)->flags & PROPERTY_FONT) ? \
         MARK_CURRENT_PROPERTY(mark)->font->gdk_font : \
79
         gtk_style_get_font (GTK_WIDGET (text)->style))
80 81 82 83 84 85 86 87 88 89 90 91 92
#define MARK_CURRENT_FORE(text, mark) \
  ((MARK_CURRENT_PROPERTY(mark)->flags & PROPERTY_FOREGROUND) ? \
         &MARK_CURRENT_PROPERTY(mark)->fore_color : \
         &((GtkWidget *)text)->style->text[((GtkWidget *)text)->state])
#define MARK_CURRENT_BACK(text, mark) \
  ((MARK_CURRENT_PROPERTY(mark)->flags & PROPERTY_BACKGROUND) ? \
         &MARK_CURRENT_PROPERTY(mark)->back_color : \
         &((GtkWidget *)text)->style->base[((GtkWidget *)text)->state])
#define MARK_CURRENT_TEXT_FONT(text, mark) \
  ((MARK_CURRENT_PROPERTY(mark)->flags & PROPERTY_FONT) ? \
         MARK_CURRENT_PROPERTY(mark)->font : \
         text->current_font)

Elliot Lee's avatar
Elliot Lee committed
93 94 95 96 97 98 99 100 101
#define TEXT_LENGTH(t)              ((t)->text_end - (t)->gap_size)
#define FONT_HEIGHT(f)              ((f)->ascent + (f)->descent)
#define LINE_HEIGHT(l)              ((l).font_ascent + (l).font_descent)
#define LINE_CONTAINS(l, i)         ((l).start.index <= (i) && (l).end.index >= (i))
#define LINE_STARTS_AT(l, i)        ((l).start.index == (i))
#define LINE_START_PIXEL(l)         ((l).tab_cont.pixel_offset)
#define LAST_INDEX(t, m)            ((m).index == TEXT_LENGTH(t))
#define CACHE_DATA(c)               (*(LineParams*)(c)->data)

102
enum {
103 104 105 106 107
  PROP_0,
  PROP_HADJUSTMENT,
  PROP_VADJUSTMENT,
  PROP_LINE_WRAP,
  PROP_WORD_WRAP
108 109
};

Elliot Lee's avatar
Elliot Lee committed
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
typedef struct _TextProperty          TextProperty;
typedef struct _TabStopMark           TabStopMark;
typedef struct _PrevTabCont           PrevTabCont;
typedef struct _FetchLinesData        FetchLinesData;
typedef struct _LineParams            LineParams;
typedef struct _SetVerticalScrollData SetVerticalScrollData;

typedef gint (*LineIteratorFunction) (GtkText* text, LineParams* lp, void* data);

typedef enum
{
  FetchLinesPixels,
  FetchLinesCount
} FLType;

struct _SetVerticalScrollData {
  gint pixel_height;
  gint last_didnt_wrap;
  gint last_line_start;
  GtkPropertyMark mark;
};

132
struct _GtkTextFont
Elliot Lee's avatar
Elliot Lee committed
133 134 135
{
  /* The actual font. */
  GdkFont *gdk_font;
136 137
  guint ref_count;

Elliot Lee's avatar
Elliot Lee committed
138 139 140
  gint16 char_widths[256];
};

141 142 143 144 145 146
typedef enum {
  PROPERTY_FONT =       1 << 0,
  PROPERTY_FOREGROUND = 1 << 1,
  PROPERTY_BACKGROUND = 1 << 2
} TextPropertyFlags;

Elliot Lee's avatar
Elliot Lee committed
147 148 149
struct _TextProperty
{
  /* Font. */
150 151
  GtkTextFont* font;

Elliot Lee's avatar
Elliot Lee committed
152
  /* Background Color. */
153
  GdkColor back_color;
154
  
Elliot Lee's avatar
Elliot Lee committed
155
  /* Foreground Color. */
156
  GdkColor fore_color;
157 158 159 160

  /* Show which properties are set */
  TextPropertyFlags flags;

Elliot Lee's avatar
Elliot Lee committed
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
  /* Length of this property. */
  guint length;
};

struct _TabStopMark
{
  GList* tab_stops; /* Index into list containing the next tab position.  If
		     * NULL, using default widths. */
  gint to_next_tab;
};

struct _PrevTabCont
{
  guint pixel_offset;
  TabStopMark tab_start;
};

struct _FetchLinesData
{
  GList* new_lines;
  FLType fl_type;
  gint data;
  gint data_max;
};

struct _LineParams
{
  guint font_ascent;
  guint font_descent;
  guint pixel_width;
  guint displayable_chars;
  guint wraps : 1;
193
  
Elliot Lee's avatar
Elliot Lee committed
194 195
  PrevTabCont tab_cont;
  PrevTabCont tab_cont_next;
196
  
Elliot Lee's avatar
Elliot Lee committed
197 198 199 200 201 202
  GtkPropertyMark start;
  GtkPropertyMark end;
};


static void  gtk_text_class_init     (GtkTextClass   *klass);
203 204 205 206 207 208 209 210
static void  gtk_text_set_property   (GObject         *object,
				      guint            prop_id,
				      const GValue    *value,
				      GParamSpec      *pspec);
static void  gtk_text_get_property   (GObject         *object,
				      guint            prop_id,
				      GValue          *value,
				      GParamSpec      *pspec);
211
static void  gtk_text_editable_init  (GtkEditableClass *iface);
Elliot Lee's avatar
Elliot Lee committed
212
static void  gtk_text_init           (GtkText        *text);
213
static void  gtk_text_destroy        (GtkObject      *object);
214
static void  gtk_text_finalize       (GObject        *object);
Elliot Lee's avatar
Elliot Lee committed
215 216
static void  gtk_text_realize        (GtkWidget      *widget);
static void  gtk_text_unrealize      (GtkWidget      *widget);
217 218
static void  gtk_text_style_set	     (GtkWidget      *widget,
				      GtkStyle       *previous_style);
Owen Taylor's avatar
Owen Taylor committed
219 220
static void  gtk_text_state_changed  (GtkWidget      *widget,
				      GtkStateType    previous_state);
Elliot Lee's avatar
Elliot Lee committed
221 222 223 224 225 226 227
static void  gtk_text_draw_focus     (GtkWidget      *widget);
static void  gtk_text_size_request   (GtkWidget      *widget,
				      GtkRequisition *requisition);
static void  gtk_text_size_allocate  (GtkWidget      *widget,
				      GtkAllocation  *allocation);
static void  gtk_text_adjustment     (GtkAdjustment  *adjustment,
				      GtkText        *text);
228
static void   gtk_text_insert_text       (GtkEditable    *editable,
Owen Taylor's avatar
Owen Taylor committed
229 230 231
					  const gchar    *new_text,
					  gint            new_text_length,
					  gint           *position);
232
static void   gtk_text_delete_text       (GtkEditable    *editable,
Owen Taylor's avatar
Owen Taylor committed
233 234 235 236 237 238 239 240 241 242 243 244 245
					  gint            start_pos,
					  gint            end_pos);
static void   gtk_text_update_text       (GtkOldEditable *old_editable,
					  gint            start_pos,
					  gint            end_pos);
static gchar *gtk_text_get_chars         (GtkOldEditable *old_editable,
					  gint            start,
					  gint            end);
static void   gtk_text_set_selection     (GtkOldEditable *old_editable,
					  gint            start,
					  gint            end);
static void   gtk_text_real_set_editable (GtkOldEditable *old_editable,
					  gboolean        is_editable);
246

Havoc Pennington's avatar
Havoc Pennington committed
247 248 249
static void  gtk_text_adjustment_destroyed (GtkAdjustment  *adjustment,
                                            GtkText        *text);

Elliot Lee's avatar
Elliot Lee committed
250 251 252 253 254 255 256 257 258 259 260 261
/* Event handlers */
static gint  gtk_text_expose            (GtkWidget         *widget,
					 GdkEventExpose    *event);
static gint  gtk_text_button_press      (GtkWidget         *widget,
					 GdkEventButton    *event);
static gint  gtk_text_button_release    (GtkWidget         *widget,
					 GdkEventButton    *event);
static gint  gtk_text_motion_notify     (GtkWidget         *widget,
					 GdkEventMotion    *event);
static gint  gtk_text_key_press         (GtkWidget         *widget,
					 GdkEventKey       *event);

262
static void move_gap (GtkText* text, guint index);
Elliot Lee's avatar
Elliot Lee committed
263
static void make_forward_space (GtkText* text, guint len);
264 265 266 267 268

/* Property management */
static GtkTextFont* get_text_font (GdkFont* gfont);
static void         text_font_unref (GtkTextFont *text_font);

Elliot Lee's avatar
Elliot Lee committed
269 270
static void insert_text_property (GtkText* text, GdkFont* font,
				  GdkColor *fore, GdkColor* back, guint len);
271 272 273 274 275 276 277 278 279
static TextProperty* new_text_property (GtkText *text, GdkFont* font, 
					GdkColor* fore, GdkColor* back, guint length);
static void destroy_text_property (TextProperty *prop);
static void init_properties      (GtkText *text);
static void realize_property     (GtkText *text, TextProperty *prop);
static void realize_properties   (GtkText *text);
static void unrealize_property   (GtkText *text, TextProperty *prop);
static void unrealize_properties (GtkText *text);

Elliot Lee's avatar
Elliot Lee committed
280
static void delete_text_property (GtkText* text, guint len);
281

Elliot Lee's avatar
Elliot Lee committed
282 283 284 285 286 287 288 289 290 291
static guint pixel_height_of (GtkText* text, GList* cache_line);

/* Property Movement and Size Computations */
static void advance_mark (GtkPropertyMark* mark);
static void decrement_mark (GtkPropertyMark* mark);
static void advance_mark_n (GtkPropertyMark* mark, gint n);
static void decrement_mark_n (GtkPropertyMark* mark, gint n);
static void move_mark_n (GtkPropertyMark* mark, gint n);
static GtkPropertyMark find_mark (GtkText* text, guint mark_position);
static GtkPropertyMark find_mark_near (GtkText* text, guint mark_position, const GtkPropertyMark* near);
292 293
static void find_line_containing_point (GtkText* text, guint point,
					gboolean scroll);
Elliot Lee's avatar
Elliot Lee committed
294 295

/* Display */
Owen Taylor's avatar
Owen Taylor committed
296
static void compute_lines_pixels (GtkText* text, guint char_count,
Owen Taylor's avatar
Owen Taylor committed
297 298
				  guint *lines, guint *pixels);

Elliot Lee's avatar
Elliot Lee committed
299 300 301 302 303 304 305 306
static gint total_line_height (GtkText* text,
			       GList* line,
			       gint line_count);
static LineParams find_line_params (GtkText* text,
				    const GtkPropertyMark *mark,
				    const PrevTabCont *tab_cont,
				    PrevTabCont *next_cont);
static void recompute_geometry (GtkText* text);
Owen Taylor's avatar
Owen Taylor committed
307 308
static void insert_expose (GtkText* text, guint old_pixels, gint nchars, guint new_line_count);
static void delete_expose (GtkText* text,
Owen Taylor's avatar
Owen Taylor committed
309
			   guint nchars,
Owen Taylor's avatar
Owen Taylor committed
310 311
			   guint old_lines, 
			   guint old_pixels);
312
static GdkGC *create_bg_gc (GtkText *text);
Elliot Lee's avatar
Elliot Lee committed
313 314 315 316 317 318 319 320 321 322 323 324 325
static void clear_area (GtkText *text, GdkRectangle *area);
static void draw_line (GtkText* text,
		       gint pixel_height,
		       LineParams* lp);
static void draw_line_wrap (GtkText* text,
			    guint height);
static void draw_cursor (GtkText* text, gint absolute);
static void undraw_cursor (GtkText* text, gint absolute);
static gint drawn_cursor_min (GtkText* text);
static gint drawn_cursor_max (GtkText* text);
static void expose_text (GtkText* text, GdkRectangle *area, gboolean cursor);

/* Search and Placement. */
326 327
static void find_cursor (GtkText* text,
			 gboolean scroll);
Elliot Lee's avatar
Elliot Lee committed
328 329 330
static void find_cursor_at_line (GtkText* text,
				 const LineParams* start_line,
				 gint pixel_height);
331
static void find_mouse_cursor (GtkText* text, gint x, gint y);
Elliot Lee's avatar
Elliot Lee committed
332 333 334 335 336 337 338

/* Scrolling. */
static void adjust_adj  (GtkText* text, GtkAdjustment* adj);
static void scroll_up   (GtkText* text, gint diff);
static void scroll_down (GtkText* text, gint diff);
static void scroll_int  (GtkText* text, gint diff);

339 340
static void process_exposes (GtkText *text);

Elliot Lee's avatar
Elliot Lee committed
341
/* Cache Management. */
342
static void   free_cache        (GtkText* text);
Elliot Lee's avatar
Elliot Lee committed
343 344 345 346 347 348 349 350
static GList* remove_cache_line (GtkText* text, GList* list);

/* Key Motion. */
static void move_cursor_buffer_ver (GtkText *text, int dir);
static void move_cursor_page_ver (GtkText *text, int dir);
static void move_cursor_ver (GtkText *text, int count);
static void move_cursor_hor (GtkText *text, int count);

351
/* Binding actions */
Owen Taylor's avatar
Owen Taylor committed
352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369
static void gtk_text_move_cursor    (GtkOldEditable *old_editable,
				     gint            x,
				     gint            y);
static void gtk_text_move_word      (GtkOldEditable *old_editable,
				     gint            n);
static void gtk_text_move_page      (GtkOldEditable *old_editable,
				     gint            x,
				     gint            y);
static void gtk_text_move_to_row    (GtkOldEditable *old_editable,
				     gint            row);
static void gtk_text_move_to_column (GtkOldEditable *old_editable,
				     gint            row);
static void gtk_text_kill_char      (GtkOldEditable *old_editable,
				     gint            direction);
static void gtk_text_kill_word      (GtkOldEditable *old_editable,
				     gint            direction);
static void gtk_text_kill_line      (GtkOldEditable *old_editable,
				     gint            direction);
370 371

/* To be removed */
372 373 374 375 376 377
static void gtk_text_move_forward_character    (GtkText          *text);
static void gtk_text_move_backward_character   (GtkText          *text);
static void gtk_text_move_forward_word         (GtkText          *text);
static void gtk_text_move_backward_word        (GtkText          *text);
static void gtk_text_move_beginning_of_line    (GtkText          *text);
static void gtk_text_move_end_of_line          (GtkText          *text);
Owen Taylor's avatar
Owen Taylor committed
378 379 380
static void gtk_text_move_next_line            (GtkText          *text);
static void gtk_text_move_previous_line        (GtkText          *text);

381 382 383 384 385 386
static void gtk_text_delete_forward_character  (GtkText          *text);
static void gtk_text_delete_backward_character (GtkText          *text);
static void gtk_text_delete_forward_word       (GtkText          *text);
static void gtk_text_delete_backward_word      (GtkText          *text);
static void gtk_text_delete_line               (GtkText          *text);
static void gtk_text_delete_to_line_end        (GtkText          *text);
387 388 389 390
static void gtk_text_select_word               (GtkText          *text,
						guint32           time);
static void gtk_text_select_line               (GtkText          *text,
						guint32           time);
391

Owen Taylor's avatar
Owen Taylor committed
392 393
static void gtk_text_set_position (GtkOldEditable *old_editable,
				   gint            position);
Owen Taylor's avatar
Owen Taylor committed
394

395
/* #define DEBUG_GTK_TEXT */
Elliot Lee's avatar
Elliot Lee committed
396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421

#if defined(DEBUG_GTK_TEXT) && defined(__GNUC__)
/* Debugging utilities. */
static void gtk_text_assert_mark (GtkText         *text,
				  GtkPropertyMark *mark,
				  GtkPropertyMark *before,
				  GtkPropertyMark *after,
				  const gchar     *msg,
				  const gchar     *where,
				  gint             line);

static void gtk_text_assert (GtkText         *text,
			     const gchar     *msg,
			     gint             line);
static void gtk_text_show_cache_line (GtkText *text, GList *cache,
				      const char* what, const char* func, gint line);
static void gtk_text_show_cache (GtkText *text, const char* func, gint line);
static void gtk_text_show_adj (GtkText *text,
			       GtkAdjustment *adj,
			       const char* what,
			       const char* func,
			       gint line);
static void gtk_text_show_props (GtkText* test,
				 const char* func,
				 int line);

422
#define TDEBUG(args) g_message args
Elliot Lee's avatar
Elliot Lee committed
423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446
#define TEXT_ASSERT(text) gtk_text_assert (text,__PRETTY_FUNCTION__,__LINE__)
#define TEXT_ASSERT_MARK(text,mark,msg) gtk_text_assert_mark (text,mark, \
					   __PRETTY_FUNCTION__,msg,__LINE__)
#define TEXT_SHOW(text) gtk_text_show_cache (text, __PRETTY_FUNCTION__,__LINE__)
#define TEXT_SHOW_LINE(text,line,msg) gtk_text_show_cache_line (text,line,msg,\
					   __PRETTY_FUNCTION__,__LINE__)
#define TEXT_SHOW_ADJ(text,adj,msg) gtk_text_show_adj (text,adj,msg, \
					  __PRETTY_FUNCTION__,__LINE__)
#else
#define TDEBUG(args)
#define TEXT_ASSERT(text)
#define TEXT_ASSERT_MARK(text,mark,msg)
#define TEXT_SHOW(text)
#define TEXT_SHOW_LINE(text,line,msg)
#define TEXT_SHOW_ADJ(text,adj,msg)
#endif

/* Memory Management. */
static GMemChunk  *params_mem_chunk    = NULL;
static GMemChunk  *text_property_chunk = NULL;

static GtkWidgetClass *parent_class = NULL;


447
static const GtkTextFunction control_keys[26] =
448 449 450
{
  (GtkTextFunction)gtk_text_move_beginning_of_line,    /* a */
  (GtkTextFunction)gtk_text_move_backward_character,   /* b */
451
  (GtkTextFunction)gtk_editable_copy_clipboard,        /* c */
452 453 454 455 456 457 458 459 460 461
  (GtkTextFunction)gtk_text_delete_forward_character,  /* d */
  (GtkTextFunction)gtk_text_move_end_of_line,          /* e */
  (GtkTextFunction)gtk_text_move_forward_character,    /* f */
  NULL,                                                /* g */
  (GtkTextFunction)gtk_text_delete_backward_character, /* h */
  NULL,                                                /* i */
  NULL,                                                /* j */
  (GtkTextFunction)gtk_text_delete_to_line_end,        /* k */
  NULL,                                                /* l */
  NULL,                                                /* m */
Owen Taylor's avatar
Owen Taylor committed
462
  (GtkTextFunction)gtk_text_move_next_line,            /* n */
463
  NULL,                                                /* o */
Owen Taylor's avatar
Owen Taylor committed
464
  (GtkTextFunction)gtk_text_move_previous_line,        /* p */
465 466 467 468 469
  NULL,                                                /* q */
  NULL,                                                /* r */
  NULL,                                                /* s */
  NULL,                                                /* t */
  (GtkTextFunction)gtk_text_delete_line,               /* u */
470
  (GtkTextFunction)gtk_editable_paste_clipboard,       /* v */
471
  (GtkTextFunction)gtk_text_delete_backward_word,      /* w */
472
  (GtkTextFunction)gtk_editable_cut_clipboard,         /* x */
473 474 475 476
  NULL,                                                /* y */
  NULL,                                                /* z */
};

477
static const GtkTextFunction alt_keys[26] =
478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507
{
  NULL,                                                /* a */
  (GtkTextFunction)gtk_text_move_backward_word,        /* b */
  NULL,                                                /* c */
  (GtkTextFunction)gtk_text_delete_forward_word,       /* d */
  NULL,                                           /* e */
  (GtkTextFunction)gtk_text_move_forward_word,         /* f */
  NULL,                                           /* g */
  NULL,                                           /* h */
  NULL,                                           /* i */
  NULL,                                           /* j */
  NULL,                                           /* k */
  NULL,                                           /* l */
  NULL,                                           /* m */
  NULL,                                           /* n */
  NULL,                                           /* o */
  NULL,                                           /* p */
  NULL,                                           /* q */
  NULL,                                           /* r */
  NULL,                                           /* s */
  NULL,                                           /* t */
  NULL,                                           /* u */
  NULL,                                           /* v */
  NULL,                                           /* w */
  NULL,                                           /* x */
  NULL,                                           /* y */
  NULL,                                           /* z */
};


Elliot Lee's avatar
Elliot Lee committed
508 509 510 511
/**********************************************************************/
/*			        Widget Crap                           */
/**********************************************************************/

512
GtkType
513
gtk_text_get_type (void)
Elliot Lee's avatar
Elliot Lee committed
514
{
515
  static GtkType text_type = 0;
516
  
Elliot Lee's avatar
Elliot Lee committed
517 518
  if (!text_type)
    {
519
      static const GtkTypeInfo text_info =
Elliot Lee's avatar
Elliot Lee committed
520 521 522 523 524 525
      {
	"GtkText",
	sizeof (GtkText),
	sizeof (GtkTextClass),
	(GtkClassInitFunc) gtk_text_class_init,
	(GtkObjectInitFunc) gtk_text_init,
526 527
	/* reserved_1 */ NULL,
        /* reserved_2 */ NULL,
528
        (GtkClassInitFunc) NULL,
Elliot Lee's avatar
Elliot Lee committed
529
      };
530 531 532 533 534 535 536

      static const GInterfaceInfo editable_info =
      {
	(GInterfaceInitFunc) gtk_text_editable_init, /* interface_init */
	NULL, /* interface_finalize */
	NULL  /* interface_data */
      };
537
      
Owen Taylor's avatar
Owen Taylor committed
538
      text_type = gtk_type_unique (GTK_TYPE_OLD_EDITABLE, &text_info);
539 540 541
      g_type_add_interface_static (text_type,
				   GTK_TYPE_EDITABLE,
				   &editable_info);
Elliot Lee's avatar
Elliot Lee committed
542
    }
543
  
Elliot Lee's avatar
Elliot Lee committed
544 545 546 547 548 549
  return text_type;
}

static void
gtk_text_class_init (GtkTextClass *class)
{
550
  GObjectClass *gobject_class;
Elliot Lee's avatar
Elliot Lee committed
551 552
  GtkObjectClass *object_class;
  GtkWidgetClass *widget_class;
Owen Taylor's avatar
Owen Taylor committed
553
  GtkOldEditableClass *old_editable_class;
554 555

  gobject_class = G_OBJECT_CLASS (class);
Elliot Lee's avatar
Elliot Lee committed
556 557
  object_class = (GtkObjectClass*) class;
  widget_class = (GtkWidgetClass*) class;
Owen Taylor's avatar
Owen Taylor committed
558 559
  old_editable_class = (GtkOldEditableClass*) class;
  parent_class = gtk_type_class (GTK_TYPE_OLD_EDITABLE);
560

561
  gobject_class->finalize = gtk_text_finalize;
562 563 564
  gobject_class->set_property = gtk_text_set_property;
  gobject_class->get_property = gtk_text_get_property;
  
565
  object_class->destroy = gtk_text_destroy;
566
  
Elliot Lee's avatar
Elliot Lee committed
567 568
  widget_class->realize = gtk_text_realize;
  widget_class->unrealize = gtk_text_unrealize;
569
  widget_class->style_set = gtk_text_style_set;
Owen Taylor's avatar
Owen Taylor committed
570
  widget_class->state_changed = gtk_text_state_changed;
Elliot Lee's avatar
Elliot Lee committed
571 572 573 574 575 576 577
  widget_class->size_request = gtk_text_size_request;
  widget_class->size_allocate = gtk_text_size_allocate;
  widget_class->expose_event = gtk_text_expose;
  widget_class->button_press_event = gtk_text_button_press;
  widget_class->button_release_event = gtk_text_button_release;
  widget_class->motion_notify_event = gtk_text_motion_notify;
  widget_class->key_press_event = gtk_text_key_press;
578

Owen Taylor's avatar
Owen Taylor committed
579
  old_editable_class->set_editable = gtk_text_real_set_editable;
580
  
Owen Taylor's avatar
Owen Taylor committed
581 582 583 584 585
  old_editable_class->move_cursor = gtk_text_move_cursor;
  old_editable_class->move_word = gtk_text_move_word;
  old_editable_class->move_page = gtk_text_move_page;
  old_editable_class->move_to_row = gtk_text_move_to_row;
  old_editable_class->move_to_column = gtk_text_move_to_column;
586
  
Owen Taylor's avatar
Owen Taylor committed
587 588 589
  old_editable_class->kill_char = gtk_text_kill_char;
  old_editable_class->kill_word = gtk_text_kill_word;
  old_editable_class->kill_line = gtk_text_kill_line;
590
  
Owen Taylor's avatar
Owen Taylor committed
591 592 593 594
  old_editable_class->update_text = gtk_text_update_text;
  old_editable_class->get_chars   = gtk_text_get_chars;
  old_editable_class->set_selection = gtk_text_set_selection;
  old_editable_class->set_position = gtk_text_set_position;
595

596
  class->set_scroll_adjustments = gtk_text_set_adjustments;
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 623 624 625 626 627 628 629
  g_object_class_install_property (gobject_class,
                                   PROP_HADJUSTMENT,
                                   g_param_spec_object ("hadjustment",
                                                        _("Horizontal Adjustment"),
                                                        _("Horizontal adjustment for the text widget"),
                                                        GTK_TYPE_ADJUSTMENT,
                                                        G_PARAM_READWRITE));

  g_object_class_install_property (gobject_class,
                                   PROP_VADJUSTMENT,
                                   g_param_spec_object ("vadjustment",
                                                        _("Vertical Adjustment"),
                                                        _("Vertical adjustment for the text widget"),
                                                        GTK_TYPE_ADJUSTMENT,
                                                        G_PARAM_READWRITE));

  g_object_class_install_property (gobject_class,
                                   PROP_LINE_WRAP,
                                   g_param_spec_boolean ("line_wrap",
							 _("Line Wrap"),
							 _("Whether lines are wrapped at widget edges"),
							 TRUE,
							 G_PARAM_READWRITE));

  g_object_class_install_property (gobject_class,
                                   PROP_WORD_WRAP,
                                   g_param_spec_boolean ("word_wrap",
							 _("Word Wrap"),
							 _("Whether words are wrapped at widget edges"),
							 FALSE,
							 G_PARAM_READWRITE));

630 631 632 633 634
  widget_class->set_scroll_adjustments_signal =
    gtk_signal_new ("set_scroll_adjustments",
		    GTK_RUN_LAST,
		    GTK_CLASS_TYPE (object_class),
		    GTK_SIGNAL_OFFSET (GtkTextClass, set_scroll_adjustments),
635
		    _gtk_marshal_VOID__OBJECT_OBJECT,
636
		    GTK_TYPE_NONE, 2, GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT);
637 638 639
}

static void
640 641 642 643
gtk_text_set_property (GObject         *object,
		       guint            prop_id,
		       const GValue    *value,
		       GParamSpec      *pspec)
644 645 646 647 648
{
  GtkText *text;
  
  text = GTK_TEXT (object);
  
649
  switch (prop_id)
650
    {
651
    case PROP_HADJUSTMENT:
652
      gtk_text_set_adjustments (text,
653
				g_value_get_object (value),
654 655
				text->vadj);
      break;
656
    case PROP_VADJUSTMENT:
657 658
      gtk_text_set_adjustments (text,
				text->hadj,
659
				g_value_get_object (value));
660
      break;
661 662
    case PROP_LINE_WRAP:
      gtk_text_set_line_wrap (text, g_value_get_boolean (value));
663
      break;
664 665
    case PROP_WORD_WRAP:
      gtk_text_set_word_wrap (text, g_value_get_boolean (value));
666 667
      break;
    default:
668
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
669 670 671 672 673
      break;
    }
}

static void
674 675 676 677
gtk_text_get_property (GObject         *object,
		       guint            prop_id,
		       GValue          *value,
		       GParamSpec      *pspec)
678 679 680 681 682
{
  GtkText *text;
  
  text = GTK_TEXT (object);
  
683
  switch (prop_id)
684
    {
685 686
    case PROP_HADJUSTMENT:
      g_value_set_object (value, text->hadj);
687
      break;
688 689
    case PROP_VADJUSTMENT:
      g_value_set_object (value, text->vadj);
690
      break;
691 692
    case PROP_LINE_WRAP:
      g_value_set_boolean (value, text->line_wrap);
693
      break;
694 695
    case PROP_WORD_WRAP:
      g_value_set_boolean (value, text->word_wrap);
696 697
      break;
    default:
698
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
699 700
      break;
    }
Elliot Lee's avatar
Elliot Lee committed
701 702
}

703 704 705 706 707 708 709
static void
gtk_text_editable_init (GtkEditableClass *iface)
{
  iface->insert_text = gtk_text_insert_text;
  iface->delete_text = gtk_text_delete_text;
}

Elliot Lee's avatar
Elliot Lee committed
710 711 712 713
static void
gtk_text_init (GtkText *text)
{
  GTK_WIDGET_SET_FLAGS (text, GTK_CAN_FOCUS);
714 715 716 717 718

  text->text_area = NULL;
  text->hadj = NULL;
  text->vadj = NULL;
  text->gc = NULL;
719
  text->bg_gc = NULL;
720 721
  text->line_wrap_bitmap = NULL;
  text->line_arrow_bitmap = NULL;
722
  
723 724
  text->use_wchar = FALSE;
  text->text.ch = g_new (guchar, INITIAL_BUFFER_SIZE);
Elliot Lee's avatar
Elliot Lee committed
725
  text->text_len = INITIAL_BUFFER_SIZE;
726 727 728 729
 
  text->scratch_buffer.ch = NULL;
  text->scratch_buffer_len = 0;
 
730
  text->freeze_count = 0;
731
  
Elliot Lee's avatar
Elliot Lee committed
732 733 734 735 736
  if (!params_mem_chunk)
    params_mem_chunk = g_mem_chunk_new ("LineParams",
					sizeof (LineParams),
					256 * sizeof (LineParams),
					G_ALLOC_AND_FREE);
737
  
Elliot Lee's avatar
Elliot Lee committed
738 739
  text->default_tab_width = 4;
  text->tab_stops = NULL;
740
  
Elliot Lee's avatar
Elliot Lee committed
741 742
  text->tab_stops = g_list_prepend (text->tab_stops, (void*)8);
  text->tab_stops = g_list_prepend (text->tab_stops, (void*)8);
743
  
744
  text->line_start_cache = NULL;
745
  text->first_cut_pixels = 0;
746
  
Elliot Lee's avatar
Elliot Lee committed
747
  text->line_wrap = TRUE;
Owen Taylor's avatar
Owen Taylor committed
748
  text->word_wrap = FALSE;
749 750
  
  text->timer = 0;
Owen Taylor's avatar
Owen Taylor committed
751
  text->button = 0;
752
  
753
  text->current_font = NULL;
754
  
755
  init_properties (text);
756
  
Owen Taylor's avatar
Owen Taylor committed
757
  GTK_OLD_EDITABLE (text)->editable = FALSE;
758
  
759
  gtk_text_set_adjustments (text, NULL, NULL);
760
  gtk_editable_set_position (GTK_EDITABLE (text), 0);
Elliot Lee's avatar
Elliot Lee committed
761 762 763 764 765 766
}

GtkWidget*
gtk_text_new (GtkAdjustment *hadj,
	      GtkAdjustment *vadj)
{
767 768 769 770 771 772 773 774 775 776 777 778 779
  GtkWidget *text;

  if (hadj)
    g_return_val_if_fail (GTK_IS_ADJUSTMENT (hadj), NULL);
  if (vadj)
    g_return_val_if_fail (GTK_IS_ADJUSTMENT (vadj), NULL);

  text = gtk_widget_new (GTK_TYPE_TEXT,
			 "hadjustment", hadj,
			 "vadjustment", vadj,
			 NULL);

  return text;
Elliot Lee's avatar
Elliot Lee committed
780 781
}

782 783
void
gtk_text_set_word_wrap (GtkText *text,
784
			gboolean word_wrap)
785 786
{
  g_return_if_fail (GTK_IS_TEXT (text));
787
  
788 789
  text->word_wrap = (word_wrap != FALSE);
  
790
  if (GTK_WIDGET_REALIZED (text))
791 792 793 794
    {
      recompute_geometry (text);
      gtk_widget_queue_draw (GTK_WIDGET (text));
    }
795 796
  
  g_object_notify (G_OBJECT (text), "word_wrap");
797 798
}

799 800
void
gtk_text_set_line_wrap (GtkText *text,
801
			gboolean line_wrap)
802 803 804 805 806 807 808 809 810 811
{
  g_return_if_fail (GTK_IS_TEXT (text));
  
  text->line_wrap = (line_wrap != FALSE);
  
  if (GTK_WIDGET_REALIZED (text))
    {
      recompute_geometry (text);
      gtk_widget_queue_draw (GTK_WIDGET (text));
    }
812 813
  
  g_object_notify (G_OBJECT (text), "line_wrap");
814 815
}

Elliot Lee's avatar
Elliot Lee committed
816 817
void
gtk_text_set_editable (GtkText *text,
818
		       gboolean is_editable)
Elliot Lee's avatar
Elliot Lee committed
819 820
{
  g_return_if_fail (GTK_IS_TEXT (text));
821
  
822 823 824 825
  gtk_editable_set_editable (GTK_EDITABLE (text), is_editable);
}

static void
Owen Taylor's avatar
Owen Taylor committed
826 827
gtk_text_real_set_editable (GtkOldEditable *old_editable,
			    gboolean        is_editable)
828 829
{
  GtkText *text;
830
  
Owen Taylor's avatar
Owen Taylor committed
831
  g_return_if_fail (GTK_IS_TEXT (old_editable));
832
  
Owen Taylor's avatar
Owen Taylor committed
833
  text = GTK_TEXT (old_editable);
834
  
Owen Taylor's avatar
Owen Taylor committed
835
  old_editable->editable = (is_editable != FALSE);
836
  
837
  if (is_editable)
838 839 840
    draw_cursor (text, TRUE);
  else
    undraw_cursor (text, TRUE);
Elliot Lee's avatar
Elliot Lee committed
841 842 843 844 845 846 847 848
}

void
gtk_text_set_adjustments (GtkText       *text,
			  GtkAdjustment *hadj,
			  GtkAdjustment *vadj)
{
  g_return_if_fail (GTK_IS_TEXT (text));
849 850 851 852 853 854 855 856
  if (hadj)
    g_return_if_fail (GTK_IS_ADJUSTMENT (hadj));
  else
    hadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
  if (vadj)
    g_return_if_fail (GTK_IS_ADJUSTMENT (vadj));
  else
    vadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
857
  
Elliot Lee's avatar
Elliot Lee committed
858 859 860 861 862
  if (text->hadj && (text->hadj != hadj))
    {
      gtk_signal_disconnect_by_data (GTK_OBJECT (text->hadj), text);
      gtk_object_unref (GTK_OBJECT (text->hadj));
    }
863
  
Elliot Lee's avatar
Elliot Lee committed
864 865 866 867 868
  if (text->vadj && (text->vadj != vadj))
    {
      gtk_signal_disconnect_by_data (GTK_OBJECT (text->vadj), text);
      gtk_object_unref (GTK_OBJECT (text->vadj));
    }
869
  
870
  g_object_freeze_notify (G_OBJECT (text));
Elliot Lee's avatar
Elliot Lee committed
871 872 873 874
  if (text->hadj != hadj)
    {
      text->hadj = hadj;
      gtk_object_ref (GTK_OBJECT (text->hadj));
875 876
      gtk_object_sink (GTK_OBJECT (text->hadj));
      
Elliot Lee's avatar
Elliot Lee committed
877 878 879 880 881 882
      gtk_signal_connect (GTK_OBJECT (text->hadj), "changed",
			  (GtkSignalFunc) gtk_text_adjustment,
			  text);
      gtk_signal_connect (GTK_OBJECT (text->hadj), "value_changed",
			  (GtkSignalFunc) gtk_text_adjustment,
			  text);
Havoc Pennington's avatar
Havoc Pennington committed
883 884
      gtk_signal_connect (GTK_OBJECT (text->hadj), "destroy",
			  (GtkSignalFunc) gtk_text_adjustment_destroyed,
Elliot Lee's avatar
Elliot Lee committed
885
			  text);
886
      gtk_text_adjustment (hadj, text);
887 888

      g_object_notify (G_OBJECT (text), "hadjustment");
Elliot Lee's avatar
Elliot Lee committed
889
    }
890
  
Elliot Lee's avatar
Elliot Lee committed
891 892 893 894
  if (text->vadj != vadj)
    {
      text->vadj = vadj;
      gtk_object_ref (GTK_OBJECT (text->vadj));
895 896
      gtk_object_sink (GTK_OBJECT (text->vadj));
      
Elliot Lee's avatar
Elliot Lee committed
897 898 899 900 901 902
      gtk_signal_connect (GTK_OBJECT (text->vadj), "changed",
			  (GtkSignalFunc) gtk_text_adjustment,
			  text);
      gtk_signal_connect (GTK_OBJECT (text->vadj), "value_changed",
			  (GtkSignalFunc) gtk_text_adjustment,
			  text);
Havoc Pennington's avatar
Havoc Pennington committed
903 904
      gtk_signal_connect (GTK_OBJECT (text->vadj), "destroy",
			  (GtkSignalFunc) gtk_text_adjustment_destroyed,
Elliot Lee's avatar
Elliot Lee committed
905
			  text);
906
      gtk_text_adjustment (vadj, text);
907 908

      g_object_notify (G_OBJECT (text), "vadjustment");
Elliot Lee's avatar
Elliot Lee committed
909
    }
910
  g_object_thaw_notify (G_OBJECT (text));
Elliot Lee's avatar
Elliot Lee committed
911 912 913 914 915 916 917
}

void
gtk_text_set_point (GtkText *text,
		    guint    index)
{
  g_return_if_fail (GTK_IS_TEXT (text));
918
  g_return_if_fail (index <= TEXT_LENGTH (text));
919
  
Elliot Lee's avatar
Elliot Lee committed
920 921 922 923 924 925 926
  text->point = find_mark (text, index);
}

guint
gtk_text_get_point (GtkText *text)
{
  g_return_val_if_fail (GTK_IS_TEXT (text), 0);
927
  
Elliot Lee's avatar
Elliot Lee committed
928 929 930 931 932 933 934
  return text->point.index;
}

guint
gtk_text_get_length (GtkText *text)
{
  g_return_val_if_fail (GTK_IS_TEXT (text), 0);
935
  
Elliot Lee's avatar
Elliot Lee committed
936 937 938 939 940 941 942
  return TEXT_LENGTH (text);
}

void
gtk_text_freeze (GtkText *text)
{
  g_return_if_fail (GTK_IS_TEXT (text));
943
  
944
  text->freeze_count++;
Elliot Lee's avatar
Elliot Lee committed
945 946 947 948 949 950
}

void
gtk_text_thaw (GtkText *text)
{
  g_return_if_fail (GTK_IS_TEXT (text));
951
  
952 953 954 955 956 957
  if (text->freeze_count)
    if (!(--text->freeze_count) && GTK_WIDGET_REALIZED (text))
      {
	recompute_geometry (text);
	gtk_widget_queue_draw (GTK_WIDGET (text));
      }
Elliot Lee's avatar
Elliot Lee committed
958 959 960 961 962 963 964 965
}

void
gtk_text_insert (GtkText    *text,
		 GdkFont    *font,
		 GdkColor   *fore,
		 GdkColor   *back,
		 const char *chars,
Owen Taylor's avatar
Owen Taylor committed
966
		 gint        nchars)
Elliot Lee's avatar
Elliot Lee committed
967
{
Owen Taylor's avatar
Owen Taylor committed
968
  GtkOldEditable *old_editable = GTK_OLD_EDITABLE (text);
Owen Taylor's avatar
Owen Taylor committed
969
  gboolean frozen = FALSE;
970
  
Owen Taylor's avatar
Owen Taylor committed
971 972
  gint new_line_count = 1;
  guint old_height = 0;
Owen Taylor's avatar
Owen Taylor committed
973
  guint length;
974
  guint i;
975
  gint numwcs;
976
  
Elliot Lee's avatar
Elliot Lee committed
977
  g_return_if_fail (GTK_IS_TEXT (text));
978

Owen Taylor's avatar
Owen Taylor committed
979
  if (nchars < 0)
Elliot Lee's avatar
Elliot Lee committed
980
    length = strlen (chars);
Owen Taylor's avatar
Owen Taylor committed
981 982
  else
    length = nchars;
983
  
Elliot Lee's avatar
Elliot Lee committed
984 985
  if (length == 0)
    return;
986
  
987
  if (!text->freeze_count && (length > FREEZE_LENGTH))
Owen Taylor's avatar
Owen Taylor committed
988 989 990 991 992
    {
      gtk_text_freeze (text);
      frozen = TRUE;
    }
  
993
  if (!text->freeze_count && (text->line_start_cache != NULL))
Owen Taylor's avatar
Owen Taylor committed
994
    {
995
      find_line_containing_point (text, text->point.index, TRUE);
Owen Taylor's avatar
Owen Taylor committed
996 997
      old_height = total_line_height (text, text->current_line, 1);
    }
998
  
999 1000
  if ((TEXT_LENGTH (text) == 0) && (text->use_wchar == FALSE))
    {
1001 1002
      GtkWidget *widget = GTK_WIDGET (text);
      
1003
      gtk_widget_ensure_style (widget);
1004
      if ((widget->style) &&
1005
	  (gtk_style_get_font (widget->style)->type == GDK_FONT_FONTSET))
1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018
 	{
 	  text->use_wchar = TRUE;
 	  g_free (text->text.ch);
 	  text->text.wc = g_new (GdkWChar, INITIAL_BUFFER_SIZE);
 	  text->text_len = INITIAL_BUFFER_SIZE;
 	  if (text->scratch_buffer.ch)
 	    g_free (text->scratch_buffer.ch);
 	  text->scratch_buffer.wc = NULL;
 	  text->scratch_buffer_len = 0;
 	}
    }
 
  move_gap (text, text->point.index);
Elliot Lee's avatar
Elliot Lee committed
1019
  make_forward_space (text, length);
1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067
 
  if (text->use_wchar)
    {
      char *chars_nt = (char *)chars;
      if (nchars > 0)
	{
	  chars_nt = g_new (char, length+1);
	  memcpy (chars_nt, chars, length);
	  chars_nt[length] = 0;
	}
      numwcs = gdk_mbstowcs (text->text.wc + text->gap_position, chars_nt,
 			     length);
      if (chars_nt != chars)
	g_free(chars_nt);
      if (numwcs < 0)
	numwcs = 0;
    }
  else
    {
      numwcs = length;
      memcpy(text->text.ch + text->gap_position, chars, length);
    }
 
  if (!text->freeze_count && (text->line_start_cache != NULL))
    {
      if (text->use_wchar)
 	{
 	  for (i=0; i<numwcs; i++)
 	    if (text->text.wc[text->gap_position + i] == '\n')
 	      new_line_count++;
	}
      else
 	{
 	  for (i=0; i<numwcs; i++)
 	    if (text->text.ch[text->gap_position + i] == '\n')
 	      new_line_count++;
 	}
    }
 
  if (numwcs > 0)
    {
      insert_text_property (text, font, fore, back, numwcs);
   
      text->gap_size -= numwcs;
      text->gap_position += numwcs;
   
      if (text->point.index < text->first_line_start_index)
 	text->first_line_start_index += numwcs;
Owen Taylor's avatar
Owen Taylor committed
1068 1069 1070 1071
      if (text->point.index < old_editable->selection_start_pos)
 	old_editable->selection_start_pos += numwcs;
      if (text->point.index < old_editable->selection_end_pos)
 	old_editable->selection_end_pos += numwcs;
1072 1073 1074 1075 1076 1077 1078 1079 1080 1081
      /* We'll reset the cursor later anyways if we aren't frozen */
      if (text->point.index < text->cursor_mark.index)
 	text->cursor_mark.index += numwcs;
  
      advance_mark_n (&text->point, numwcs);
  
      if (!text->freeze_count && (text->line_start_cache != NULL))
	insert_expose (text, old_height, numwcs, new_line_count);
    }

Owen Taylor's avatar
Owen Taylor committed
1082 1083
  if (frozen)
    gtk_text_thaw (text);
Elliot Lee's avatar
Elliot Lee committed
1084 1085
}

1086
gboolean
Elliot Lee's avatar
Elliot Lee committed
1087 1088 1089
gtk_text_backward_delete (GtkText *text,
			  guint    nchars)
{
1090
  g_return_val_if_fail (GTK_IS_TEXT (text), FALSE);
1091
  
Elliot Lee's avatar
Elliot Lee committed
1092 1093
  if (nchars > text->point.index || nchars <= 0)
    return FALSE;
1094
  
Elliot Lee's avatar
Elliot Lee committed
1095
  gtk_text_set_point (text, text->point.index - nchars);
1096
  
1097
  return gtk_text_forward_delete (text, nchars);
Elliot Lee's avatar
Elliot Lee committed
1098 1099
}

1100
gboolean
1101
gtk_text_forward_delete (GtkText *text,
1102
			 guint    nchars)
Elliot Lee's avatar
Elliot Lee committed
1103
{
Owen Taylor's avatar
Owen Taylor committed
1104
  guint old_lines, old_height;
Owen Taylor's avatar
Owen Taylor committed
1105
  GtkOldEditable *old_editable = GTK_OLD_EDITABLE (text);
Owen Taylor's avatar
Owen Taylor committed
1106
  gboolean frozen = FALSE;
1107
  
1108
  g_return_val_if_fail (GTK_IS_TEXT (text), FALSE);
1109
  
Elliot Lee's avatar
Elliot Lee committed
1110 1111
  if (text->point.index + nchars > TEXT_LENGTH (text) || nchars <= 0)
    return FALSE;
1112
  
1113
  if (!text->freeze_count && nchars > FREEZE_LENGTH)
Owen Taylor's avatar
Owen Taylor committed
1114 1115 1116 1117 1118
    {
      gtk_text_freeze (text);
      frozen = TRUE;
    }
  
1119
  if (!text->freeze_count && text->line_start_cache != NULL)
Owen Taylor's avatar
Owen Taylor committed
1120
    {
1121 1122 1123 1124
      /* We need to undraw the cursor here, since we may later
       * delete the cursor's property
       */
      undraw_cursor (text, FALSE);
1125
      find_line_containing_point (text, text->point.index, TRUE);
Owen Taylor's avatar
Owen Taylor committed
1126 1127
      compute_lines_pixels (text, nchars, &old_lines, &old_height);
    }
1128
  
1129
  /* FIXME, or resizing after deleting will be odd */
Owen Taylor's avatar
Owen Taylor committed
1130
  if (text->point.index < text->first_line_start_index)
1131
    {
1132
      if (text->point.index + nchars >= text->first_line_start_index)
1133 1134 1135
	{
	  text->first_line_start_index = text->point.index;
	  while ((text->first_line_start_index > 0) &&
1136 1137
		 (GTK_TEXT_INDEX (text, text->first_line_start_index - 1)
		  != LINE_DELIM))
1138 1139 1140 1141 1142 1143
	    text->first_line_start_index -= 1;
	  
	}
      else
	text->first_line_start_index -= nchars;
    }
1144
  
Owen Taylor's avatar
Owen Taylor committed
1145 1146 1147 1148 1149 1150
  if (text->point.index < old_editable->selection_start_pos)
    old_editable->selection_start_pos -= 
      MIN(nchars, old_editable->selection_start_pos - text->point.index);
  if (text->point.index < old_editable->selection_end_pos)
    old_editable->selection_end_pos -= 
      MIN(nchars, old_editable->selection_end_pos - text->point.index);
Owen Taylor's avatar
Owen Taylor committed
1151 1152
  /* We'll reset the cursor later anyways if we aren't frozen */
  if (text->point.index < text->cursor_mark.index)
1153 1154
    move_mark_n (&text->cursor_mark, 
		 -MIN(nchars, text->cursor_mark.index - text->point.index));
1155
  
1156
  move_gap (text, text->point.index);
1157
  
Elliot Lee's avatar
Elliot Lee committed
1158
  text->gap_size += nchars;
1159
  
Elliot Lee's avatar
Elliot Lee committed
1160
  delete_text_property (text, nchars);
1161
  
1162
  if (!text->freeze_count && (text->line_start_cache != NULL))
1163 1164 1165 1166
    {
      delete_expose (text, nchars, old_lines, old_height);
      draw_cursor (text, FALSE);
    }
1167
  
Owen Taylor's avatar
Owen Taylor committed
1168 1169
  if (frozen)
    gtk_text_thaw (text);
1170
  
Elliot Lee's avatar
Elliot Lee committed
1171 1172
  return TRUE;
}
1173

Owen Taylor's avatar
Owen Taylor committed
1174
static void
Owen Taylor's avatar
Owen Taylor committed
1175 1176
gtk_text_set_position (GtkOldEditable *old_editable,
		       gint            position)
Owen Taylor's avatar
Owen Taylor committed
1177
{
Owen Taylor's avatar
Owen Taylor committed
1178
  GtkText *text = (GtkText *) old_editable;
1179 1180 1181

  if (position < 0)
    position = gtk_text_get_length (text);                                    
1182
  
1183 1184 1185 1186
  undraw_cursor (text, FALSE);
  text->cursor_mark = find_mark (text, position);
  find_cursor (text, TRUE);
  draw_cursor (text, FALSE);
Owen Taylor's avatar
Owen Taylor committed
1187
  gtk_editable_select_region (GTK_EDITABLE (old_editable), 0, 0);
Owen Taylor's avatar
Owen Taylor committed
1188
}
Elliot Lee's avatar
Elliot Lee committed
1189

1190
static gchar *    
Owen Taylor's avatar
Owen Taylor committed
1191 1192 1193
gtk_text_get_chars (GtkOldEditable *old_editable,
		    gint            start_pos,
		    gint            end_pos)
Owen Taylor's avatar
Owen Taylor committed
1194
{
1195
  GtkText *text;
1196

Owen Taylor's avatar
Owen Taylor committed
1197
  gchar *retval;
1198
  
Owen Taylor's avatar
Owen Taylor committed
1199 1200
  g_return_val_if_fail (GTK_IS_TEXT (old_editable), NULL);
  text = GTK_TEXT (old_editable);
Owen Taylor's avatar
Owen Taylor committed
1201
  
1202 1203 1204
  if (end_pos < 0)
    end_pos = TEXT_LENGTH (text);
  
1205 1206 1207
  if ((start_pos < 0) || 
      (end_pos > TEXT_LENGTH (text)) || 
      (end_pos < start_pos))
Owen Taylor's avatar
Owen Taylor committed
1208
    return NULL;
1209
  
1210 1211 1212 1213
  move_gap (text, TEXT_LENGTH (text));
  make_forward_space (text, 1);

  if (text->use_wchar)
Owen Taylor's avatar
Owen Taylor committed
1214
    {
1215 1216 1217 1218 1219
      GdkWChar ch;
      ch = text->text.wc[end_pos];
      text->text.wc[end_pos] = 0;
      retval = gdk_wcstombs (text->text.wc + start_pos);
      text->text.wc[end_pos] = ch;
Owen Taylor's avatar
Owen Taylor committed
1220
    }
1221
  else
Owen Taylor's avatar
Owen Taylor committed
1222
    {
1223 1224 1225 1226 1227
      guchar ch;
      ch = text->text.ch[end_pos];
      text->text.ch[end_pos] = 0;
      retval = g_strdup (text->text.ch + start_pos);
      text->text.ch[end_pos] = ch;
Owen Taylor's avatar
Owen Taylor committed
1228
    }
1229

Owen Taylor's avatar
Owen Taylor committed
1230 1231 1232 1233
  return retval;
}


Elliot Lee's avatar
Elliot Lee committed
1234
static void
1235
gtk_text_destroy (GtkObject *object)
Elliot Lee's avatar
Elliot Lee committed
1236
{
1237
  GtkText *text;
1238
  
Elliot Lee's avatar
Elliot Lee committed
1239
  g_return_if_fail (GTK_IS_TEXT (object));
1240
  
1241
  text = GTK_TEXT (object);
1242

1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254
  if (text->hadj)
    {
      gtk_signal_disconnect_by_data (GTK_OBJECT (text->hadj), text);
      gtk_object_unref (GTK_OBJECT (text->hadj));
      text->hadj = NULL;
    }
  if (text->vadj)
    {
      gtk_signal_disconnect_by_data (GTK_OBJECT (text->vadj), text);
      gtk_object_unref (GTK_OBJECT (text->vadj));
      text->vadj = NULL;
    }
1255

1256 1257
  if (text->timer)
    {
1258
      g_source_remove (text->timer);
1259
      text->timer = 0;
1260
    }
1261
  
1262
  GTK_OBJECT_CLASS(parent_class)->destroy (object);
Elliot Lee's avatar
Elliot Lee committed
1263 1264
}

1265
static void
1266
gtk_text_finalize (GObject *object)