gtkentry.c 152 KB
Newer Older
1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
Elliot Lee's avatar
Elliot Lee committed
2 3 4 5
/* 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
6
 * modify it under the terms of the GNU Lesser General Public
Elliot Lee's avatar
Elliot Lee committed
7 8 9 10 11 12
 * 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
13
 * Lesser General Public License for more details.
Elliot Lee's avatar
Elliot Lee committed
14
 *
15
 * You should have received a copy of the GNU Lesser General Public
16 17 18
 * 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
19
 */
20 21

/*
22
 * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
23 24 25 26 27
 * 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/. 
 */

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

#include <pango/pango.h>

Elliot Lee's avatar
Elliot Lee committed
33
#include "gdk/gdkkeysyms.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
#include "gtktreeview.h"
#include "gtktreeselection.h"
54
#include "gtkprivate.h"
55 56
#include "gtkentryprivate.h"
#include "gtkcelllayout.h"
57
#include "gtkalias.h"
58 59

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

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

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

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

72 73 74 75 76 77 78
typedef struct _GtkEntryPrivate GtkEntryPrivate;

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

struct _GtkEntryPrivate 
{
  gfloat xalign;
79
  gint insert_pos;
80 81
};

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

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

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

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

Owen Taylor's avatar
Owen Taylor committed
119 120
/* GObject, GtkObject methods
 */
121 122 123
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);
124
static void   gtk_entry_init                 (GtkEntry         *entry);
Havoc Pennington's avatar
Havoc Pennington committed
125 126 127
static void   gtk_entry_set_property (GObject         *object,
				      guint            prop_id,
				      const GValue    *value,
128
				      GParamSpec      *pspec);
Havoc Pennington's avatar
Havoc Pennington committed
129 130 131
static void   gtk_entry_get_property (GObject         *object,
				      guint            prop_id,
				      GValue          *value,
132
				      GParamSpec      *pspec);
133
static void   gtk_entry_finalize             (GObject          *object);
134
static void   gtk_entry_destroy              (GtkObject        *object);
Owen Taylor's avatar
Owen Taylor committed
135 136 137

/* GtkWidget methods
 */
138 139 140 141 142 143
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);
144
static void   gtk_entry_draw_frame           (GtkWidget        *widget);
145 146 147 148 149 150 151 152 153 154
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);
155 156
static gint   gtk_entry_key_release          (GtkWidget        *widget,
					      GdkEventKey      *event);
157 158 159 160
static gint   gtk_entry_focus_in             (GtkWidget        *widget,
					      GdkEventFocus    *event);
static gint   gtk_entry_focus_out            (GtkWidget        *widget,
					      GdkEventFocus    *event);
161
static void   gtk_entry_grab_focus           (GtkWidget        *widget);
162 163 164 165 166 167
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);
168 169
static void   gtk_entry_screen_changed       (GtkWidget        *widget,
					      GdkScreen        *old_screen);
Owen Taylor's avatar
Owen Taylor committed
170

171 172 173 174 175
static gboolean gtk_entry_drag_drop          (GtkWidget        *widget,
                                              GdkDragContext   *context,
                                              gint              x,
                                              gint              y,
                                              guint             time);
Owen Taylor's avatar
Owen Taylor committed
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
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
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
/* 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);

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

Owen Taylor's avatar
Owen Taylor committed
226 227
/* Default signal handlers
 */
228
static void gtk_entry_real_insert_text   (GtkEditable     *editable,
229 230 231
					  const gchar     *new_text,
					  gint             new_text_length,
					  gint            *position);
232
static void gtk_entry_real_delete_text   (GtkEditable     *editable,
233 234 235 236 237 238 239 240 241 242 243
					  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);
244
static void gtk_entry_backspace          (GtkEntry        *entry);
245 246 247 248
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);
249
static void gtk_entry_select_all         (GtkEntry        *entry);
250
static void gtk_entry_real_activate      (GtkEntry        *entry);
251
static gboolean gtk_entry_popup_menu     (GtkWidget      *widget);
Owen Taylor's avatar
Owen Taylor committed
252

253 254
static void gtk_entry_keymap_direction_changed (GdkKeymap *keymap,
						GtkEntry  *entry);
Owen Taylor's avatar
Owen Taylor committed
255 256
/* IM Context Callbacks
 */
257 258 259 260 261 262 263 264 265 266 267 268
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
269 270
/* Internal routines
 */
271 272
static void         gtk_entry_enter_text               (GtkEntry       *entry,
                                                        const gchar    *str);
273 274 275
static void         gtk_entry_set_positions            (GtkEntry       *entry,
							gint            current_pos,
							gint            selection_bound);
Owen Taylor's avatar
Owen Taylor committed
276
static void         gtk_entry_draw_text                (GtkEntry       *entry);
Owen Taylor's avatar
Owen Taylor committed
277 278
static void         gtk_entry_draw_cursor              (GtkEntry       *entry,
							CursorType      type);
279 280
static PangoLayout *gtk_entry_ensure_layout            (GtkEntry       *entry,
                                                        gboolean        include_preedit);
281
static void         gtk_entry_reset_layout             (GtkEntry       *entry);
Owen Taylor's avatar
Owen Taylor committed
282 283 284 285 286 287
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
288
							CursorType      type,
Owen Taylor's avatar
Owen Taylor committed
289 290 291 292 293 294
							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);
295 296 297
static gint         gtk_entry_move_logically           (GtkEntry       *entry,
							gint            start,
							gint            count);
Owen Taylor's avatar
Owen Taylor committed
298
static gint         gtk_entry_move_forward_word        (GtkEntry       *entry,
299 300
							gint            start,
                                                        gboolean        allow_whitespace);
Owen Taylor's avatar
Owen Taylor committed
301
static gint         gtk_entry_move_backward_word       (GtkEntry       *entry,
302 303
							gint            start,
                                                        gboolean        allow_whitespace);
Owen Taylor's avatar
Owen Taylor committed
304 305 306 307 308 309 310 311 312
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);
313
static void         gtk_entry_do_popup                 (GtkEntry       *entry,
Owen Taylor's avatar
Owen Taylor committed
314
							GdkEventButton *event);
315 316
static gboolean     gtk_entry_mnemonic_activate        (GtkWidget      *widget,
							gboolean        group_cycling);
317 318
static void         gtk_entry_state_changed            (GtkWidget      *widget,
							GtkStateType    previous_state);
319 320
static void         gtk_entry_check_cursor_blink       (GtkEntry       *entry);
static void         gtk_entry_pend_cursor_blink        (GtkEntry       *entry);
321 322 323 324 325 326 327 328 329 330
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);
331

332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356
/* 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
357 358
static GtkWidgetClass *parent_class = NULL;

Manish Singh's avatar
Manish Singh committed
359
GType
360
gtk_entry_get_type (void)
Elliot Lee's avatar
Elliot Lee committed
361
{
Manish Singh's avatar
Manish Singh committed
362
  static GType entry_type = 0;
Elliot Lee's avatar
Elliot Lee committed
363 364 365

  if (!entry_type)
    {
Manish Singh's avatar
Manish Singh committed
366
      static const GTypeInfo entry_info =
Elliot Lee's avatar
Elliot Lee committed
367 368
      {
	sizeof (GtkEntryClass),
Manish Singh's avatar
Manish Singh committed
369 370 371 372 373 374 375 376
	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
377
      };
Owen Taylor's avatar
Owen Taylor committed
378 379 380 381 382 383 384
      
      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
385

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

Owen Taylor's avatar
Owen Taylor committed
396 397 398
      g_type_add_interface_static (entry_type,
				   GTK_TYPE_EDITABLE,
				   &editable_info);
399 400 401
      g_type_add_interface_static (entry_type,
				   GTK_TYPE_CELL_EDITABLE,
				   &cell_editable_info);
Elliot Lee's avatar
Elliot Lee committed
402 403 404 405 406
    }

  return entry_type;
}

Owen Taylor's avatar
Owen Taylor committed
407 408 409 410 411 412 413 414 415 416 417
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
418
				G_TYPE_ENUM, step,
Owen Taylor's avatar
Owen Taylor committed
419
				G_TYPE_INT, count,
Manish Singh's avatar
Manish Singh committed
420
				G_TYPE_BOOLEAN, FALSE);
Owen Taylor's avatar
Owen Taylor committed
421 422 423 424

  /* 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
425
				G_TYPE_ENUM, step,
Owen Taylor's avatar
Owen Taylor committed
426
				G_TYPE_INT, count,
Manish Singh's avatar
Manish Singh committed
427
				G_TYPE_BOOLEAN, TRUE);
Owen Taylor's avatar
Owen Taylor committed
428 429
}

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

  widget_class = (GtkWidgetClass*) class;
439
  gtk_object_class = (GtkObjectClass *)class;
Manish Singh's avatar
Manish Singh committed
440
  parent_class = g_type_class_peek_parent (class);
Elliot Lee's avatar
Elliot Lee committed
441

442
  gobject_class->finalize = gtk_entry_finalize;
Havoc Pennington's avatar
Havoc Pennington committed
443 444
  gobject_class->set_property = gtk_entry_set_property;
  gobject_class->get_property = gtk_entry_get_property;
445 446 447 448 449 450 451 452 453 454

  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;
455
  widget_class->key_release_event = gtk_entry_key_release;
456 457
  widget_class->focus_in_event = gtk_entry_focus_in;
  widget_class->focus_out_event = gtk_entry_focus_out;
458
  widget_class->grab_focus = gtk_entry_grab_focus;
459 460 461
  widget_class->style_set = gtk_entry_style_set;
  widget_class->direction_changed = gtk_entry_direction_changed;
  widget_class->state_changed = gtk_entry_state_changed;
462
  widget_class->screen_changed = gtk_entry_screen_changed;
463
  widget_class->mnemonic_activate = gtk_entry_mnemonic_activate;
464

465
  widget_class->drag_drop = gtk_entry_drag_drop;
Owen Taylor's avatar
Owen Taylor committed
466 467 468 469 470 471
  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;

472
  widget_class->popup_menu = gtk_entry_popup_menu;
473

474 475
  gtk_object_class->destroy = gtk_entry_destroy;

476 477 478
  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;
479
  class->backspace = gtk_entry_backspace;
480 481 482 483
  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;
484 485
  class->activate = gtk_entry_real_activate;
  
Havoc Pennington's avatar
Havoc Pennington committed
486
  g_object_class_install_property (gobject_class,
487
                                   PROP_CURSOR_POSITION,
Matthias Clasen's avatar
x  
Matthias Clasen committed
488
                                   g_param_spec_int ("cursor-position",
489 490
                                                     P_("Cursor Position"),
                                                     P_("The current position of the insertion cursor in chars"),
Havoc Pennington's avatar
Havoc Pennington committed
491
                                                     0,
492
                                                     MAX_SIZE,
Havoc Pennington's avatar
Havoc Pennington committed
493
                                                     0,
494
                                                     GTK_PARAM_READABLE));
495 496 497
  
  g_object_class_install_property (gobject_class,
                                   PROP_SELECTION_BOUND,
Matthias Clasen's avatar
x  
Matthias Clasen committed
498
                                   g_param_spec_int ("selection-bound",
499 500
                                                     P_("Selection Bound"),
                                                     P_("The position of the opposite end of the selection from the cursor in chars"),
501
                                                     0,
502
                                                     MAX_SIZE,
503
                                                     0,
504
                                                     GTK_PARAM_READABLE));
Havoc Pennington's avatar
Havoc Pennington committed
505 506 507 508
  
  g_object_class_install_property (gobject_class,
                                   PROP_EDITABLE,
                                   g_param_spec_boolean ("editable",
509 510
							 P_("Editable"),
							 P_("Whether the entry contents can be edited"),
Havoc Pennington's avatar
Havoc Pennington committed
511
                                                         TRUE,
512
							 GTK_PARAM_READWRITE));
Havoc Pennington's avatar
Havoc Pennington committed
513 514 515
  
  g_object_class_install_property (gobject_class,
                                   PROP_MAX_LENGTH,
Matthias Clasen's avatar
x  
Matthias Clasen committed
516
                                   g_param_spec_int ("max-length",
517 518
                                                     P_("Maximum length"),
                                                     P_("Maximum number of characters for this entry. Zero if no maximum"),
519 520 521
                                                     0,
                                                     MAX_SIZE,
                                                     0,
522
                                                     GTK_PARAM_READWRITE));
Havoc Pennington's avatar
Havoc Pennington committed
523 524 525
  g_object_class_install_property (gobject_class,
                                   PROP_VISIBILITY,
                                   g_param_spec_boolean ("visibility",
526 527
							 P_("Visibility"),
							 P_("FALSE displays the \"invisible char\" instead of the actual text (password mode)"),
Havoc Pennington's avatar
Havoc Pennington committed
528
                                                         TRUE,
529
							 GTK_PARAM_READWRITE));
530

Havoc Pennington's avatar
Havoc Pennington committed
531
  g_object_class_install_property (gobject_class,
532
                                   PROP_HAS_FRAME,
Matthias Clasen's avatar
x  
Matthias Clasen committed
533
                                   g_param_spec_boolean ("has-frame",
534 535
							 P_("Has Frame"),
							 P_("FALSE removes outside bevel from entry"),
536
                                                         TRUE,
537
							 GTK_PARAM_READWRITE));
538

Morten Welinder's avatar
Morten Welinder committed
539
  g_object_class_install_property (gobject_class,
Havoc Pennington's avatar
Havoc Pennington committed
540
                                   PROP_INVISIBLE_CHAR,
Matthias Clasen's avatar
x  
Matthias Clasen committed
541
                                   g_param_spec_unichar ("invisible-char",
542 543
							 P_("Invisible character"),
							 P_("The character to use when masking entry contents (in \"password mode\")"),
544
							 '*',
545
							 GTK_PARAM_READWRITE));
Havoc Pennington's avatar
Havoc Pennington committed
546

547 548
  g_object_class_install_property (gobject_class,
                                   PROP_ACTIVATES_DEFAULT,
Matthias Clasen's avatar
x  
Matthias Clasen committed
549
                                   g_param_spec_boolean ("activates-default",
550 551
							 P_("Activates default"),
							 P_("Whether to activate the default widget (such as the default button in a dialog) when Enter is pressed"),
552
                                                         FALSE,
553
							 GTK_PARAM_READWRITE));
554 555
  g_object_class_install_property (gobject_class,
                                   PROP_WIDTH_CHARS,
Matthias Clasen's avatar
x  
Matthias Clasen committed
556
                                   g_param_spec_int ("width-chars",
557 558
                                                     P_("Width in chars"),
                                                     P_("Number of characters to leave space for in the entry"),
559 560 561
                                                     -1,
                                                     G_MAXINT,
                                                     -1,
562
                                                     GTK_PARAM_READWRITE));
563

564 565
  g_object_class_install_property (gobject_class,
                                   PROP_SCROLL_OFFSET,
Matthias Clasen's avatar
x  
Matthias Clasen committed
566
                                   g_param_spec_int ("scroll-offset",
567 568
                                                     P_("Scroll offset"),
                                                     P_("Number of pixels of the entry scrolled off the screen to the left"),
569 570 571
                                                     0,
                                                     G_MAXINT,
                                                     0,
572
                                                     GTK_PARAM_READABLE));
573 574 575 576

  g_object_class_install_property (gobject_class,
                                   PROP_TEXT,
                                   g_param_spec_string ("text",
577 578
							P_("Text"),
							P_("The contents of the entry"),
579
							"",
580
							GTK_PARAM_READWRITE));
581

582 583 584 585 586 587 588 589
  /**
   * GtkEntry:xalign:
   *
   * The horizontal alignment, from 0 (left) to 1 (right). 
   * Reversed for RTL layouts.
   * 
   * Since: 2.4
   */
590 591 592 593
  g_object_class_install_property (gobject_class,
                                   PROP_XALIGN,
                                   g_param_spec_float ("xalign",
						       P_("X align"),
594
						       P_("The horizontal alignment, from 0 (left) to 1 (right). Reversed for RTL layouts."),
595 596 597
						       0.0,
						       1.0,
						       0.0,
598
						       GTK_PARAM_READWRITE));
599
  
600
  signals[POPULATE_POPUP] =
601
    g_signal_new (I_("populate_popup"),
Manish Singh's avatar
Manish Singh committed
602 603 604 605 606 607 608
		  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);
609
  
Owen Taylor's avatar
Owen Taylor committed
610 611 612
 /* Action signals */
  
  signals[ACTIVATE] =
613
    g_signal_new (I_("activate"),
Manish Singh's avatar
Manish Singh committed
614 615 616 617 618 619
		  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
620 621 622
  widget_class->activate_signal = signals[ACTIVATE];

  signals[MOVE_CURSOR] = 
623
    g_signal_new (I_("move_cursor"),
Manish Singh's avatar
Manish Singh committed
624 625 626 627 628 629 630 631 632
		  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
633 634

  signals[INSERT_AT_CURSOR] = 
635
    g_signal_new (I_("insert_at_cursor"),
Manish Singh's avatar
Manish Singh committed
636 637 638 639 640 641 642
		  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
643 644

  signals[DELETE_FROM_CURSOR] = 
645
    g_signal_new (I_("delete_from_cursor"),
Manish Singh's avatar
Manish Singh committed
646 647 648 649 650 651 652 653
		  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
654

655
  signals[BACKSPACE] =
656
    g_signal_new (I_("backspace"),
657 658 659 660 661 662 663
		  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
664
  signals[CUT_CLIPBOARD] =
665
    g_signal_new (I_("cut_clipboard"),
Manish Singh's avatar
Manish Singh committed
666 667 668 669 670 671
		  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
672 673

  signals[COPY_CLIPBOARD] =
674
    g_signal_new (I_("copy_clipboard"),
Manish Singh's avatar
Manish Singh committed
675 676 677 678 679 680
		  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
681 682

  signals[PASTE_CLIPBOARD] =
683
    g_signal_new (I_("paste_clipboard"),
Manish Singh's avatar
Manish Singh committed
684 685 686 687 688 689
		  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
690 691

  signals[TOGGLE_OVERWRITE] =
692
    g_signal_new (I_("toggle_overwrite"),
Manish Singh's avatar
Manish Singh committed
693 694 695 696 697 698
		  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
699 700 701 702 703 704 705 706 707

  /*
   * Key bindings
   */

  binding_set = gtk_binding_set_by_class (class);

  /* Moving the insertion point */
  add_move_binding (binding_set, GDK_Right, 0,
708
		    GTK_MOVEMENT_VISUAL_POSITIONS, 1);
Owen Taylor's avatar
Owen Taylor committed
709 710
  
  add_move_binding (binding_set, GDK_Left, 0,
711
		    GTK_MOVEMENT_VISUAL_POSITIONS, -1);
Owen Taylor's avatar
Owen Taylor committed
712

713 714 715 716 717 718
  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
719 720 721 722 723
  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);
724 725 726 727 728 729

  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
730 731 732 733 734 735
  
  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);
736 737 738 739 740 741

  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
742 743 744 745 746 747 748
  
  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);

749 750 751 752 753 754
  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);

755 756 757 758 759
  /* 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
760 761
                                G_TYPE_INT, -1,
				G_TYPE_BOOLEAN, FALSE);
762 763 764
  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
765
                                G_TYPE_INT, 1,
766
				G_TYPE_BOOLEAN, TRUE);  
767

768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784
  gtk_binding_entry_add_signal (binding_set, GDK_slash, GDK_CONTROL_MASK,
                                "move_cursor", 3,
                                GTK_TYPE_MOVEMENT_STEP, GTK_MOVEMENT_BUFFER_ENDS,
                                G_TYPE_INT, -1,
				G_TYPE_BOOLEAN, FALSE);
  gtk_binding_entry_add_signal (binding_set, GDK_slash, GDK_CONTROL_MASK,
                                "move_cursor", 3,
                                GTK_TYPE_MOVEMENT_STEP, GTK_MOVEMENT_BUFFER_ENDS,
                                G_TYPE_INT, 1,
				G_TYPE_BOOLEAN, TRUE);  
  /* Unselect all 
   */
  gtk_binding_entry_add_signal (binding_set, GDK_backslash, GDK_CONTROL_MASK,
                                "move_cursor", 3,
                                GTK_TYPE_MOVEMENT_STEP, GTK_MOVEMENT_VISUAL_POSITIONS,
                                G_TYPE_INT, 0,
				G_TYPE_BOOLEAN, FALSE);
785 786 787

  /* Activate
   */
788 789 790 791 792
  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
793 794 795
  /* Deleting text */
  gtk_binding_entry_add_signal (binding_set, GDK_Delete, 0,
				"delete_from_cursor", 2,
Manish Singh's avatar
Manish Singh committed
796 797
				G_TYPE_ENUM, GTK_DELETE_CHARS,
				G_TYPE_INT, 1);
Owen Taylor's avatar
Owen Taylor committed
798

799 800
  gtk_binding_entry_add_signal (binding_set, GDK_KP_Delete, 0,
				"delete_from_cursor", 2,
Manish Singh's avatar
Manish Singh committed
801 802
				G_TYPE_ENUM, GTK_DELETE_CHARS,
				G_TYPE_INT, 1);
803
  
Owen Taylor's avatar
Owen Taylor committed
804
  gtk_binding_entry_add_signal (binding_set, GDK_BackSpace, 0,
805
				"backspace", 0);
Owen Taylor's avatar
Owen Taylor committed
806

807 808
  /* Make this do the same as Backspace, to help with mis-typing */
  gtk_binding_entry_add_signal (binding_set, GDK_BackSpace, GDK_SHIFT_MASK,
809
				"backspace", 0);
810

Owen Taylor's avatar
Owen Taylor committed
811 812
  gtk_binding_entry_add_signal (binding_set, GDK_Delete, GDK_CONTROL_MASK,
				"delete_from_cursor", 2,
Manish Singh's avatar
Manish Singh committed
813 814
				G_TYPE_ENUM, GTK_DELETE_WORD_ENDS,
				G_TYPE_INT, 1);
Owen Taylor's avatar
Owen Taylor committed
815

816 817
  gtk_binding_entry_add_signal (binding_set, GDK_KP_Delete, GDK_CONTROL_MASK,
				"delete_from_cursor", 2,
Manish Singh's avatar
Manish Singh committed
818 819
				G_TYPE_ENUM, GTK_DELETE_WORD_ENDS,
				G_TYPE_INT, 1);
820
  
Owen Taylor's avatar
Owen Taylor committed
821 822
  gtk_binding_entry_add_signal (binding_set, GDK_BackSpace, GDK_CONTROL_MASK,
				"delete_from_cursor", 2,
Manish Singh's avatar
Manish Singh committed
823 824
				G_TYPE_ENUM, GTK_DELETE_WORD_ENDS,
				G_TYPE_INT, -1);
Owen Taylor's avatar
Owen Taylor committed
825 826 827 828 829 830 831 832 833

  /* 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
834

835 836 837 838 839 840 841
  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
842 843 844
  /* Overwrite */
  gtk_binding_entry_add_signal (binding_set, GDK_Insert, 0,
				"toggle_overwrite", 0);
845 846
  gtk_binding_entry_add_signal (binding_set, GDK_KP_Insert, 0,
				"toggle_overwrite", 0);
847 848

  gtk_settings_install_property (g_param_spec_boolean ("gtk-entry-select-on-focus",
849 850
						       P_("Select on focus"),
						       P_("Whether to select the contents of an entry when it is focused"),
851
						       TRUE,
852
						       GTK_PARAM_READWRITE));
853 854

  g_type_class_add_private (gobject_class, sizeof (GtkEntryPrivate));
Owen Taylor's avatar
Owen Taylor committed
855
}
856

Owen Taylor's avatar
Owen Taylor committed
857 858 859
static void
gtk_entry_editable_init (GtkEditableClass *iface)
{
860 861 862 863
  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
864 865 866 867 868
  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
869 870
}

871 872 873 874 875 876
static void
gtk_entry_cell_editable_init (GtkCellEditableIface *iface)
{
  iface->start_editing = gtk_entry_start_editing;
}

877 878 879 880 881
static void
gtk_entry_set_property (GObject         *object,
                        guint            prop_id,
                        const GValue    *value,
                        GParamSpec      *pspec)
882
{
Owen Taylor's avatar
Owen Taylor committed
883
  GtkEntry *entry = GTK_ENTRY (object);
884

Havoc Pennington's avatar
Havoc Pennington committed
885
  switch (prop_id)
886
    {
Havoc Pennington's avatar
Havoc Pennington committed
887
    case PROP_EDITABLE:
Owen Taylor's avatar
Owen Taylor committed
888
      {
Havoc Pennington's avatar
Havoc Pennington committed
889 890 891
        gboolean new_value = g_value_get_boolean (value);

      	if (new_value != entry->editable)
Owen Taylor's avatar
Owen Taylor committed
892
	  {
893 894 895 896 897 898 899 900 901 902
	    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
903
	    entry->editable = new_value;
904

905 906 907 908
	    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
909 910 911
	  }
      }
      break;
Havoc Pennington's avatar
Havoc Pennington committed
912 913 914

    case PROP_MAX_LENGTH:
      gtk_entry_set_max_length (entry, g_value_get_int (value));
915
      break;
Havoc Pennington's avatar
Havoc Pennington committed
916 917 918
      
    case PROP_VISIBILITY:
      gtk_entry_set_visibility (entry, g_value_get_boolean (value));
919
      break;
Havoc Pennington's avatar
Havoc Pennington committed
920

921 922 923 924
    case PROP_HAS_FRAME:
      gtk_entry_set_has_frame (entry, g_value_get_boolean (value));
      break;

Havoc Pennington's avatar
Havoc Pennington committed
925
    case PROP_INVISIBLE_CHAR:
926
      gtk_entry_set_invisible_char (entry, g_value_get_uint (value));
927
      break;
Havoc Pennington's avatar
Havoc Pennington committed
928

929 930 931
    case PROP_ACTIVATES_DEFAULT:
      gtk_entry_set_activates_default (entry, g_value_get_boolean (value));
      break;
932 933 934 935

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

937 938 939 940
    case PROP_TEXT:
      gtk_entry_set_text (entry, g_value_get_string (value));
      break;

941 942 943 944
    case PROP_XALIGN:
      gtk_entry_set_alignment (entry, g_value_get_float (value));
      break;

945
    case PROP_SCROLL_OFFSET:
946
    case PROP_CURSOR_POSITION:
947
    default:
Havoc Pennington's avatar
Havoc Pennington committed
948
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
949 950 951 952
      break;
    }
}

953 954 955 956 957
static void
gtk_entry_get_property (GObject         *object,
                        guint            prop_id,
                        GValue          *value,
                        GParamSpec      *pspec)
958
{
959
  GtkEntry *entry = GTK_ENTRY (object);
960

Havoc Pennington's avatar
Havoc Pennington committed
961
  switch (prop_id)
962
    {
963
    case PROP_CURSOR_POSITION:
Havoc Pennington's avatar
Havoc Pennington committed
964
      g_value_set_int (value, entry->current_pos);
Owen Taylor's avatar
Owen Taylor committed
965
      break;
966 967 968
    case PROP_SELECTION_BOUND:
      g_value_set_int (value, entry->selection_bound);
      break;
Havoc Pennington's avatar
Havoc Pennington committed
969 970
    case PROP_EDITABLE:
      g_value_set_boolean (value, entry->editable);
Owen Taylor's avatar
Owen Taylor committed
971
      break;
Havoc Pennington's avatar
Havoc Pennington committed
972 973
    case PROP_MAX_LENGTH:
      g_value_set_int (value, entry->text_max_length); 
974
      break;
Havoc Pennington's avatar
Havoc Pennington committed
975 976
    case PROP_VISIBILITY:
      g_value_set_boolean (value, entry->visible);
977
      break;
978 979 980
    case PROP_HAS_FRAME:
      g_value_set_boolean (value, entry->has_frame);
      break;
Havoc Pennington's avatar
Havoc Pennington committed
981
    case PROP_INVISIBLE_CHAR:
982
      g_value_set_uint (value, entry->invisible_char);
983
      break;
984 985 986
    case PROP_ACTIVATES_DEFAULT:
      g_value_set_boolean (value, entry->activates_default);
      break;
987 988 989
    case PROP_WIDTH_CHARS:
      g_value_set_int (value, entry->width_chars);
      break;
990 991 992
    case PROP_SCROLL_OFFSET:
      g_value_set_int (value, entry->scroll_offset);
      break;
993 994 995
    case PROP_TEXT:
      g_value_set_string (value, gtk_entry_get_text (entry));
      break;
996 997 998
    case PROP_XALIGN:
      g_value_set_float (value, gtk_entry_get_alignment (entry));
      break;
999
      
1000
    default:
Havoc Pennington's avatar
Havoc Pennington committed
1001
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1002 1003 1004 1005
      break;
    }
}

Elliot Lee's avatar
Elliot Lee committed
1006 1007 1008
static void
gtk_entry_init (GtkEntry *entry)
{
1009 1010
  GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (entry);
  
Elliot Lee's avatar
Elliot Lee committed
1011 1012
  GTK_WIDGET_SET_FLAGS (entry, GTK_CAN_FOCUS);

1013 1014 1015
  entry->text_size = MIN_SIZE;
  entry->text = g_malloc (entry->text_size);
  entry->text[0] = '\0';
Owen Taylor's avatar
Owen Taylor committed
1016 1017 1018

  entry->editable = TRUE;
  entry->visible = TRUE;
1019
  entry->invisible_char = '*';
Owen Taylor's avatar
Owen Taylor committed
1020
  entry->dnd_position = -1;
1021
  entry->width_chars = -1;
1022
  entry->is_cell_renderer = FALSE;
1023
  entry->editing_canceled = FALSE;
1024
  entry->has_frame = TRUE;
1025
  priv->xalign = 0.0;
1026

Owen Taylor's avatar
Owen Taylor committed
1027
  gtk_drag_dest_set (GTK_WIDGET (entry),
1028
                     GTK_DEST_DEFAULT_HIGHLIGHT,
1029
                     NULL, 0,
Owen Taylor's avatar
Owen Taylor committed
1030
                     GDK_ACTION_COPY | GDK_ACTION_MOVE);
1031
  gtk_drag_dest_add_text_targets (GTK_WIDGET (entry));
Owen Taylor's avatar
Owen Taylor committed
1032

1033 1034 1035 1036 1037
  /* 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
1038
  g_signal_connect (entry->im_context, "commit",
1039
		    G_CALLBACK (gtk_entry_commit_cb), entry);
Manish Singh's avatar
Manish Singh committed
1040
  g_signal_connect (entry->im_context, "preedit_changed",
1041
		    G_CALLBACK (gtk_entry_preedit_changed_cb), entry);
Manish Singh's avatar
Manish Singh committed
1042
  g_signal_connect (entry->im_context, "retrieve_surrounding",
1043
		    G_CALLBACK (gtk_entry_retrieve_surrounding_cb), entry);
Manish Singh's avatar
Manish Singh committed
1044
  g_signal_connect (entry->im_context, "delete_surrounding",
1045
		    G_CALLBACK (gtk_entry_delete_surrounding_cb), entry);
Elliot Lee's avatar
Elliot Lee committed
1046 1047
}

1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077
/*
 * 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
1078
static void
1079
gtk_entry_finalize (GObject *object)
Elliot Lee's avatar
Elliot Lee committed
1080
{
1081
  GtkEntry *entry = GTK_ENTRY (object);
Elliot Lee's avatar
Elliot Lee committed
1082

1083 1084
  gtk_entry_set_completion (entry, NULL);

Owen Taylor's avatar
Owen Taylor committed
1085
  if (entry->cached_layout)
Manish Singh's avatar
Manish Singh committed
1086
    g_object_unref (entry->cached_layout);
Owen Taylor's avatar
Owen Taylor committed
1087

Manish Singh's avatar
Manish Singh committed
1088
  g_object_unref (entry->im_context);
1089

1090 1091
  if (entry->blink_timeout)
    g_source_remove (entry->blink_timeout);
Owen Taylor's avatar
Owen Taylor committed
1092 1093 1094

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

1096
  entry->text_size = 0;
1097

Elliot Lee's avatar
Elliot Lee committed
1098
  if (entry->text)
1099 1100 1101 1102 1103 1104
    {
      if (!entry->visible)
	trash_area (entry->text, strlen (entry->text));
      g_free (entry->text);
      entry->text = NULL;
    }
Elliot Lee's avatar
Elliot Lee committed
1105

1106
  G_OBJECT_CLASS (parent_class)->finalize (object);
Elliot Lee's avatar
Elliot Lee committed
1107 1108 1109 1110 1111 1112
}

static void
gtk_entry_realize (GtkWidget *widget)
{
  GtkEntry *entry;
1113
  GtkEditable *editable;
Elliot Lee's avatar
Elliot Lee committed
1114 1115 1116 1117 1118
  GdkWindowAttr attributes;
  gint attributes_mask;

  GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
  entry = GTK_ENTRY (widget);
1119
  editable = GTK_EDITABLE (widget);
1120

Elliot Lee's avatar
Elliot Lee committed
1121
  attributes.window_type = GDK_WINDOW_CHILD;
1122 1123 1124
  
  get_widget_window_size (entry, &attributes.x, &attributes.y, &attributes.width, &attributes.height);

Elliot Lee's avatar
Elliot Lee committed
1125 1126 1127 1128 1129 1130 1131 1132 1133
  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 |
1134
			    GDK_POINTER_MOTION_HINT_MASK |
1135
			    GDK_POINTER_MOTION_MASK |
1136 1137
                            GDK_ENTER_NOTIFY_MASK |
			    GDK_LEAVE_NOTIFY_MASK);
Elliot Lee's avatar
Elliot Lee committed
1138 1139
  attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;

1140
  widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
Elliot Lee's avatar
Elliot Lee committed
1141 1142
  gdk_window_set_user_data (widget->window, entry);

1143 1144
  get_text_area_size (entry, &attributes.x, &attributes.y, &attributes.width, &attributes.height);

1145
  attributes.cursor = gdk_cursor_new_for_display (gtk_widget_get_display (widget), GDK_XTERM);
1146
  attributes_mask |= GDK_WA_CURSOR;
Elliot Lee's avatar
Elliot Lee committed
1147 1148 1149 1150

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

1151
  gdk_cursor_unref (attributes.cursor);
1152

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

1155 1156
  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
1157 1158

  gdk_window_show (entry->text_area);
1159

1160
  gtk_im_context_set_client_window (entry->im_context, entry->text_area);
1161

Owen Taylor's avatar
Owen Taylor committed
1162
  gtk_entry_adjust_scroll (entry);
1163
  gtk_entry_update_primary_selection (entry);
Elliot Lee's avatar
Elliot Lee committed
1164 1165 1166 1167 1168
}

static void
gtk_entry_unrealize (GtkWidget *widget)
{
1169
  GtkEntry *entry = GTK_ENTRY (widget);
1170
  GtkClipboard *clipboard;
Elliot Lee's avatar
Elliot Lee committed
1171

1172 1173
  gtk_entry_reset_layout (entry);
  
1174
  gtk_im_context_set_client_window (entry->im_context, NULL);
1175 1176 1177 1178

  clipboard = gtk_widget_get_clipboard (widget, GDK_SELECTION_PRIMARY);
  if (gtk_clipboard_get_owner (clipboard) == G_OBJECT (entry))
    gtk_clipboard_clear (clipboard);
1179
  
Elliot Lee's avatar
Elliot Lee committed
1180 1181 1182 1183
  if (entry->text_area)
    {
      gdk_window_set_user_data (entry->text_area, NULL);
      gdk_window_destroy (entry->text_area);
1184
      entry->text_area = NULL;
Elliot Lee's avatar
Elliot Lee committed
1185
    }
1186

Owen Taylor's avatar
Owen Taylor committed
1187
  if (entry->popup_menu)
1188 1189 1190 1191
    {
      gtk_widget_destroy (entry->popup_menu);
      entry->popup_menu = NULL;
    }
Owen Taylor's avatar
Owen Taylor committed
1192

1193 1194
  if (GTK_WIDGET_CLASS (parent_class)->unrealize)
    (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
Elliot Lee's avatar
Elliot Lee committed
1195 1196
}

1197 1198 1199 1200
void
_gtk_entry_get_borders (GtkEntry *entry,
			gint     *xborder,
			gint     *yborder)
1201
{
1202
  GtkWidget *widget = GTK_WIDGET (entry);
1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228
  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
1229 1230 1231 1232
static void
gtk_entry_size_request (GtkWidget      *widget,
			GtkRequisition *requisition)
{
1233
  GtkEntry *entry = GTK_ENTRY (widget);
1234
  PangoFontMetrics *metrics;
1235
  gint xborder, yborder;
1236
  PangoContext *context;
1237
  
Matthias Clasen's avatar
Matthias Clasen committed
1238
  gtk_widget_ensure_style (widget);
1239
  context = gtk_widget_get_pango_context (widget);
1240 1241 1242
  metrics = pango_context_get_metrics (context,
				       widget->style->font_desc,
				       pango_context_get_language (context));
1243

1244 1245
  entry->ascent = pango_font_metrics_get_ascent (metrics);
  entry->descent = pango_font_metrics_get_descent (metrics);
Matthias Clasen's avatar
Matthias Clasen committed
1246
  
1247
  _gtk_entry_get_borders (entry, &xborder, &yborder);
1248 1249 1250
  
  xborder += INNER_BORDER;
  yborder += INNER_BORDER;
1251
  
1252 1253 1254 1255
  if (entry->width_chars < 0)
    requisition->width = MIN_ENTRY_WIDTH + xborder * 2;
  else
    {
1256
      gint char_width = pango_font_metrics_get_approximate_char_width (metrics);
1257 1258 1259 1260
      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;
1261 1262
    }
    
1263 1264 1265
  requisition->height = PANGO_PIXELS (entry->ascent + entry->descent) + yborder * 2;

  pango_font_metrics_unref (metrics);
Elliot Lee's avatar
Elliot Lee committed
1266 1267
}

1268 1269 1270 1271 1272 1273 1274 1275 1276
static void
get_text_area_size (GtkEntry *entry,
                    gint     *x,
                    gint     *y,
                    gint     *width,
                    gint     *height)
{
  gint xborder, yborder;
  GtkRequisition requisition;
1277
  GtkWidget *widget = GTK_WIDGET (entry);
1278

1279 1280
  gtk_widget_get_child_requisition (widget, &requisition);

1281
  _gtk_entry_get_borders (entry, &xborder, &yborder);
1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303

  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;
1304
  GtkWidget *widget = GTK_WIDGET (entry);
1305 1306 1307 1308 1309 1310 1311
      
  gtk_widget_get_child_requisition