gtkentry.c 149 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/. 
 */

27
#include <config.h>
Elliot Lee's avatar
Elliot Lee committed
28
#include <string.h>
Owen Taylor's avatar
Owen Taylor committed
29 30 31

#include <pango/pango.h>

Elliot Lee's avatar
Elliot Lee committed
32
#include "gdk/gdkkeysyms.h"
33
#include "gtkalias.h"
Owen Taylor's avatar
Owen Taylor committed
34
#include "gtkbindings.h"
35
#include "gtkcelleditable.h"
Owen Taylor's avatar
Owen Taylor committed
36
#include "gtkclipboard.h"
Owen Taylor's avatar
Owen Taylor committed
37
#include "gtkdnd.h"
Elliot Lee's avatar
Elliot Lee committed
38
#include "gtkentry.h"
39
#include "gtkimagemenuitem.h"
40
#include "gtkimmulticontext.h"
Owen Taylor's avatar
Owen Taylor committed
41
#include "gtkintl.h"
Elliot Lee's avatar
Elliot Lee committed
42
#include "gtkmain.h"
43
#include "gtkmarshalers.h"
Owen Taylor's avatar
Owen Taylor committed
44 45
#include "gtkmenu.h"
#include "gtkmenuitem.h"
46
#include "gtkseparatormenuitem.h"
Elliot Lee's avatar
Elliot Lee committed
47
#include "gtkselection.h"
48
#include "gtksettings.h"
49
#include "gtkstock.h"
50
#include "gtktextutil.h"
51
#include "gtkwindow.h"
52 53 54 55 56 57
#include "gtktreeview.h"
#include "gtktreeselection.h"
#include "gtkentryprivate.h"
#include "gtkcelllayout.h"

#define GTK_ENTRY_COMPLETION_KEY "gtk-entry-completion-key"
58

Elliot Lee's avatar
Elliot Lee committed
59 60 61
#define MIN_ENTRY_WIDTH  150
#define DRAW_TIMEOUT     20
#define INNER_BORDER     2
62
#define COMPLETION_TIMEOUT 300
Elliot Lee's avatar
Elliot Lee committed
63

64 65 66 67 68 69
/* Initial size of buffer, in bytes */
#define MIN_SIZE 16

/* Maximum size of text buffer, in bytes */
#define MAX_SIZE G_MAXUSHORT

70 71 72 73 74 75 76
typedef struct _GtkEntryPrivate GtkEntryPrivate;

#define GTK_ENTRY_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_ENTRY, GtkEntryPrivate))

struct _GtkEntryPrivate 
{
  gfloat xalign;
77
  gint insert_pos;
78 79
};

Owen Taylor's avatar
Owen Taylor committed
80 81
enum {
  ACTIVATE,
82
  POPULATE_POPUP,
Owen Taylor's avatar
Owen Taylor committed
83 84 85
  MOVE_CURSOR,
  INSERT_AT_CURSOR,
  DELETE_FROM_CURSOR,
86
  BACKSPACE,
Owen Taylor's avatar
Owen Taylor committed
87 88 89 90 91 92 93
  CUT_CLIPBOARD,
  COPY_CLIPBOARD,
  PASTE_CLIPBOARD,
  TOGGLE_OVERWRITE,
  LAST_SIGNAL
};

94
enum {
Havoc Pennington's avatar
Havoc Pennington committed
95
  PROP_0,
96 97
  PROP_CURSOR_POSITION,
  PROP_SELECTION_BOUND,
Havoc Pennington's avatar
Havoc Pennington committed
98 99 100
  PROP_EDITABLE,
  PROP_MAX_LENGTH,
  PROP_VISIBILITY,
101
  PROP_HAS_FRAME,
102
  PROP_INVISIBLE_CHAR,
103
  PROP_ACTIVATES_DEFAULT,
104
  PROP_WIDTH_CHARS,
105
  PROP_SCROLL_OFFSET,
106 107
  PROP_TEXT,
  PROP_XALIGN
108 109
};

Owen Taylor's avatar
Owen Taylor committed
110
static guint signals[LAST_SIGNAL] = { 0 };
111

Owen Taylor's avatar
Owen Taylor committed
112 113 114 115 116
typedef enum {
  CURSOR_STANDARD,
  CURSOR_DND
} CursorType;

Owen Taylor's avatar
Owen Taylor committed
117 118
/* GObject, GtkObject methods
 */
119 120 121
static void   gtk_entry_class_init           (GtkEntryClass        *klass);
static void   gtk_entry_editable_init        (GtkEditableClass     *iface);
static void   gtk_entry_cell_editable_init   (GtkCellEditableIface *iface);
122
static void   gtk_entry_init                 (GtkEntry         *entry);
Havoc Pennington's avatar
Havoc Pennington committed
123 124 125
static void   gtk_entry_set_property (GObject         *object,
				      guint            prop_id,
				      const GValue    *value,
126
				      GParamSpec      *pspec);
Havoc Pennington's avatar
Havoc Pennington committed
127 128 129
static void   gtk_entry_get_property (GObject         *object,
				      guint            prop_id,
				      GValue          *value,
130
				      GParamSpec      *pspec);
131
static void   gtk_entry_finalize             (GObject          *object);
132
static void   gtk_entry_destroy              (GtkObject        *object);
Owen Taylor's avatar
Owen Taylor committed
133 134 135

/* GtkWidget methods
 */
136 137 138 139 140 141
static void   gtk_entry_realize              (GtkWidget        *widget);
static void   gtk_entry_unrealize            (GtkWidget        *widget);
static void   gtk_entry_size_request         (GtkWidget        *widget,
					      GtkRequisition   *requisition);
static void   gtk_entry_size_allocate        (GtkWidget        *widget,
					      GtkAllocation    *allocation);
142
static void   gtk_entry_draw_frame           (GtkWidget        *widget);
143 144 145 146 147 148 149 150 151 152
static gint   gtk_entry_expose               (GtkWidget        *widget,
					      GdkEventExpose   *event);
static gint   gtk_entry_button_press         (GtkWidget        *widget,
					      GdkEventButton   *event);
static gint   gtk_entry_button_release       (GtkWidget        *widget,
					      GdkEventButton   *event);
static gint   gtk_entry_motion_notify        (GtkWidget        *widget,
					      GdkEventMotion   *event);
static gint   gtk_entry_key_press            (GtkWidget        *widget,
					      GdkEventKey      *event);
153 154
static gint   gtk_entry_key_release          (GtkWidget        *widget,
					      GdkEventKey      *event);
155 156 157 158
static gint   gtk_entry_focus_in             (GtkWidget        *widget,
					      GdkEventFocus    *event);
static gint   gtk_entry_focus_out            (GtkWidget        *widget,
					      GdkEventFocus    *event);
159
static void   gtk_entry_grab_focus           (GtkWidget        *widget);
160 161 162 163 164 165
static void   gtk_entry_style_set            (GtkWidget        *widget,
					      GtkStyle         *previous_style);
static void   gtk_entry_direction_changed    (GtkWidget        *widget,
					      GtkTextDirection  previous_dir);
static void   gtk_entry_state_changed        (GtkWidget        *widget,
					      GtkStateType      previous_state);
166 167
static void   gtk_entry_screen_changed       (GtkWidget        *widget,
					      GdkScreen        *old_screen);
Owen Taylor's avatar
Owen Taylor committed
168

169 170 171 172 173
static gboolean gtk_entry_drag_drop          (GtkWidget        *widget,
                                              GdkDragContext   *context,
                                              gint              x,
                                              gint              y,
                                              guint             time);
Owen Taylor's avatar
Owen Taylor committed
174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
static gboolean gtk_entry_drag_motion        (GtkWidget        *widget,
					      GdkDragContext   *context,
					      gint              x,
					      gint              y,
					      guint             time);
static void     gtk_entry_drag_leave         (GtkWidget        *widget,
					      GdkDragContext   *context,
					      guint             time);
static void     gtk_entry_drag_data_received (GtkWidget        *widget,
					      GdkDragContext   *context,
					      gint              x,
					      gint              y,
					      GtkSelectionData *selection_data,
					      guint             info,
					      guint             time);
static void     gtk_entry_drag_data_get      (GtkWidget        *widget,
					      GdkDragContext   *context,
					      GtkSelectionData *selection_data,
					      guint             info,
					      guint             time);
static void     gtk_entry_drag_data_delete   (GtkWidget        *widget,
					      GdkDragContext   *context);

Owen Taylor's avatar
Owen Taylor committed
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
/* GtkEditable method implementations
 */
static void     gtk_entry_insert_text          (GtkEditable *editable,
						const gchar *new_text,
						gint         new_text_length,
						gint        *position);
static void     gtk_entry_delete_text          (GtkEditable *editable,
						gint         start_pos,
						gint         end_pos);
static gchar *  gtk_entry_get_chars            (GtkEditable *editable,
						gint         start_pos,
						gint         end_pos);
static void     gtk_entry_real_set_position    (GtkEditable *editable,
						gint         position);
static gint     gtk_entry_get_position         (GtkEditable *editable);
static void     gtk_entry_set_selection_bounds (GtkEditable *editable,
						gint         start,
						gint         end);
static gboolean gtk_entry_get_selection_bounds (GtkEditable *editable,
						gint        *start,
						gint        *end);

219 220 221 222 223
/* GtkCellEditable method implementations
 */
static void gtk_entry_start_editing (GtkCellEditable *cell_editable,
				     GdkEvent        *event);

Owen Taylor's avatar
Owen Taylor committed
224 225
/* Default signal handlers
 */
226
static void gtk_entry_real_insert_text   (GtkEditable     *editable,
227 228 229
					  const gchar     *new_text,
					  gint             new_text_length,
					  gint            *position);
230
static void gtk_entry_real_delete_text   (GtkEditable     *editable,
231 232 233 234 235 236 237 238 239 240 241
					  gint             start_pos,
					  gint             end_pos);
static void gtk_entry_move_cursor        (GtkEntry        *entry,
					  GtkMovementStep  step,
					  gint             count,
					  gboolean         extend_selection);
static void gtk_entry_insert_at_cursor   (GtkEntry        *entry,
					  const gchar     *str);
static void gtk_entry_delete_from_cursor (GtkEntry        *entry,
					  GtkDeleteType    type,
					  gint             count);
242
static void gtk_entry_backspace          (GtkEntry        *entry);
243 244 245 246
static void gtk_entry_cut_clipboard      (GtkEntry        *entry);
static void gtk_entry_copy_clipboard     (GtkEntry        *entry);
static void gtk_entry_paste_clipboard    (GtkEntry        *entry);
static void gtk_entry_toggle_overwrite   (GtkEntry        *entry);
247
static void gtk_entry_select_all         (GtkEntry        *entry);
248
static void gtk_entry_real_activate      (GtkEntry        *entry);
249
static gboolean gtk_entry_popup_menu     (GtkWidget      *widget);
Owen Taylor's avatar
Owen Taylor committed
250

251 252
static void gtk_entry_keymap_direction_changed (GdkKeymap *keymap,
						GtkEntry  *entry);
Owen Taylor's avatar
Owen Taylor committed
253 254
/* IM Context Callbacks
 */
255 256 257 258 259 260 261 262 263 264 265 266
static void     gtk_entry_commit_cb               (GtkIMContext *context,
						   const gchar  *str,
						   GtkEntry     *entry);
static void     gtk_entry_preedit_changed_cb      (GtkIMContext *context,
						   GtkEntry     *entry);
static gboolean gtk_entry_retrieve_surrounding_cb (GtkIMContext *context,
						   GtkEntry     *entry);
static gboolean gtk_entry_delete_surrounding_cb   (GtkIMContext *context,
						   gint          offset,
						   gint          n_chars,
						   GtkEntry     *entry);

Owen Taylor's avatar
Owen Taylor committed
267 268
/* Internal routines
 */
269 270
static void         gtk_entry_enter_text               (GtkEntry       *entry,
                                                        const gchar    *str);
271 272 273
static void         gtk_entry_set_positions            (GtkEntry       *entry,
							gint            current_pos,
							gint            selection_bound);
Owen Taylor's avatar
Owen Taylor committed
274
static void         gtk_entry_draw_text                (GtkEntry       *entry);
Owen Taylor's avatar
Owen Taylor committed
275 276
static void         gtk_entry_draw_cursor              (GtkEntry       *entry,
							CursorType      type);
277 278
static PangoLayout *gtk_entry_ensure_layout            (GtkEntry       *entry,
                                                        gboolean        include_preedit);
279
static void         gtk_entry_reset_layout             (GtkEntry       *entry);
Owen Taylor's avatar
Owen Taylor committed
280 281 282 283 284 285
static void         gtk_entry_queue_draw               (GtkEntry       *entry);
static void         gtk_entry_reset_im_context         (GtkEntry       *entry);
static void         gtk_entry_recompute                (GtkEntry       *entry);
static gint         gtk_entry_find_position            (GtkEntry       *entry,
							gint            x);
static void         gtk_entry_get_cursor_locations     (GtkEntry       *entry,
Owen Taylor's avatar
Owen Taylor committed
286
							CursorType      type,
Owen Taylor's avatar
Owen Taylor committed
287 288 289 290 291 292
							gint           *strong_x,
							gint           *weak_x);
static void         gtk_entry_adjust_scroll            (GtkEntry       *entry);
static gint         gtk_entry_move_visually            (GtkEntry       *editable,
							gint            start,
							gint            count);
293 294 295
static gint         gtk_entry_move_logically           (GtkEntry       *entry,
							gint            start,
							gint            count);
Owen Taylor's avatar
Owen Taylor committed
296 297 298 299 300 301 302 303 304 305 306 307 308
static gint         gtk_entry_move_forward_word        (GtkEntry       *entry,
							gint            start);
static gint         gtk_entry_move_backward_word       (GtkEntry       *entry,
							gint            start);
static void         gtk_entry_delete_whitespace        (GtkEntry       *entry);
static void         gtk_entry_select_word              (GtkEntry       *entry);
static void         gtk_entry_select_line              (GtkEntry       *entry);
static char *       gtk_entry_get_public_chars         (GtkEntry       *entry,
							gint            start,
							gint            end);
static void         gtk_entry_paste                    (GtkEntry       *entry,
							GdkAtom         selection);
static void         gtk_entry_update_primary_selection (GtkEntry       *entry);
309
static void         gtk_entry_do_popup                 (GtkEntry       *entry,
Owen Taylor's avatar
Owen Taylor committed
310
							GdkEventButton *event);
311 312
static gboolean     gtk_entry_mnemonic_activate        (GtkWidget      *widget,
							gboolean        group_cycling);
313 314
static void         gtk_entry_state_changed            (GtkWidget      *widget,
							GtkStateType    previous_state);
315 316
static void         gtk_entry_check_cursor_blink       (GtkEntry       *entry);
static void         gtk_entry_pend_cursor_blink        (GtkEntry       *entry);
317 318 319 320 321 322 323 324 325 326
static void         get_text_area_size                 (GtkEntry       *entry,
							gint           *x,
							gint           *y,
							gint           *width,
							gint           *height);
static void         get_widget_window_size             (GtkEntry       *entry,
							gint           *x,
							gint           *y,
							gint           *width,
							gint           *height);
327

328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352
/* Completion */
static gint         gtk_entry_completion_timeout       (gpointer            data);
static gboolean     gtk_entry_completion_key_press     (GtkWidget          *widget,
							GdkEventKey        *event,
							gpointer            user_data);
static void         gtk_entry_completion_changed       (GtkWidget          *entry,
							gpointer            user_data);
static gboolean     check_completion_callback          (GtkEntryCompletion *completion);
static void         clear_completion_callback          (GtkEntry           *entry,
							GParamSpec         *pspec);
static gboolean     accept_completion_callback         (GtkEntry           *entry);
static void         completion_insert_text_callback    (GtkEntry           *entry,
							const gchar        *text,
							gint                length,
							gint                position,
							GtkEntryCompletion *completion);
static void         completion_changed                 (GtkEntryCompletion *completion,
							GParamSpec         *pspec,
							gpointer            data);
static void         disconnect_completion_signals      (GtkEntry           *entry,
							GtkEntryCompletion *completion);
static void         connect_completion_signals         (GtkEntry           *entry,
							GtkEntryCompletion *completion);


Elliot Lee's avatar
Elliot Lee committed
353 354
static GtkWidgetClass *parent_class = NULL;

Manish Singh's avatar
Manish Singh committed
355
GType
356
gtk_entry_get_type (void)
Elliot Lee's avatar
Elliot Lee committed
357
{
Manish Singh's avatar
Manish Singh committed
358
  static GType entry_type = 0;
Elliot Lee's avatar
Elliot Lee committed
359 360 361

  if (!entry_type)
    {
Manish Singh's avatar
Manish Singh committed
362
      static const GTypeInfo entry_info =
Elliot Lee's avatar
Elliot Lee committed
363 364
      {
	sizeof (GtkEntryClass),
Manish Singh's avatar
Manish Singh committed
365 366 367 368 369 370 371 372
	NULL,		/* base_init */
	NULL,		/* base_finalize */
	(GClassInitFunc) gtk_entry_class_init,
	NULL,		/* class_finalize */
	NULL,		/* class_data */
	sizeof (GtkEntry),
	0,		/* n_preallocs */
	(GInstanceInitFunc) gtk_entry_init,
Elliot Lee's avatar
Elliot Lee committed
373
      };
Owen Taylor's avatar
Owen Taylor committed
374 375 376 377 378 379 380
      
      static const GInterfaceInfo editable_info =
      {
	(GInterfaceInitFunc) gtk_entry_editable_init,	 /* interface_init */
	NULL,			                         /* interface_finalize */
	NULL			                         /* interface_data */
      };
Elliot Lee's avatar
Elliot Lee committed
381

382 383 384 385 386 387 388
      static const GInterfaceInfo cell_editable_info =
      {
	(GInterfaceInitFunc) gtk_entry_cell_editable_init,    /* interface_init */
	NULL,                                                 /* interface_finalize */
	NULL                                                  /* interface_data */
      };
      
Manish Singh's avatar
Manish Singh committed
389 390 391
      entry_type = g_type_register_static (GTK_TYPE_WIDGET, "GtkEntry",
					   &entry_info, 0);

Owen Taylor's avatar
Owen Taylor committed
392 393 394
      g_type_add_interface_static (entry_type,
				   GTK_TYPE_EDITABLE,
				   &editable_info);
395 396 397
      g_type_add_interface_static (entry_type,
				   GTK_TYPE_CELL_EDITABLE,
				   &cell_editable_info);
Elliot Lee's avatar
Elliot Lee committed
398 399 400 401 402
    }

  return entry_type;
}

Owen Taylor's avatar
Owen Taylor committed
403 404 405 406 407 408 409 410 411 412 413
static void
add_move_binding (GtkBindingSet  *binding_set,
		  guint           keyval,
		  guint           modmask,
		  GtkMovementStep step,
		  gint            count)
{
  g_return_if_fail ((modmask & GDK_SHIFT_MASK) == 0);
  
  gtk_binding_entry_add_signal (binding_set, keyval, modmask,
				"move_cursor", 3,
Manish Singh's avatar
Manish Singh committed
414
				G_TYPE_ENUM, step,
Owen Taylor's avatar
Owen Taylor committed
415
				G_TYPE_INT, count,
Manish Singh's avatar
Manish Singh committed
416
				G_TYPE_BOOLEAN, FALSE);
Owen Taylor's avatar
Owen Taylor committed
417 418 419 420

  /* Selection-extending version */
  gtk_binding_entry_add_signal (binding_set, keyval, modmask | GDK_SHIFT_MASK,
				"move_cursor", 3,
Manish Singh's avatar
Manish Singh committed
421
				G_TYPE_ENUM, step,
Owen Taylor's avatar
Owen Taylor committed
422
				G_TYPE_INT, count,
Manish Singh's avatar
Manish Singh committed
423
				G_TYPE_BOOLEAN, TRUE);
Owen Taylor's avatar
Owen Taylor committed
424 425
}

Elliot Lee's avatar
Elliot Lee committed
426 427 428
static void
gtk_entry_class_init (GtkEntryClass *class)
{
429
  GObjectClass *gobject_class = G_OBJECT_CLASS (class);
Elliot Lee's avatar
Elliot Lee committed
430
  GtkWidgetClass *widget_class;
431
  GtkObjectClass *gtk_object_class;
Owen Taylor's avatar
Owen Taylor committed
432
  GtkBindingSet *binding_set;
Elliot Lee's avatar
Elliot Lee committed
433 434

  widget_class = (GtkWidgetClass*) class;
435
  gtk_object_class = (GtkObjectClass *)class;
Manish Singh's avatar
Manish Singh committed
436
  parent_class = g_type_class_peek_parent (class);
Elliot Lee's avatar
Elliot Lee committed
437

438
  gobject_class->finalize = gtk_entry_finalize;
Havoc Pennington's avatar
Havoc Pennington committed
439 440
  gobject_class->set_property = gtk_entry_set_property;
  gobject_class->get_property = gtk_entry_get_property;
441 442 443 444 445 446 447 448 449 450

  widget_class->realize = gtk_entry_realize;
  widget_class->unrealize = gtk_entry_unrealize;
  widget_class->size_request = gtk_entry_size_request;
  widget_class->size_allocate = gtk_entry_size_allocate;
  widget_class->expose_event = gtk_entry_expose;
  widget_class->button_press_event = gtk_entry_button_press;
  widget_class->button_release_event = gtk_entry_button_release;
  widget_class->motion_notify_event = gtk_entry_motion_notify;
  widget_class->key_press_event = gtk_entry_key_press;
451
  widget_class->key_release_event = gtk_entry_key_release;
452 453
  widget_class->focus_in_event = gtk_entry_focus_in;
  widget_class->focus_out_event = gtk_entry_focus_out;
454
  widget_class->grab_focus = gtk_entry_grab_focus;
455 456 457
  widget_class->style_set = gtk_entry_style_set;
  widget_class->direction_changed = gtk_entry_direction_changed;
  widget_class->state_changed = gtk_entry_state_changed;
458
  widget_class->screen_changed = gtk_entry_screen_changed;
459
  widget_class->mnemonic_activate = gtk_entry_mnemonic_activate;
460

461
  widget_class->drag_drop = gtk_entry_drag_drop;
Owen Taylor's avatar
Owen Taylor committed
462 463 464 465 466 467
  widget_class->drag_motion = gtk_entry_drag_motion;
  widget_class->drag_leave = gtk_entry_drag_leave;
  widget_class->drag_data_received = gtk_entry_drag_data_received;
  widget_class->drag_data_get = gtk_entry_drag_data_get;
  widget_class->drag_data_delete = gtk_entry_drag_data_delete;

468
  widget_class->popup_menu = gtk_entry_popup_menu;
469

470 471
  gtk_object_class->destroy = gtk_entry_destroy;

472 473 474
  class->move_cursor = gtk_entry_move_cursor;
  class->insert_at_cursor = gtk_entry_insert_at_cursor;
  class->delete_from_cursor = gtk_entry_delete_from_cursor;
475
  class->backspace = gtk_entry_backspace;
476 477 478 479
  class->cut_clipboard = gtk_entry_cut_clipboard;
  class->copy_clipboard = gtk_entry_copy_clipboard;
  class->paste_clipboard = gtk_entry_paste_clipboard;
  class->toggle_overwrite = gtk_entry_toggle_overwrite;
480 481
  class->activate = gtk_entry_real_activate;
  
Havoc Pennington's avatar
Havoc Pennington committed
482
  g_object_class_install_property (gobject_class,
483 484
                                   PROP_CURSOR_POSITION,
                                   g_param_spec_int ("cursor_position",
485 486
                                                     P_("Cursor Position"),
                                                     P_("The current position of the insertion cursor in chars"),
Havoc Pennington's avatar
Havoc Pennington committed
487
                                                     0,
488
                                                     MAX_SIZE,
Havoc Pennington's avatar
Havoc Pennington committed
489
                                                     0,
490 491 492 493 494
                                                     G_PARAM_READABLE));
  
  g_object_class_install_property (gobject_class,
                                   PROP_SELECTION_BOUND,
                                   g_param_spec_int ("selection_bound",
495 496
                                                     P_("Selection Bound"),
                                                     P_("The position of the opposite end of the selection from the cursor in chars"),
497
                                                     0,
498
                                                     MAX_SIZE,
499 500
                                                     0,
                                                     G_PARAM_READABLE));
Havoc Pennington's avatar
Havoc Pennington committed
501 502 503 504
  
  g_object_class_install_property (gobject_class,
                                   PROP_EDITABLE,
                                   g_param_spec_boolean ("editable",
505 506
							 P_("Editable"),
							 P_("Whether the entry contents can be edited"),
Havoc Pennington's avatar
Havoc Pennington committed
507 508 509 510 511 512
                                                         TRUE,
							 G_PARAM_READABLE | G_PARAM_WRITABLE));
  
  g_object_class_install_property (gobject_class,
                                   PROP_MAX_LENGTH,
                                   g_param_spec_int ("max_length",
513 514
                                                     P_("Maximum length"),
                                                     P_("Maximum number of characters for this entry. Zero if no maximum"),
515 516 517
                                                     0,
                                                     MAX_SIZE,
                                                     0,
Havoc Pennington's avatar
Havoc Pennington committed
518 519 520 521
                                                     G_PARAM_READABLE | G_PARAM_WRITABLE));
  g_object_class_install_property (gobject_class,
                                   PROP_VISIBILITY,
                                   g_param_spec_boolean ("visibility",
522 523
							 P_("Visibility"),
							 P_("FALSE displays the \"invisible char\" instead of the actual text (password mode)"),
Havoc Pennington's avatar
Havoc Pennington committed
524 525
                                                         TRUE,
							 G_PARAM_READABLE | G_PARAM_WRITABLE));
526

Havoc Pennington's avatar
Havoc Pennington committed
527
  g_object_class_install_property (gobject_class,
528 529
                                   PROP_HAS_FRAME,
                                   g_param_spec_boolean ("has_frame",
530 531
							 P_("Has Frame"),
							 P_("FALSE removes outside bevel from entry"),
532 533 534
                                                         TRUE,
							 G_PARAM_READABLE | G_PARAM_WRITABLE));

Morten Welinder's avatar
Morten Welinder committed
535
  g_object_class_install_property (gobject_class,
Havoc Pennington's avatar
Havoc Pennington committed
536
                                   PROP_INVISIBLE_CHAR,
537
                                   g_param_spec_unichar ("invisible_char",
538 539
							 P_("Invisible character"),
							 P_("The character to use when masking entry contents (in \"password mode\")"),
540 541
							 '*',
							 G_PARAM_READABLE | G_PARAM_WRITABLE));
Havoc Pennington's avatar
Havoc Pennington committed
542

543 544 545
  g_object_class_install_property (gobject_class,
                                   PROP_ACTIVATES_DEFAULT,
                                   g_param_spec_boolean ("activates_default",
546 547
							 P_("Activates default"),
							 P_("Whether to activate the default widget (such as the default button in a dialog) when Enter is pressed"),
548 549
                                                         FALSE,
							 G_PARAM_READABLE | G_PARAM_WRITABLE));
550 551 552
  g_object_class_install_property (gobject_class,
                                   PROP_WIDTH_CHARS,
                                   g_param_spec_int ("width_chars",
553 554
                                                     P_("Width in chars"),
                                                     P_("Number of characters to leave space for in the entry"),
555 556 557 558
                                                     -1,
                                                     G_MAXINT,
                                                     -1,
                                                     G_PARAM_READABLE | G_PARAM_WRITABLE));
559

560 561 562
  g_object_class_install_property (gobject_class,
                                   PROP_SCROLL_OFFSET,
                                   g_param_spec_int ("scroll_offset",
563 564
                                                     P_("Scroll offset"),
                                                     P_("Number of pixels of the entry scrolled off the screen to the left"),
565 566 567 568
                                                     0,
                                                     G_MAXINT,
                                                     0,
                                                     G_PARAM_READABLE));
569 570 571 572

  g_object_class_install_property (gobject_class,
                                   PROP_TEXT,
                                   g_param_spec_string ("text",
573 574
							P_("Text"),
							P_("The contents of the entry"),
575 576
							"",
							G_PARAM_READABLE | G_PARAM_WRITABLE));
577

578 579 580 581 582 583 584 585
  /**
   * GtkEntry:xalign:
   *
   * The horizontal alignment, from 0 (left) to 1 (right). 
   * Reversed for RTL layouts.
   * 
   * Since: 2.4
   */
586 587 588 589
  g_object_class_install_property (gobject_class,
                                   PROP_XALIGN,
                                   g_param_spec_float ("xalign",
						       P_("X align"),
590
						       P_("The horizontal alignment, from 0 (left) to 1 (right). Reversed for RTL layouts."),
591 592 593 594
						       0.0,
						       1.0,
						       0.0,
						       G_PARAM_READABLE | G_PARAM_WRITABLE));
595
  
596
  signals[POPULATE_POPUP] =
Manish Singh's avatar
Manish Singh committed
597 598 599 600 601 602 603 604
    g_signal_new ("populate_popup",
		  G_OBJECT_CLASS_TYPE (gobject_class),
		  G_SIGNAL_RUN_LAST,
		  G_STRUCT_OFFSET (GtkEntryClass, populate_popup),
		  NULL, NULL,
		  _gtk_marshal_VOID__OBJECT,
		  G_TYPE_NONE, 1,
		  GTK_TYPE_MENU);
605
  
Owen Taylor's avatar
Owen Taylor committed
606 607 608
 /* Action signals */
  
  signals[ACTIVATE] =
Manish Singh's avatar
Manish Singh committed
609 610 611 612 613 614 615
    g_signal_new ("activate",
		  G_OBJECT_CLASS_TYPE (gobject_class),
		  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
		  G_STRUCT_OFFSET (GtkEntryClass, activate),
		  NULL, NULL,
		  _gtk_marshal_VOID__VOID,
		  G_TYPE_NONE, 0);
Owen Taylor's avatar
Owen Taylor committed
616 617 618
  widget_class->activate_signal = signals[ACTIVATE];

  signals[MOVE_CURSOR] = 
Manish Singh's avatar
Manish Singh committed
619 620 621 622 623 624 625 626 627 628
    g_signal_new ("move_cursor",
		  G_OBJECT_CLASS_TYPE (gobject_class),
		  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
		  G_STRUCT_OFFSET (GtkEntryClass, move_cursor),
		  NULL, NULL,
		  _gtk_marshal_VOID__ENUM_INT_BOOLEAN,
		  G_TYPE_NONE, 3,
		  GTK_TYPE_MOVEMENT_STEP,
		  G_TYPE_INT,
		  G_TYPE_BOOLEAN);
Owen Taylor's avatar
Owen Taylor committed
629 630

  signals[INSERT_AT_CURSOR] = 
Manish Singh's avatar
Manish Singh committed
631 632 633 634 635 636 637 638
    g_signal_new ("insert_at_cursor",
		  G_OBJECT_CLASS_TYPE (gobject_class),
		  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
		  G_STRUCT_OFFSET (GtkEntryClass, insert_at_cursor),
		  NULL, NULL,
		  _gtk_marshal_VOID__STRING,
		  G_TYPE_NONE, 1,
		  G_TYPE_STRING);
Owen Taylor's avatar
Owen Taylor committed
639 640

  signals[DELETE_FROM_CURSOR] = 
Manish Singh's avatar
Manish Singh committed
641 642 643 644 645 646 647 648 649
    g_signal_new ("delete_from_cursor",
		  G_OBJECT_CLASS_TYPE (gobject_class),
		  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
		  G_STRUCT_OFFSET (GtkEntryClass, delete_from_cursor),
		  NULL, NULL,
		  _gtk_marshal_VOID__ENUM_INT,
		  G_TYPE_NONE, 2,
		  GTK_TYPE_DELETE_TYPE,
		  G_TYPE_INT);
Owen Taylor's avatar
Owen Taylor committed
650

651 652 653 654 655 656 657 658 659
  signals[BACKSPACE] =
    g_signal_new ("backspace",
		  G_OBJECT_CLASS_TYPE (gobject_class),
		  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
		  G_STRUCT_OFFSET (GtkEntryClass, backspace),
		  NULL, NULL,
		  _gtk_marshal_VOID__VOID,
		  G_TYPE_NONE, 0);

Owen Taylor's avatar
Owen Taylor committed
660
  signals[CUT_CLIPBOARD] =
Manish Singh's avatar
Manish Singh committed
661 662 663 664 665 666 667
    g_signal_new ("cut_clipboard",
		  G_OBJECT_CLASS_TYPE (gobject_class),
		  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
		  G_STRUCT_OFFSET (GtkEntryClass, cut_clipboard),
		  NULL, NULL,
		  _gtk_marshal_VOID__VOID,
		  G_TYPE_NONE, 0);
Owen Taylor's avatar
Owen Taylor committed
668 669

  signals[COPY_CLIPBOARD] =
Manish Singh's avatar
Manish Singh committed
670 671 672 673 674 675 676
    g_signal_new ("copy_clipboard",
		  G_OBJECT_CLASS_TYPE (gobject_class),
		  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
		  G_STRUCT_OFFSET (GtkEntryClass, copy_clipboard),
		  NULL, NULL,
		  _gtk_marshal_VOID__VOID,
		  G_TYPE_NONE, 0);
Owen Taylor's avatar
Owen Taylor committed
677 678

  signals[PASTE_CLIPBOARD] =
Manish Singh's avatar
Manish Singh committed
679 680 681 682 683 684 685
    g_signal_new ("paste_clipboard",
		  G_OBJECT_CLASS_TYPE (gobject_class),
		  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
		  G_STRUCT_OFFSET (GtkEntryClass, paste_clipboard),
		  NULL, NULL,
		  _gtk_marshal_VOID__VOID,
		  G_TYPE_NONE, 0);
Owen Taylor's avatar
Owen Taylor committed
686 687

  signals[TOGGLE_OVERWRITE] =
Manish Singh's avatar
Manish Singh committed
688 689 690 691 692 693 694
    g_signal_new ("toggle_overwrite",
		  G_OBJECT_CLASS_TYPE (gobject_class),
		  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
		  G_STRUCT_OFFSET (GtkEntryClass, toggle_overwrite),
		  NULL, NULL,
		  _gtk_marshal_VOID__VOID,
		  G_TYPE_NONE, 0);
Owen Taylor's avatar
Owen Taylor committed
695 696 697 698 699 700 701 702 703

  /*
   * Key bindings
   */

  binding_set = gtk_binding_set_by_class (class);

  /* Moving the insertion point */
  add_move_binding (binding_set, GDK_Right, 0,
704
		    GTK_MOVEMENT_VISUAL_POSITIONS, 1);
Owen Taylor's avatar
Owen Taylor committed
705 706
  
  add_move_binding (binding_set, GDK_Left, 0,
707
		    GTK_MOVEMENT_VISUAL_POSITIONS, -1);
Owen Taylor's avatar
Owen Taylor committed
708

709 710 711 712 713 714
  add_move_binding (binding_set, GDK_KP_Right, 0,
		    GTK_MOVEMENT_VISUAL_POSITIONS, 1);
  
  add_move_binding (binding_set, GDK_KP_Left, 0,
		    GTK_MOVEMENT_VISUAL_POSITIONS, -1);
  
Owen Taylor's avatar
Owen Taylor committed
715 716 717 718 719
  add_move_binding (binding_set, GDK_Right, GDK_CONTROL_MASK,
		    GTK_MOVEMENT_WORDS, 1);

  add_move_binding (binding_set, GDK_Left, GDK_CONTROL_MASK,
		    GTK_MOVEMENT_WORDS, -1);
720 721 722 723 724 725

  add_move_binding (binding_set, GDK_KP_Right, GDK_CONTROL_MASK,
		    GTK_MOVEMENT_WORDS, 1);

  add_move_binding (binding_set, GDK_KP_Left, GDK_CONTROL_MASK,
		    GTK_MOVEMENT_WORDS, -1);
Owen Taylor's avatar
Owen Taylor committed
726 727 728 729 730 731
  
  add_move_binding (binding_set, GDK_Home, 0,
		    GTK_MOVEMENT_DISPLAY_LINE_ENDS, -1);

  add_move_binding (binding_set, GDK_End, 0,
		    GTK_MOVEMENT_DISPLAY_LINE_ENDS, 1);
732 733 734 735 736 737

  add_move_binding (binding_set, GDK_KP_Home, 0,
		    GTK_MOVEMENT_DISPLAY_LINE_ENDS, -1);

  add_move_binding (binding_set, GDK_KP_End, 0,
		    GTK_MOVEMENT_DISPLAY_LINE_ENDS, 1);
Owen Taylor's avatar
Owen Taylor committed
738 739 740 741 742 743 744
  
  add_move_binding (binding_set, GDK_Home, GDK_CONTROL_MASK,
		    GTK_MOVEMENT_BUFFER_ENDS, -1);

  add_move_binding (binding_set, GDK_End, GDK_CONTROL_MASK,
		    GTK_MOVEMENT_BUFFER_ENDS, 1);

745 746 747 748 749 750
  add_move_binding (binding_set, GDK_KP_Home, GDK_CONTROL_MASK,
		    GTK_MOVEMENT_BUFFER_ENDS, -1);

  add_move_binding (binding_set, GDK_KP_End, GDK_CONTROL_MASK,
		    GTK_MOVEMENT_BUFFER_ENDS, 1);

751 752 753 754 755
  /* Select all
   */
  gtk_binding_entry_add_signal (binding_set, GDK_a, GDK_CONTROL_MASK,
                                "move_cursor", 3,
                                GTK_TYPE_MOVEMENT_STEP, GTK_MOVEMENT_BUFFER_ENDS,
Manish Singh's avatar
Manish Singh committed
756 757
                                G_TYPE_INT, -1,
				G_TYPE_BOOLEAN, FALSE);
758 759 760
  gtk_binding_entry_add_signal (binding_set, GDK_a, GDK_CONTROL_MASK,
                                "move_cursor", 3,
                                GTK_TYPE_MOVEMENT_STEP, GTK_MOVEMENT_BUFFER_ENDS,
Manish Singh's avatar
Manish Singh committed
761 762
                                G_TYPE_INT, 1,
				G_TYPE_BOOLEAN, TRUE);
763 764 765 766


  /* Activate
   */
767 768 769 770 771
  gtk_binding_entry_add_signal (binding_set, GDK_Return, 0,
				"activate", 0);
  gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0,
				"activate", 0);
  
Owen Taylor's avatar
Owen Taylor committed
772 773 774
  /* Deleting text */
  gtk_binding_entry_add_signal (binding_set, GDK_Delete, 0,
				"delete_from_cursor", 2,
Manish Singh's avatar
Manish Singh committed
775 776
				G_TYPE_ENUM, GTK_DELETE_CHARS,
				G_TYPE_INT, 1);
Owen Taylor's avatar
Owen Taylor committed
777

778 779
  gtk_binding_entry_add_signal (binding_set, GDK_KP_Delete, 0,
				"delete_from_cursor", 2,
Manish Singh's avatar
Manish Singh committed
780 781
				G_TYPE_ENUM, GTK_DELETE_CHARS,
				G_TYPE_INT, 1);
782
  
Owen Taylor's avatar
Owen Taylor committed
783
  gtk_binding_entry_add_signal (binding_set, GDK_BackSpace, 0,
784
				"backspace", 0);
Owen Taylor's avatar
Owen Taylor committed
785

786 787
  /* Make this do the same as Backspace, to help with mis-typing */
  gtk_binding_entry_add_signal (binding_set, GDK_BackSpace, GDK_SHIFT_MASK,
788
				"backspace", 0);
789

Owen Taylor's avatar
Owen Taylor committed
790 791
  gtk_binding_entry_add_signal (binding_set, GDK_Delete, GDK_CONTROL_MASK,
				"delete_from_cursor", 2,
Manish Singh's avatar
Manish Singh committed
792 793
				G_TYPE_ENUM, GTK_DELETE_WORD_ENDS,
				G_TYPE_INT, 1);
Owen Taylor's avatar
Owen Taylor committed
794

795 796
  gtk_binding_entry_add_signal (binding_set, GDK_KP_Delete, GDK_CONTROL_MASK,
				"delete_from_cursor", 2,
Manish Singh's avatar
Manish Singh committed
797 798
				G_TYPE_ENUM, GTK_DELETE_WORD_ENDS,
				G_TYPE_INT, 1);
799
  
Owen Taylor's avatar
Owen Taylor committed
800 801
  gtk_binding_entry_add_signal (binding_set, GDK_BackSpace, GDK_CONTROL_MASK,
				"delete_from_cursor", 2,
Manish Singh's avatar
Manish Singh committed
802 803
				G_TYPE_ENUM, GTK_DELETE_WORD_ENDS,
				G_TYPE_INT, -1);
Owen Taylor's avatar
Owen Taylor committed
804 805 806 807 808 809 810 811 812

  /* Cut/copy/paste */

  gtk_binding_entry_add_signal (binding_set, GDK_x, GDK_CONTROL_MASK,
				"cut_clipboard", 0);
  gtk_binding_entry_add_signal (binding_set, GDK_c, GDK_CONTROL_MASK,
				"copy_clipboard", 0);
  gtk_binding_entry_add_signal (binding_set, GDK_v, GDK_CONTROL_MASK,
				"paste_clipboard", 0);
Elliot Lee's avatar
Elliot Lee committed
813

814 815 816 817 818 819 820
  gtk_binding_entry_add_signal (binding_set, GDK_Delete, GDK_SHIFT_MASK,
				"cut_clipboard", 0);
  gtk_binding_entry_add_signal (binding_set, GDK_Insert, GDK_CONTROL_MASK,
				"copy_clipboard", 0);
  gtk_binding_entry_add_signal (binding_set, GDK_Insert, GDK_SHIFT_MASK,
				"paste_clipboard", 0);

Owen Taylor's avatar
Owen Taylor committed
821 822 823
  /* Overwrite */
  gtk_binding_entry_add_signal (binding_set, GDK_Insert, 0,
				"toggle_overwrite", 0);
824 825
  gtk_binding_entry_add_signal (binding_set, GDK_KP_Insert, 0,
				"toggle_overwrite", 0);
826 827

  gtk_settings_install_property (g_param_spec_boolean ("gtk-entry-select-on-focus",
828 829
						       P_("Select on focus"),
						       P_("Whether to select the contents of an entry when it is focused"),
830 831
						       TRUE,
						       G_PARAM_READWRITE));
832 833

  g_type_class_add_private (gobject_class, sizeof (GtkEntryPrivate));
Owen Taylor's avatar
Owen Taylor committed
834
}
835

Owen Taylor's avatar
Owen Taylor committed
836 837 838
static void
gtk_entry_editable_init (GtkEditableClass *iface)
{
839 840 841 842
  iface->do_insert_text = gtk_entry_insert_text;
  iface->do_delete_text = gtk_entry_delete_text;
  iface->insert_text = gtk_entry_real_insert_text;
  iface->delete_text = gtk_entry_real_delete_text;
Owen Taylor's avatar
Owen Taylor committed
843 844 845 846 847
  iface->get_chars = gtk_entry_get_chars;
  iface->set_selection_bounds = gtk_entry_set_selection_bounds;
  iface->get_selection_bounds = gtk_entry_get_selection_bounds;
  iface->set_position = gtk_entry_real_set_position;
  iface->get_position = gtk_entry_get_position;
Elliot Lee's avatar
Elliot Lee committed
848 849
}

850 851 852 853 854 855
static void
gtk_entry_cell_editable_init (GtkCellEditableIface *iface)
{
  iface->start_editing = gtk_entry_start_editing;
}

856 857 858 859 860
static void
gtk_entry_set_property (GObject         *object,
                        guint            prop_id,
                        const GValue    *value,
                        GParamSpec      *pspec)
861
{
Owen Taylor's avatar
Owen Taylor committed
862
  GtkEntry *entry = GTK_ENTRY (object);
863

Havoc Pennington's avatar
Havoc Pennington committed
864
  switch (prop_id)
865
    {
Havoc Pennington's avatar
Havoc Pennington committed
866
    case PROP_EDITABLE:
Owen Taylor's avatar
Owen Taylor committed
867
      {
Havoc Pennington's avatar
Havoc Pennington committed
868 869 870
        gboolean new_value = g_value_get_boolean (value);

      	if (new_value != entry->editable)
Owen Taylor's avatar
Owen Taylor committed
871
	  {
872 873 874 875 876 877 878 879 880 881
	    if (!new_value)
	      {
		gtk_entry_reset_im_context (entry);
		if (GTK_WIDGET_HAS_FOCUS (entry))
		  gtk_im_context_focus_out (entry->im_context);

		entry->preedit_length = 0;
		entry->preedit_cursor = 0;
	      }

Owen Taylor's avatar
Owen Taylor committed
882
	    entry->editable = new_value;
883

884 885 886 887
	    if (new_value && GTK_WIDGET_HAS_FOCUS (entry))
	      gtk_im_context_focus_in (entry->im_context);
	    
	    gtk_entry_queue_draw (entry);
Owen Taylor's avatar
Owen Taylor committed
888 889 890
	  }
      }
      break;
Havoc Pennington's avatar
Havoc Pennington committed
891 892 893

    case PROP_MAX_LENGTH:
      gtk_entry_set_max_length (entry, g_value_get_int (value));
894
      break;
Havoc Pennington's avatar
Havoc Pennington committed
895 896 897
      
    case PROP_VISIBILITY:
      gtk_entry_set_visibility (entry, g_value_get_boolean (value));
898
      break;
Havoc Pennington's avatar
Havoc Pennington committed
899

900 901 902 903
    case PROP_HAS_FRAME:
      gtk_entry_set_has_frame (entry, g_value_get_boolean (value));
      break;

Havoc Pennington's avatar
Havoc Pennington committed
904
    case PROP_INVISIBLE_CHAR:
905
      gtk_entry_set_invisible_char (entry, g_value_get_uint (value));
906
      break;
Havoc Pennington's avatar
Havoc Pennington committed
907

908 909 910
    case PROP_ACTIVATES_DEFAULT:
      gtk_entry_set_activates_default (entry, g_value_get_boolean (value));
      break;
911 912 913 914

    case PROP_WIDTH_CHARS:
      gtk_entry_set_width_chars (entry, g_value_get_int (value));
      break;
915

916 917 918 919
    case PROP_TEXT:
      gtk_entry_set_text (entry, g_value_get_string (value));
      break;

920 921 922 923
    case PROP_XALIGN:
      gtk_entry_set_alignment (entry, g_value_get_float (value));
      break;

924
    case PROP_SCROLL_OFFSET:
925
    case PROP_CURSOR_POSITION:
926
    default:
Havoc Pennington's avatar
Havoc Pennington committed
927
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
928 929 930 931
      break;
    }
}

932 933 934 935 936
static void
gtk_entry_get_property (GObject         *object,
                        guint            prop_id,
                        GValue          *value,
                        GParamSpec      *pspec)
937
{
938
  GtkEntry *entry = GTK_ENTRY (object);
939

Havoc Pennington's avatar
Havoc Pennington committed
940
  switch (prop_id)
941
    {
942
    case PROP_CURSOR_POSITION:
Havoc Pennington's avatar
Havoc Pennington committed
943
      g_value_set_int (value, entry->current_pos);
Owen Taylor's avatar
Owen Taylor committed
944
      break;
945 946 947
    case PROP_SELECTION_BOUND:
      g_value_set_int (value, entry->selection_bound);
      break;
Havoc Pennington's avatar
Havoc Pennington committed
948 949
    case PROP_EDITABLE:
      g_value_set_boolean (value, entry->editable);
Owen Taylor's avatar
Owen Taylor committed
950
      break;
Havoc Pennington's avatar
Havoc Pennington committed
951 952
    case PROP_MAX_LENGTH:
      g_value_set_int (value, entry->text_max_length); 
953
      break;
Havoc Pennington's avatar
Havoc Pennington committed
954 955
    case PROP_VISIBILITY:
      g_value_set_boolean (value, entry->visible);
956
      break;
957 958 959
    case PROP_HAS_FRAME:
      g_value_set_boolean (value, entry->has_frame);
      break;
Havoc Pennington's avatar
Havoc Pennington committed
960
    case PROP_INVISIBLE_CHAR:
961
      g_value_set_uint (value, entry->invisible_char);
962
      break;
963 964 965
    case PROP_ACTIVATES_DEFAULT:
      g_value_set_boolean (value, entry->activates_default);
      break;
966 967 968
    case PROP_WIDTH_CHARS:
      g_value_set_int (value, entry->width_chars);
      break;
969 970 971
    case PROP_SCROLL_OFFSET:
      g_value_set_int (value, entry->scroll_offset);
      break;
972 973 974
    case PROP_TEXT:
      g_value_set_string (value, gtk_entry_get_text (entry));
      break;
975 976 977
    case PROP_XALIGN:
      g_value_set_float (value, gtk_entry_get_alignment (entry));
      break;
978
      
979
    default:
Havoc Pennington's avatar
Havoc Pennington committed
980
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
981 982 983 984
      break;
    }
}

Elliot Lee's avatar
Elliot Lee committed
985 986 987
static void
gtk_entry_init (GtkEntry *entry)
{
988 989
  GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (entry);
  
Elliot Lee's avatar
Elliot Lee committed
990 991
  GTK_WIDGET_SET_FLAGS (entry, GTK_CAN_FOCUS);

992 993 994
  entry->text_size = MIN_SIZE;
  entry->text = g_malloc (entry->text_size);
  entry->text[0] = '\0';
Owen Taylor's avatar
Owen Taylor committed
995 996 997

  entry->editable = TRUE;
  entry->visible = TRUE;
998
  entry->invisible_char = '*';
Owen Taylor's avatar
Owen Taylor committed
999
  entry->dnd_position = -1;
1000
  entry->width_chars = -1;
1001
  entry->is_cell_renderer = FALSE;
1002
  entry->editing_canceled = FALSE;
1003
  entry->has_frame = TRUE;
1004
  priv->xalign = 0.0;
1005

Owen Taylor's avatar
Owen Taylor committed
1006
  gtk_drag_dest_set (GTK_WIDGET (entry),
1007
                     GTK_DEST_DEFAULT_HIGHLIGHT,
1008
                     NULL, 0,
Owen Taylor's avatar
Owen Taylor committed
1009
                     GDK_ACTION_COPY | GDK_ACTION_MOVE);
1010
  gtk_drag_dest_add_text_targets (GTK_WIDGET (entry));
Owen Taylor's avatar
Owen Taylor committed
1011

1012 1013 1014 1015 1016
  /* This object is completely private. No external entity can gain a reference
   * to it; so we create it here and destroy it in finalize().
   */
  entry->im_context = gtk_im_multicontext_new ();
  
Manish Singh's avatar
Manish Singh committed
1017
  g_signal_connect (entry->im_context, "commit",
1018
		    G_CALLBACK (gtk_entry_commit_cb), entry);
Manish Singh's avatar
Manish Singh committed
1019
  g_signal_connect (entry->im_context, "preedit_changed",
1020
		    G_CALLBACK (gtk_entry_preedit_changed_cb), entry);
Manish Singh's avatar
Manish Singh committed
1021
  g_signal_connect (entry->im_context, "retrieve_surrounding",
1022
		    G_CALLBACK (gtk_entry_retrieve_surrounding_cb), entry);
Manish Singh's avatar
Manish Singh committed
1023
  g_signal_connect (entry->im_context, "delete_surrounding",
1024
		    G_CALLBACK (gtk_entry_delete_surrounding_cb), entry);
Elliot Lee's avatar
Elliot Lee committed
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
/*
 * Overwrite a memory that might contain sensitive information.
 */
static void
trash_area (gchar *area, gsize len)
{
  volatile gchar *varea = (volatile gchar *)area;
  while (len-- > 0)
    *varea++ = 0;
}

static void
gtk_entry_destroy (GtkObject *object)
{
  GtkEntry *entry = GTK_ENTRY (object);

  entry->n_bytes = 0;
  entry->current_pos = entry->selection_bound = entry->text_length = 0;
  gtk_entry_reset_im_context (entry);
  gtk_entry_reset_layout (entry);

  if (!entry->visible)
    {
      /* We want to trash the text here because the entry might be leaked.  */
      trash_area (entry->text, strlen (entry->text));
    }

  GTK_OBJECT_CLASS (parent_class)->destroy (object);
}

Elliot Lee's avatar
Elliot Lee committed
1057
static void
1058
gtk_entry_finalize (GObject *object)
Elliot Lee's avatar
Elliot Lee committed
1059
{
1060
  GtkEntry *entry = GTK_ENTRY (object);
Elliot Lee's avatar
Elliot Lee committed
1061

1062 1063
  gtk_entry_set_completion (entry, NULL);

Owen Taylor's avatar
Owen Taylor committed
1064
  if (entry->cached_layout)
Manish Singh's avatar
Manish Singh committed
1065
    g_object_unref (entry->cached_layout);
Owen Taylor's avatar
Owen Taylor committed
1066

Manish Singh's avatar
Manish Singh committed
1067
  g_object_unref (entry->im_context);
1068

1069 1070
  if (entry->blink_timeout)
    g_source_remove (entry->blink_timeout);
Owen Taylor's avatar
Owen Taylor committed
1071 1072 1073

  if (entry->recompute_idle)
    g_source_remove (entry->recompute_idle);
Elliot Lee's avatar
Elliot Lee committed
1074

1075
  entry->text_size = 0;
1076

Elliot Lee's avatar
Elliot Lee committed
1077
  if (entry->text)
1078 1079 1080 1081 1082 1083
    {
      if (!entry->visible)
	trash_area (entry->text, strlen (entry->text));
      g_free (entry->text);
      entry->text = NULL;
    }
Elliot Lee's avatar
Elliot Lee committed
1084

1085
  G_OBJECT_CLASS (parent_class)->finalize (object);
Elliot Lee's avatar
Elliot Lee committed
1086 1087 1088 1089 1090 1091
}

static void
gtk_entry_realize (GtkWidget *widget)
{
  GtkEntry *entry;
1092
  GtkEditable *editable;
Elliot Lee's avatar
Elliot Lee committed
1093 1094 1095 1096 1097
  GdkWindowAttr attributes;
  gint attributes_mask;

  GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
  entry = GTK_ENTRY (widget);
1098
  editable = GTK_EDITABLE (widget);
1099

Elliot Lee's avatar
Elliot Lee committed
1100
  attributes.window_type = GDK_WINDOW_CHILD;
1101 1102 1103
  
  get_widget_window_size (entry, &attributes.x, &attributes.y, &attributes.width, &attributes.height);

Elliot Lee's avatar
Elliot Lee committed
1104 1105 1106 1107 1108 1109 1110 1111 1112
  attributes.wclass = GDK_INPUT_OUTPUT;
  attributes.visual = gtk_widget_get_visual (widget);
  attributes.colormap = gtk_widget_get_colormap (widget);
  attributes.event_mask = gtk_widget_get_events (widget);
  attributes.event_mask |= (GDK_EXPOSURE_MASK |
			    GDK_BUTTON_PRESS_MASK |
			    GDK_BUTTON_RELEASE_MASK |
			    GDK_BUTTON1_MOTION_MASK |
			    GDK_BUTTON3_MOTION_MASK |
1113
			    GDK_POINTER_MOTION_HINT_MASK |
1114
			    GDK_POINTER_MOTION_MASK |
1115 1116
                            GDK_ENTER_NOTIFY_MASK |
			    GDK_LEAVE_NOTIFY_MASK);
Elliot Lee's avatar
Elliot Lee committed
1117 1118
  attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;

1119
  widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
Elliot Lee's avatar
Elliot Lee committed
1120 1121
  gdk_window_set_user_data (widget->window, entry);

1122 1123
  get_text_area_size (entry, &attributes.x, &attributes.y, &attributes.width, &attributes.height);

1124
  attributes.cursor = gdk_cursor_new_for_display (gtk_widget_get_display (widget), GDK_XTERM);
1125
  attributes_mask |= GDK_WA_CURSOR;
Elliot Lee's avatar
Elliot Lee committed
1126 1127 1128 1129

  entry->text_area = gdk_window_new (widget->window, &attributes, attributes_mask);
  gdk_window_set_user_data (entry->text_area, entry);

1130
  gdk_cursor_unref (attributes.cursor);
1131

Elliot Lee's avatar
Elliot Lee committed
1132 1133
  widget->style = gtk_style_attach (widget->style, widget->window);

1134 1135
  gdk_window_set_background (widget->window, &widget->style->base[GTK_WIDGET_STATE (widget)]);
  gdk_window_set_background (entry->text_area, &widget->style->base[GTK_WIDGET_STATE (widget)]);
Elliot Lee's avatar
Elliot Lee committed
1136 1137

  gdk_window_show (entry->text_area);
1138

1139
  gtk_im_context_set_client_window (entry->im_context, entry->text_area);
1140

Owen Taylor's avatar
Owen Taylor committed
1141
  gtk_entry_adjust_scroll (entry);
1142
  gtk_entry_update_primary_selection (entry);
Elliot Lee's avatar
Elliot Lee committed
1143 1144 1145 1146 1147
}

static void
gtk_entry_unrealize (GtkWidget *widget)
{
1148
  GtkEntry *entry = GTK_ENTRY (widget);
1149
  GtkClipboard *clipboard;
Elliot Lee's avatar
Elliot Lee committed
1150

1151 1152
  gtk_entry_reset_layout (entry);
  
1153
  gtk_im_context_set_client_window (entry->im_context, NULL);
1154 1155 1156 1157

  clipboard = gtk_widget_get_clipboard (widget, GDK_SELECTION_PRIMARY);
  if (gtk_clipboard_get_owner (clipboard) == G_OBJECT (entry))
    gtk_clipboard_clear (clipboard);
1158
  
Elliot Lee's avatar
Elliot Lee committed
1159 1160 1161 1162
  if (entry->text_area)
    {
      gdk_window_set_user_data (entry->text_area, NULL);
      gdk_window_destroy (entry->text_area);
1163
      entry->text_area = NULL;
Elliot Lee's avatar
Elliot Lee committed
1164
    }
1165

Owen Taylor's avatar
Owen Taylor committed
1166
  if (entry->popup_menu)
1167 1168 1169 1170
    {
      gtk_widget_destroy (entry->popup_menu);
      entry->popup_menu = NULL;
    }
Owen Taylor's avatar
Owen Taylor committed
1171

1172 1173
  if (GTK_WIDGET_CLASS (parent_class)->unrealize)
    (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
Elliot Lee's avatar
Elliot Lee committed
1174 1175
}

1176 1177 1178 1179
void
_gtk_entry_get_borders (GtkEntry *entry,
			gint     *xborder,
			gint     *yborder)
1180
{
1181
  GtkWidget *widget = GTK_WIDGET (entry);
1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207
  gint focus_width;
  gboolean interior_focus;

  gtk_widget_style_get (widget,
			"interior-focus", &interior_focus,
			"focus-line-width", &focus_width,
			NULL);

  if (entry->has_frame)
    {
      *xborder = widget->style->xthickness;
      *yborder = widget->style->ythickness;
    }
  else
    {
      *xborder = 0;
      *yborder = 0;
    }

  if (!interior_focus)
    {
      *xborder += focus_width;
      *yborder += focus_width;
    }
}

Elliot Lee's avatar
Elliot Lee committed
1208 1209 1210 1211
static void
gtk_entry_size_request (GtkWidget      *widget,
			GtkRequisition *requisition)
{
1212
  GtkEntry *entry = GTK_ENTRY (widget);
1213
  PangoFontMetrics *metrics;
1214
  gint xborder, yborder;
1215
  PangoContext *context;
1216
  
Matthias Clasen's avatar
Matthias Clasen committed
1217
  gtk_widget_ensure_style (widget);
1218
  context = gtk_widget_get_pango_context (widget);
1219 1220 1221
  metrics = pango_context_get_metrics (context,
				       widget->style->font_desc,
				       pango_context_get_language (context));
1222

1223 1224
  entry->ascent = pango_font_metrics_get_ascent (metrics);
  entry->descent = pango_font_metrics_get_descent (metrics);
Matthias Clasen's avatar
Matthias Clasen committed
1225
  
1226
  _gtk_entry_get_borders (entry, &xborder, &yborder);
1227 1228 1229
  
  xborder += INNER_BORDER;
  yborder += INNER_BORDER;
1230
  
1231 1232 1233 1234
  if (entry->width_chars < 0)
    requisition->width = MIN_ENTRY_WIDTH + xborder * 2;
  else
    {
1235
      gint char_width = pango_font_metrics_get_approximate_char_width (metrics);
1236 1237 1238 1239
      gint digit_width = pango_font_metrics_get_approximate_digit_width (metrics);
      gint char_pixels = (MAX (char_width, digit_width) + PANGO_SCALE - 1) / PANGO_SCALE;
      
      requisition->width = char_pixels * entry->width_chars + xborder * 2;
1240 1241
    }
    
1242 1243 1244
  requisition->height = PANGO_PIXELS (entry->ascent + entry->descent) + yborder * 2;

  pango_font_metrics_unref (metrics);
Elliot Lee's avatar
Elliot Lee committed
1245 1246
}

1247 1248 1249 1250 1251 1252 1253 1254 1255
static void
get_text_area_size (GtkEntry *entry,
                    gint     *x,
                    gint     *y,
                    gint     *width,
                    gint     *height)
{
  gint xborder, yborder;
  GtkRequisition requisition;
1256
  GtkWidget *widget = GTK_WIDGET (entry);
1257

1258 1259
  gtk_widget_get_child_requisition (widget, &requisition);

1260
  _gtk_entry_get_borders (entry, &xborder, &yborder);
1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282

  if (x)
    *x = xborder;

  if (y)
    *y = yborder;
  
  if (width)
    *width = GTK_WIDGET (entry)->allocation.width - xborder * 2;

  if (height)
    *height = requisition.height - yborder * 2;
}

static void
get_widget_window_size (GtkEntry *entry,
                        gint     *x,
                        gint     *y,
                        gint     *width,
                        gint     *height)
{
  GtkRequisition requisition;
1283
  GtkWidget *widget = GTK_WIDGET (entry);
1284 1285 1286 1287 1288 1289 1290
      
  gtk_widget_get_child_requisition (widget, &requisition);

  if (x)
    *x = widget->allocation.x;

  if (y)
1291 1292 1293 1294 1295 1296
    {
      if (entry->is_cell_renderer)
	*y = widget->allocation.y;
      else
	*y = widget->allocation.y + (widget->allocation.height - requisition.height) / 2;
    }
1297 1298 1299 1300 1301

  if (width)
    *width = widget->allocation.width;

  if (height)
1302 1303 1304 1305 1306 1307
    {
      if (entry->is_cell_renderer)
	*height = widget->allocation.height;
      else
	*height = requisition.height;
    }
1308 1309
}

Elliot Lee's avatar
Elliot Lee committed
1310 1311 1312 1313
static void
gtk_entry_size_allocate (GtkWidget     *widget,
			 GtkAllocation *allocation)
{
1314
  GtkEntry *entry = GTK_ENTRY (widget);
1315
  
Elliot Lee's avatar
Elliot Lee committed
1316
  widget->allocation = *allocation;
1317
  
Elliot Lee's avatar
Elliot Lee committed
1318 1319
  if (GTK_WIDGET_REALIZED (widget))
    {
1320 1321 1322 1323
      /* We call gtk_widget_get_child_requisition, since we want (for
       * backwards compatibility reasons) the realization here to
       * be affected by the usize of the entry, if set
       */
1324 1325 1326 1327
      gint x, y, width, height;

      get_widget_window_size (entry, &x, &y, &width, &height);
      
Elliot Lee's avatar
Elliot Lee committed
1328
      gdk_window_move_resize (widget->window,
1329 1330 1331 1332
                              x, y, width, height);   

      get_text_area_size (entry, &x, &y, &width, &height);
      
Elliot Lee's avatar
Elliot Lee committed
1333
      gdk_window_move_resize (entry->text_area,
1334
                              x, y, width, height);
Elliot Lee's avatar
Elliot Lee committed
1335

Owen Taylor's avatar
Owen Taylor committed
1336
      gtk_entry_recompute (entry);
Elliot Lee's avatar
Elliot Lee committed
1337 1338 1339
    }
}

Owen Taylor's avatar
Owen Taylor committed
1340
static void
1341
gtk_entry_draw_frame (GtkWidget *widget)
Elliot Lee's avatar
Elliot Lee committed
1342
{
1343
  gint x = 0, y = 0;
Owen Taylor's avatar
Owen Taylor committed
1344
  gint width, height;
1345
  gboolean interior_focus;
1346
  gint focus_width;
1347
  
1348 1349 1350 1351
  gtk_widget_style_get (widget,
			"interior-focus", &interior_focus,
			"focus-line-width", &focus_width,
			NULL);
1352
  
Manish Singh's avatar
Manish Singh committed
1353
  gdk_drawable_get_size (widget->window, &width, &height);
1354 1355 1356 1357 1358 1359 1360
  
  if (GTK_WIDGET_HAS_FOCUS (widget) && !interior_focus)
    {
      x += focus_width;
      y += focus_width