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

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

#include <pango/pango.h>

Elliot Lee's avatar
Elliot Lee committed
31
#include "gdk/gdkkeysyms.h"
Owen Taylor's avatar
Owen Taylor committed
32 33
#include "gtkbindings.h"
#include "gtkclipboard.h"
Owen Taylor's avatar
Owen Taylor committed
34
#include "gtkdnd.h"
Elliot Lee's avatar
Elliot Lee committed
35
#include "gtkentry.h"
36
#include "gtkimmulticontext.h"
Owen Taylor's avatar
Owen Taylor committed
37
#include "gtkintl.h"
Elliot Lee's avatar
Elliot Lee committed
38
#include "gtkmain.h"
Owen Taylor's avatar
Owen Taylor committed
39 40
#include "gtkmenu.h"
#include "gtkmenuitem.h"
41
#include "gtkseparatormenuitem.h"
Elliot Lee's avatar
Elliot Lee committed
42
#include "gtkselection.h"
43
#include "gtksettings.h"
Elliot Lee's avatar
Elliot Lee committed
44
#include "gtksignal.h"
45
#include "gtkwindow.h"
46

Elliot Lee's avatar
Elliot Lee committed
47 48 49 50
#define MIN_ENTRY_WIDTH  150
#define DRAW_TIMEOUT     20
#define INNER_BORDER     2

51 52 53 54 55 56
/* Initial size of buffer, in bytes */
#define MIN_SIZE 16

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

Owen Taylor's avatar
Owen Taylor committed
57 58 59 60 61
enum {
  INSERT_TEXT,
  DELETE_TEXT,
  CHANGED,
  ACTIVATE,
Owen Taylor's avatar
Owen Taylor committed
62
  POPULATE_POPUP,
Owen Taylor's avatar
Owen Taylor committed
63 64 65 66 67 68 69 70 71 72
  MOVE_CURSOR,
  INSERT_AT_CURSOR,
  DELETE_FROM_CURSOR,
  CUT_CLIPBOARD,
  COPY_CLIPBOARD,
  PASTE_CLIPBOARD,
  TOGGLE_OVERWRITE,
  LAST_SIGNAL
};

73
enum {
Havoc Pennington's avatar
Havoc Pennington committed
74 75 76 77 78
  PROP_0,
  PROP_TEXT_POSITION,
  PROP_EDITABLE,
  PROP_MAX_LENGTH,
  PROP_VISIBILITY,
79
  PROP_INVISIBLE_CHAR,
80
  PROP_ACTIVATES_DEFAULT,
81 82
  PROP_WIDTH_CHARS,
  PROP_SCROLL_OFFSET
83 84
};

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

Owen Taylor's avatar
Owen Taylor committed
87 88 89 90 91 92 93 94 95 96 97 98 99
typedef enum {
  CURSOR_STANDARD,
  CURSOR_DND
} CursorType;

static GtkTargetEntry target_table[] = {
  { "UTF8_STRING",   0, 0 },
  { "COMPOUND_TEXT", 0, 0 },
  { "TEXT",          0, 0 },
  { "text/plain",    0, 0 },
  { "STRING",        0, 0 }
};

Owen Taylor's avatar
Owen Taylor committed
100 101
/* GObject, GtkObject methods
 */
102
static void   gtk_entry_class_init           (GtkEntryClass    *klass);
Owen Taylor's avatar
Owen Taylor committed
103
static void   gtk_entry_editable_init        (GtkEditableClass *iface);
104
static void   gtk_entry_init                 (GtkEntry         *entry);
Havoc Pennington's avatar
Havoc Pennington committed
105 106 107
static void   gtk_entry_set_property (GObject         *object,
				      guint            prop_id,
				      const GValue    *value,
108
				      GParamSpec      *pspec);
Havoc Pennington's avatar
Havoc Pennington committed
109 110 111
static void   gtk_entry_get_property (GObject         *object,
				      guint            prop_id,
				      GValue          *value,
112
				      GParamSpec      *pspec);
113
static void   gtk_entry_finalize             (GObject          *object);
Owen Taylor's avatar
Owen Taylor committed
114 115 116

/* GtkWidget methods
 */
117 118 119 120 121 122
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);
Owen Taylor's avatar
Owen Taylor committed
123
static void   gtk_entry_draw_focus           (GtkWidget        *widget);
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
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);
static gint   gtk_entry_focus_in             (GtkWidget        *widget,
					      GdkEventFocus    *event);
static gint   gtk_entry_focus_out            (GtkWidget        *widget,
					      GdkEventFocus    *event);
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);
Owen Taylor's avatar
Owen Taylor committed
144

Owen Taylor's avatar
Owen Taylor committed
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
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
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
/* 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);

/* Default signal handlers
 */
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
static void gtk_entry_real_insert_text   (GtkEntry        *entry,
					  const gchar     *new_text,
					  gint             new_text_length,
					  gint            *position);
static void gtk_entry_real_delete_text   (GtkEntry        *entry,
					  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);
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);
212
static void gtk_entry_real_activate      (GtkEntry        *entry);
Owen Taylor's avatar
Owen Taylor committed
213
static void gtk_entry_popup_menu         (GtkWidget      *widget);
Owen Taylor's avatar
Owen Taylor committed
214

215 216
static void gtk_entry_keymap_direction_changed (GdkKeymap *keymap,
						GtkEntry  *entry);
Owen Taylor's avatar
Owen Taylor committed
217 218
/* IM Context Callbacks
 */
219 220 221
static void gtk_entry_commit_cb           (GtkIMContext      *context,
					   const gchar       *str,
					   GtkEntry          *entry);
Owen Taylor's avatar
Owen Taylor committed
222 223 224 225
static void gtk_entry_preedit_changed_cb  (GtkIMContext      *context,
					   GtkEntry          *entry);
/* Internal routines
 */
226 227 228
static void         gtk_entry_set_positions            (GtkEntry       *entry,
							gint            current_pos,
							gint            selection_bound);
Owen Taylor's avatar
Owen Taylor committed
229
static void         gtk_entry_draw_text                (GtkEntry       *entry);
Owen Taylor's avatar
Owen Taylor committed
230 231
static void         gtk_entry_draw_cursor              (GtkEntry       *entry,
							CursorType      type);
232 233
static PangoLayout *gtk_entry_ensure_layout            (GtkEntry       *entry,
                                                        gboolean        include_preedit);
Owen Taylor's avatar
Owen Taylor committed
234 235 236 237 238 239
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
240
							CursorType      type,
Owen Taylor's avatar
Owen Taylor committed
241 242 243 244 245 246
							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);
247 248 249
static gint         gtk_entry_move_logically           (GtkEntry       *entry,
							gint            start,
							gint            count);
Owen Taylor's avatar
Owen Taylor committed
250 251 252 253 254 255 256 257 258 259 260 261 262
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);
Owen Taylor's avatar
Owen Taylor committed
263
static void         gtk_entry_do_popup                 (GtkEntry       *entry,
Owen Taylor's avatar
Owen Taylor committed
264
							GdkEventButton *event);
265 266
static gboolean     gtk_entry_mnemonic_activate        (GtkWidget      *widget,
							gboolean        group_cycling);
267 268
static void         gtk_entry_check_cursor_blink       (GtkEntry       *entry);
static void         gtk_entry_pend_cursor_blink        (GtkEntry       *entry);
269

Elliot Lee's avatar
Elliot Lee committed
270 271
static GtkWidgetClass *parent_class = NULL;

272
GtkType
273
gtk_entry_get_type (void)
Elliot Lee's avatar
Elliot Lee committed
274
{
275
  static GtkType entry_type = 0;
Elliot Lee's avatar
Elliot Lee committed
276 277 278

  if (!entry_type)
    {
279
      static const GtkTypeInfo entry_info =
Elliot Lee's avatar
Elliot Lee committed
280 281 282 283 284 285
      {
	"GtkEntry",
	sizeof (GtkEntry),
	sizeof (GtkEntryClass),
	(GtkClassInitFunc) gtk_entry_class_init,
	(GtkObjectInitFunc) gtk_entry_init,
286 287
	/* reserved_1 */ NULL,
	/* reserved_2 */ NULL,
288
        (GtkClassInitFunc) NULL,
Elliot Lee's avatar
Elliot Lee committed
289
      };
Owen Taylor's avatar
Owen Taylor committed
290 291 292 293 294 295 296
      
      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
297

Owen Taylor's avatar
Owen Taylor committed
298 299 300 301
      entry_type = gtk_type_unique (GTK_TYPE_WIDGET, &entry_info);
      g_type_add_interface_static (entry_type,
				   GTK_TYPE_EDITABLE,
				   &editable_info);
Elliot Lee's avatar
Elliot Lee committed
302 303 304 305 306
    }

  return entry_type;
}

Owen Taylor's avatar
Owen Taylor committed
307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329
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,
				GTK_TYPE_ENUM, step,
				G_TYPE_INT, count,
                                G_TYPE_BOOLEAN, FALSE);

  /* Selection-extending version */
  gtk_binding_entry_add_signal (binding_set, keyval, modmask | GDK_SHIFT_MASK,
				"move_cursor", 3,
				GTK_TYPE_ENUM, step,
				G_TYPE_INT, count,
                                G_TYPE_BOOLEAN, TRUE);
}

Elliot Lee's avatar
Elliot Lee committed
330 331 332
static void
gtk_entry_class_init (GtkEntryClass *class)
{
333
  GObjectClass *gobject_class = G_OBJECT_CLASS (class);
Elliot Lee's avatar
Elliot Lee committed
334 335
  GtkObjectClass *object_class;
  GtkWidgetClass *widget_class;
Owen Taylor's avatar
Owen Taylor committed
336
  GtkBindingSet *binding_set;
Elliot Lee's avatar
Elliot Lee committed
337 338 339

  object_class = (GtkObjectClass*) class;
  widget_class = (GtkWidgetClass*) class;
Owen Taylor's avatar
Owen Taylor committed
340
  parent_class = gtk_type_class (GTK_TYPE_WIDGET);
Elliot Lee's avatar
Elliot Lee committed
341

342
  gobject_class->finalize = gtk_entry_finalize;
Havoc Pennington's avatar
Havoc Pennington committed
343 344
  gobject_class->set_property = gtk_entry_set_property;
  gobject_class->get_property = gtk_entry_get_property;
345 346 347 348 349 350 351 352 353 354 355 356 357 358 359

  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;
  widget_class->focus_in_event = gtk_entry_focus_in;
  widget_class->focus_out_event = gtk_entry_focus_out;
  widget_class->style_set = gtk_entry_style_set;
  widget_class->direction_changed = gtk_entry_direction_changed;
  widget_class->state_changed = gtk_entry_state_changed;
360
  widget_class->mnemonic_activate = gtk_entry_mnemonic_activate;
361

Owen Taylor's avatar
Owen Taylor committed
362 363 364 365 366 367
  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;

Owen Taylor's avatar
Owen Taylor committed
368 369
  widget_class->popup_menu = gtk_entry_popup_menu;
  
370 371 372 373 374 375 376 377 378
  class->insert_text = gtk_entry_real_insert_text;
  class->delete_text = gtk_entry_real_delete_text;
  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;
  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;
379 380
  class->activate = gtk_entry_real_activate;
  
Havoc Pennington's avatar
Havoc Pennington committed
381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416
  g_object_class_install_property (gobject_class,
                                   PROP_TEXT_POSITION,
                                   g_param_spec_int ("text_position",
                                                     _("Text Position"),
                                                     _("The current position of the insertion point"),
                                                     0,
                                                     G_MAXINT,
                                                     0,
                                                     G_PARAM_READABLE | G_PARAM_WRITABLE));
  
  g_object_class_install_property (gobject_class,
                                   PROP_EDITABLE,
                                   g_param_spec_boolean ("editable",
							 _("Editable"),
							 _("Whether the entry contents can be edited"),
                                                         TRUE,
							 G_PARAM_READABLE | G_PARAM_WRITABLE));
  
  g_object_class_install_property (gobject_class,
                                   PROP_MAX_LENGTH,
                                   g_param_spec_int ("max_length",
                                                     _("Maximum length"),
                                                     _("Maximum number of characters for this entry"),
                                                     -1,
                                                     G_MAXINT,
                                                     -1,
                                                     G_PARAM_READABLE | G_PARAM_WRITABLE));
  g_object_class_install_property (gobject_class,
                                   PROP_VISIBILITY,
                                   g_param_spec_boolean ("visibility",
							 _("Visibility"),
							 _("FALSE displays the \"invisible char\" instead of the actual text (password mode)"),
                                                         TRUE,
							 G_PARAM_READABLE | G_PARAM_WRITABLE));
  g_object_class_install_property (gobject_class,
                                   PROP_INVISIBLE_CHAR,
417 418 419 420 421
                                   g_param_spec_unichar ("invisible_char",
							 _("Invisible character"),
							 _("The character to use when masking entry contents (in \"password mode\")"),
							 '*',
							 G_PARAM_READABLE | G_PARAM_WRITABLE));
Havoc Pennington's avatar
Havoc Pennington committed
422

423 424 425 426 427 428 429
  g_object_class_install_property (gobject_class,
                                   PROP_ACTIVATES_DEFAULT,
                                   g_param_spec_boolean ("activates_default",
							 _("Activates default"),
							 _("Whether to activate the default widget (such as the default button in a dialog) when Enter is pressed."),
                                                         FALSE,
							 G_PARAM_READABLE | G_PARAM_WRITABLE));
430 431 432 433 434 435 436 437 438 439
  g_object_class_install_property (gobject_class,
                                   PROP_WIDTH_CHARS,
                                   g_param_spec_int ("width_chars",
                                                     _("Width in chars"),
                                                     _("Number of characters to leave space for in the entry."),
                                                     -1,
                                                     G_MAXINT,
                                                     
                                                     -1,
                                                     G_PARAM_READABLE | G_PARAM_WRITABLE));
440

441 442 443 444 445 446 447 448 449 450 451
  g_object_class_install_property (gobject_class,
                                   PROP_SCROLL_OFFSET,
                                   g_param_spec_int ("scroll_offset",
                                                     _("Scroll offset"),
                                                     _("Number of pixels of the entry scrolled off the screen to the left"),
                                                     0,
                                                     G_MAXINT,
                                                     
                                                     0,
                                                     G_PARAM_READABLE));
  
452 453 454 455
  gtk_widget_class_install_style_property (widget_class,
					   g_param_spec_boxed ("cursor_color",
							       _("Cursor color"),
							       _("Color with which to draw insertion cursor"),
456
							       GDK_TYPE_COLOR,
457 458
							       G_PARAM_READABLE));

Owen Taylor's avatar
Owen Taylor committed
459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489
  signals[INSERT_TEXT] =
    gtk_signal_new ("insert_text",
		    GTK_RUN_LAST,
		    GTK_CLASS_TYPE (object_class),
		    GTK_SIGNAL_OFFSET (GtkEntryClass, insert_text),
		    gtk_marshal_VOID__STRING_INT_POINTER,
		    GTK_TYPE_NONE,
		    3,
		    GTK_TYPE_STRING,
		    GTK_TYPE_INT,
		    GTK_TYPE_POINTER);

  signals[DELETE_TEXT] =
    gtk_signal_new ("delete_text",
		    GTK_RUN_LAST,
		    GTK_CLASS_TYPE (object_class),
		    GTK_SIGNAL_OFFSET (GtkEntryClass, delete_text),
		    gtk_marshal_VOID__INT_INT,
		    GTK_TYPE_NONE,
		    2,
		    GTK_TYPE_INT,
		    GTK_TYPE_INT);		    

  signals[CHANGED] =
    gtk_signal_new ("changed",
		    GTK_RUN_LAST,
		    GTK_CLASS_TYPE (object_class),
		    GTK_SIGNAL_OFFSET (GtkEntryClass, changed),
		    gtk_marshal_VOID__VOID,
		    GTK_TYPE_NONE, 0);

Owen Taylor's avatar
Owen Taylor committed
490 491 492 493 494 495 496 497
  signals[POPULATE_POPUP] =
    gtk_signal_new ("populate_popup",
		    GTK_RUN_LAST,
		    GTK_CLASS_TYPE (object_class),
		    GTK_SIGNAL_OFFSET (GtkEntryClass, populate_popup),
		    gtk_marshal_VOID__OBJECT,
		    GTK_TYPE_NONE, 1, GTK_TYPE_MENU);
  
Owen Taylor's avatar
Owen Taylor committed
498 499 500 501 502 503 504 505 506 507 508 509 510 511 512
 /* Action signals */
  
  signals[ACTIVATE] =
    gtk_signal_new ("activate",
		    GTK_RUN_LAST | GTK_RUN_ACTION,
		    GTK_CLASS_TYPE (object_class),
		    GTK_SIGNAL_OFFSET (GtkEntryClass, activate),
		    gtk_marshal_VOID__VOID,
		    GTK_TYPE_NONE, 0);
  widget_class->activate_signal = signals[ACTIVATE];

  signals[MOVE_CURSOR] = 
      gtk_signal_new ("move_cursor",
                      GTK_RUN_LAST | GTK_RUN_ACTION,
                      GTK_CLASS_TYPE (object_class),
513
                      GTK_SIGNAL_OFFSET (GtkEntryClass, move_cursor),
Owen Taylor's avatar
Owen Taylor committed
514 515 516 517 518 519 520
                      gtk_marshal_VOID__ENUM_INT_BOOLEAN,
                      GTK_TYPE_NONE, 3, GTK_TYPE_MOVEMENT_STEP, GTK_TYPE_INT, GTK_TYPE_BOOL);

  signals[INSERT_AT_CURSOR] = 
      gtk_signal_new ("insert_at_cursor",
                      GTK_RUN_LAST | GTK_RUN_ACTION,
                      GTK_CLASS_TYPE (object_class),
521
                      GTK_SIGNAL_OFFSET (GtkEntryClass, insert_at_cursor),
Owen Taylor's avatar
Owen Taylor committed
522 523 524 525 526 527 528
                      gtk_marshal_VOID__STRING,
                      GTK_TYPE_NONE, 1, GTK_TYPE_STRING);

  signals[DELETE_FROM_CURSOR] = 
      gtk_signal_new ("delete_from_cursor",
                      GTK_RUN_LAST | GTK_RUN_ACTION,
                      GTK_CLASS_TYPE (object_class),
529
                      GTK_SIGNAL_OFFSET (GtkEntryClass, delete_from_cursor),
Owen Taylor's avatar
Owen Taylor committed
530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572
                      gtk_marshal_VOID__ENUM_INT,
                      GTK_TYPE_NONE, 2, GTK_TYPE_DELETE_TYPE, GTK_TYPE_INT);

  signals[CUT_CLIPBOARD] =
    gtk_signal_new ("cut_clipboard",
                    GTK_RUN_LAST | GTK_RUN_ACTION,
                    GTK_CLASS_TYPE (object_class),
                    GTK_SIGNAL_OFFSET (GtkEntryClass, cut_clipboard),
                    gtk_marshal_VOID__VOID,
                    GTK_TYPE_NONE, 0);

  signals[COPY_CLIPBOARD] =
    gtk_signal_new ("copy_clipboard",
                    GTK_RUN_LAST | GTK_RUN_ACTION,
                    GTK_CLASS_TYPE (object_class),
                    GTK_SIGNAL_OFFSET (GtkEntryClass, copy_clipboard),
                    gtk_marshal_VOID__VOID,
                    GTK_TYPE_NONE, 0);

  signals[PASTE_CLIPBOARD] =
    gtk_signal_new ("paste_clipboard",
                    GTK_RUN_LAST | GTK_RUN_ACTION,
                    GTK_CLASS_TYPE (object_class),
                    GTK_SIGNAL_OFFSET (GtkEntryClass, paste_clipboard),
                    gtk_marshal_VOID__VOID,
                    GTK_TYPE_NONE, 0);

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

  /*
   * Key bindings
   */

  binding_set = gtk_binding_set_by_class (class);

  /* Moving the insertion point */
  add_move_binding (binding_set, GDK_Right, 0,
573
		    GTK_MOVEMENT_VISUAL_POSITIONS, 1);
Owen Taylor's avatar
Owen Taylor committed
574 575
  
  add_move_binding (binding_set, GDK_Left, 0,
576
		    GTK_MOVEMENT_VISUAL_POSITIONS, -1);
Owen Taylor's avatar
Owen Taylor committed
577

578 579 580 581 582 583
  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
584
  add_move_binding (binding_set, GDK_f, GDK_CONTROL_MASK,
585
		    GTK_MOVEMENT_LOGICAL_POSITIONS, 1);
Owen Taylor's avatar
Owen Taylor committed
586 587
  
  add_move_binding (binding_set, GDK_b, GDK_CONTROL_MASK,
588
		    GTK_MOVEMENT_LOGICAL_POSITIONS, -1);
Owen Taylor's avatar
Owen Taylor committed
589 590 591 592 593 594
  
  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);
595 596 597 598 599 600

  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
601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618
  
  add_move_binding (binding_set, GDK_a, GDK_CONTROL_MASK,
		    GTK_MOVEMENT_PARAGRAPH_ENDS, -1);

  add_move_binding (binding_set, GDK_e, GDK_CONTROL_MASK,
		    GTK_MOVEMENT_PARAGRAPH_ENDS, 1);

  add_move_binding (binding_set, GDK_f, GDK_MOD1_MASK,
		    GTK_MOVEMENT_WORDS, 1);

  add_move_binding (binding_set, GDK_b, GDK_MOD1_MASK,
		    GTK_MOVEMENT_WORDS, -1);

  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);
619 620 621 622 623 624

  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
625 626 627 628 629 630 631
  
  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);

632 633 634 635 636 637 638 639 640 641 642 643 644 645
  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);

  /* Activate */

  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
646 647 648 649 650 651
  /* Deleting text */
  gtk_binding_entry_add_signal (binding_set, GDK_Delete, 0,
				"delete_from_cursor", 2,
				GTK_TYPE_ENUM, GTK_DELETE_CHARS,
				GTK_TYPE_INT, 1);

652 653 654 655 656
  gtk_binding_entry_add_signal (binding_set, GDK_KP_Delete, 0,
				"delete_from_cursor", 2,
				GTK_TYPE_ENUM, GTK_DELETE_CHARS,
				GTK_TYPE_INT, 1);
  
Owen Taylor's avatar
Owen Taylor committed
657 658 659 660 661 662 663 664 665 666 667 668 669 670 671
  gtk_binding_entry_add_signal (binding_set, GDK_d, GDK_CONTROL_MASK,
				"delete_from_cursor", 2,
				GTK_TYPE_ENUM, GTK_DELETE_CHARS,
				GTK_TYPE_INT, 1);

  gtk_binding_entry_add_signal (binding_set, GDK_BackSpace, 0,
				"delete_from_cursor", 2,
				GTK_TYPE_ENUM, GTK_DELETE_CHARS,
				GTK_TYPE_INT, -1);

  gtk_binding_entry_add_signal (binding_set, GDK_Delete, GDK_CONTROL_MASK,
				"delete_from_cursor", 2,
				GTK_TYPE_ENUM, GTK_DELETE_WORD_ENDS,
				GTK_TYPE_INT, 1);

672 673 674 675 676
  gtk_binding_entry_add_signal (binding_set, GDK_KP_Delete, GDK_CONTROL_MASK,
				"delete_from_cursor", 2,
				GTK_TYPE_ENUM, GTK_DELETE_WORD_ENDS,
				GTK_TYPE_INT, 1);
  
Owen Taylor's avatar
Owen Taylor committed
677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722
  gtk_binding_entry_add_signal (binding_set, GDK_d, GDK_MOD1_MASK,
				"delete_from_cursor", 2,
				GTK_TYPE_ENUM, GTK_DELETE_WORD_ENDS,
				GTK_TYPE_INT, 1);

  gtk_binding_entry_add_signal (binding_set, GDK_BackSpace, GDK_CONTROL_MASK,
				"delete_from_cursor", 2,
				GTK_TYPE_ENUM, GTK_DELETE_WORD_ENDS,
				GTK_TYPE_INT, -1);

  gtk_binding_entry_add_signal (binding_set, GDK_k, GDK_CONTROL_MASK,
				"delete_from_cursor", 2,
				GTK_TYPE_ENUM, GTK_DELETE_PARAGRAPH_ENDS,
				GTK_TYPE_INT, 1);

  gtk_binding_entry_add_signal (binding_set, GDK_u, GDK_CONTROL_MASK,
				"delete_from_cursor", 2,
				GTK_TYPE_ENUM, GTK_DELETE_PARAGRAPHS,
				GTK_TYPE_INT, 1);

  gtk_binding_entry_add_signal (binding_set, GDK_space, GDK_MOD1_MASK,
				"delete_from_cursor", 2,
				GTK_TYPE_ENUM, GTK_DELETE_WHITESPACE,
				GTK_TYPE_INT, 1);
  gtk_binding_entry_add_signal (binding_set, GDK_space, GDK_MOD1_MASK,
				"insert_at_cursor", 1,
				GTK_TYPE_STRING, " ");

  gtk_binding_entry_add_signal (binding_set, GDK_backslash, GDK_MOD1_MASK,
				"delete_from_cursor", 2,
				GTK_TYPE_ENUM, GTK_DELETE_WHITESPACE,
				GTK_TYPE_INT, 1);
  
  /* 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_w, 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
723

Owen Taylor's avatar
Owen Taylor committed
724 725 726 727 728 729 730
  gtk_binding_entry_add_signal (binding_set, GDK_y, GDK_CONTROL_MASK,
				"paste_clipboard", 0);

  /* Overwrite */
  gtk_binding_entry_add_signal (binding_set, GDK_Insert, 0,
				"toggle_overwrite", 0);
}
731

Owen Taylor's avatar
Owen Taylor committed
732 733 734 735 736 737 738 739 740 741
static void
gtk_entry_editable_init (GtkEditableClass *iface)
{
  iface->insert_text = gtk_entry_insert_text;
  iface->delete_text = gtk_entry_delete_text;
  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
742 743
}

744 745 746 747 748
static void
gtk_entry_set_property (GObject         *object,
                        guint            prop_id,
                        const GValue    *value,
                        GParamSpec      *pspec)
749
{
Owen Taylor's avatar
Owen Taylor committed
750
  GtkEntry *entry = GTK_ENTRY (object);
751

Havoc Pennington's avatar
Havoc Pennington committed
752
  switch (prop_id)
753
    {
Havoc Pennington's avatar
Havoc Pennington committed
754 755 756
    case PROP_TEXT_POSITION:
      gtk_editable_set_position (GTK_EDITABLE (object), 
				 g_value_get_int (value));
Owen Taylor's avatar
Owen Taylor committed
757
      break;
Havoc Pennington's avatar
Havoc Pennington committed
758 759

    case PROP_EDITABLE:
Owen Taylor's avatar
Owen Taylor committed
760
      {
Havoc Pennington's avatar
Havoc Pennington committed
761 762 763
        gboolean new_value = g_value_get_boolean (value);

      	if (new_value != entry->editable)
Owen Taylor's avatar
Owen Taylor committed
764 765 766 767 768 769
	  {
	    entry->editable = new_value;
	    gtk_entry_queue_draw (entry);
	  }
      }
      break;
Havoc Pennington's avatar
Havoc Pennington committed
770 771 772

    case PROP_MAX_LENGTH:
      gtk_entry_set_max_length (entry, g_value_get_int (value));
773
      break;
Havoc Pennington's avatar
Havoc Pennington committed
774 775 776
      
    case PROP_VISIBILITY:
      gtk_entry_set_visibility (entry, g_value_get_boolean (value));
777
      break;
Havoc Pennington's avatar
Havoc Pennington committed
778 779

    case PROP_INVISIBLE_CHAR:
780
      gtk_entry_set_invisible_char (entry, g_value_get_uint (value));
781
      break;
Havoc Pennington's avatar
Havoc Pennington committed
782

783 784 785
    case PROP_ACTIVATES_DEFAULT:
      gtk_entry_set_activates_default (entry, g_value_get_boolean (value));
      break;
786 787 788 789

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

    case PROP_SCROLL_OFFSET:
792
    default:
Havoc Pennington's avatar
Havoc Pennington committed
793
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
794 795 796 797
      break;
    }
}

798 799 800 801 802
static void
gtk_entry_get_property (GObject         *object,
                        guint            prop_id,
                        GValue          *value,
                        GParamSpec      *pspec)
803 804 805 806 807
{
  GtkEntry *entry;

  entry = GTK_ENTRY (object);

Havoc Pennington's avatar
Havoc Pennington committed
808
  switch (prop_id)
809
    {
Havoc Pennington's avatar
Havoc Pennington committed
810 811
    case PROP_TEXT_POSITION:
      g_value_set_int (value, entry->current_pos);
Owen Taylor's avatar
Owen Taylor committed
812
      break;
Havoc Pennington's avatar
Havoc Pennington committed
813 814
    case PROP_EDITABLE:
      g_value_set_boolean (value, entry->editable);
Owen Taylor's avatar
Owen Taylor committed
815
      break;
Havoc Pennington's avatar
Havoc Pennington committed
816 817
    case PROP_MAX_LENGTH:
      g_value_set_int (value, entry->text_max_length); 
818
      break;
Havoc Pennington's avatar
Havoc Pennington committed
819 820
    case PROP_VISIBILITY:
      g_value_set_boolean (value, entry->visible);
821
      break;
Havoc Pennington's avatar
Havoc Pennington committed
822
    case PROP_INVISIBLE_CHAR:
823
      g_value_set_uint (value, entry->invisible_char);
824
      break;
825 826 827
    case PROP_ACTIVATES_DEFAULT:
      g_value_set_boolean (value, entry->activates_default);
      break;
828 829 830
    case PROP_WIDTH_CHARS:
      g_value_set_int (value, entry->width_chars);
      break;
831 832 833
    case PROP_SCROLL_OFFSET:
      g_value_set_int (value, entry->scroll_offset);
      break;
834
      
835
    default:
Havoc Pennington's avatar
Havoc Pennington committed
836
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
837 838 839 840
      break;
    }
}

Elliot Lee's avatar
Elliot Lee committed
841 842 843 844 845
static void
gtk_entry_init (GtkEntry *entry)
{
  GTK_WIDGET_SET_FLAGS (entry, GTK_CAN_FOCUS);

846 847 848
  entry->text_size = MIN_SIZE;
  entry->text = g_malloc (entry->text_size);
  entry->text[0] = '\0';
Owen Taylor's avatar
Owen Taylor committed
849 850 851

  entry->editable = TRUE;
  entry->visible = TRUE;
852
  entry->invisible_char = '*';
Owen Taylor's avatar
Owen Taylor committed
853
  entry->dnd_position = -1;
854 855
  entry->width_chars = -1;
  
Havoc Pennington's avatar
Havoc Pennington committed
856
  entry->has_frame = TRUE;
857
  
Owen Taylor's avatar
Owen Taylor committed
858 859 860 861 862
  gtk_drag_dest_set (GTK_WIDGET (entry),
                     GTK_DEST_DEFAULT_DROP | GTK_DEST_DEFAULT_HIGHLIGHT,
                     target_table, G_N_ELEMENTS (target_table),
                     GDK_ACTION_COPY | GDK_ACTION_MOVE);

863 864 865 866 867 868 869
  /* 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 ();
  
  gtk_signal_connect (GTK_OBJECT (entry->im_context), "commit",
		      GTK_SIGNAL_FUNC (gtk_entry_commit_cb), entry);
Owen Taylor's avatar
Owen Taylor committed
870 871
  gtk_signal_connect (GTK_OBJECT (entry->im_context), "preedit_changed",
		      GTK_SIGNAL_FUNC (gtk_entry_preedit_changed_cb), entry);
Elliot Lee's avatar
Elliot Lee committed
872 873 874
}

static void
875
gtk_entry_finalize (GObject *object)
Elliot Lee's avatar
Elliot Lee committed
876 877 878 879 880 881 882
{
  GtkEntry *entry;

  g_return_if_fail (GTK_IS_ENTRY (object));

  entry = GTK_ENTRY (object);

Owen Taylor's avatar
Owen Taylor committed
883 884
  if (entry->cached_layout)
    g_object_unref (G_OBJECT (entry->cached_layout));
Owen Taylor's avatar
Owen Taylor committed
885

886 887
  gtk_object_unref (GTK_OBJECT (entry->im_context));

888 889
  if (entry->blink_timeout)
    g_source_remove (entry->blink_timeout);
Owen Taylor's avatar
Owen Taylor committed
890 891 892

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

894
  entry->text_size = 0;
895

Elliot Lee's avatar
Elliot Lee committed
896 897 898 899
  if (entry->text)
    g_free (entry->text);
  entry->text = NULL;

900
  G_OBJECT_CLASS (parent_class)->finalize (object);
Elliot Lee's avatar
Elliot Lee committed
901 902
}

903 904 905 906 907 908 909 910 911 912 913 914 915 916 917
static void
gtk_entry_realize_cursor_gc (GtkEntry *entry)
{
  GdkColor *cursor_color;
  
  if (entry->cursor_gc)
    gdk_gc_unref (entry->cursor_gc);

  gtk_widget_style_get (GTK_WIDGET (entry), "cursor_color", &cursor_color, NULL);
  if (cursor_color)
    {
      entry->cursor_gc = gdk_gc_new (entry->text_area);
      gdk_gc_set_rgb_fg_color (entry->cursor_gc, cursor_color);
    }
  else
Havoc Pennington's avatar
Havoc Pennington committed
918
    entry->cursor_gc = gdk_gc_ref (GTK_WIDGET (entry)->style->base_gc[GTK_STATE_SELECTED]);
919 920
}

Elliot Lee's avatar
Elliot Lee committed
921 922 923 924
static void
gtk_entry_realize (GtkWidget *widget)
{
  GtkEntry *entry;
925
  GtkEditable *editable;
926
  GtkRequisition requisition;
Elliot Lee's avatar
Elliot Lee committed
927 928 929 930 931 932 933 934
  GdkWindowAttr attributes;
  gint attributes_mask;

  g_return_if_fail (widget != NULL);
  g_return_if_fail (GTK_IS_ENTRY (widget));

  GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
  entry = GTK_ENTRY (widget);
935
  editable = GTK_EDITABLE (widget);
936 937

  gtk_widget_get_child_requisition (widget, &requisition);
938
  
Elliot Lee's avatar
Elliot Lee committed
939 940
  attributes.window_type = GDK_WINDOW_CHILD;
  attributes.x = widget->allocation.x;
941
  attributes.y = widget->allocation.y + (widget->allocation.height -
942
					 requisition.height) / 2;
Elliot Lee's avatar
Elliot Lee committed
943
  attributes.width = widget->allocation.width;
944
  attributes.height = requisition.height;
Elliot Lee's avatar
Elliot Lee committed
945 946 947 948 949 950 951 952 953
  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 |
954 955 956
			    GDK_POINTER_MOTION_HINT_MASK |
                            GDK_ENTER_NOTIFY_MASK |
			    GDK_LEAVE_NOTIFY_MASK);
Elliot Lee's avatar
Elliot Lee committed
957 958
  attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;

959
  widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
Elliot Lee's avatar
Elliot Lee committed
960 961
  gdk_window_set_user_data (widget->window, entry);

Havoc Pennington's avatar
Havoc Pennington committed
962 963 964 965 966 967 968 969 970 971 972
  if (entry->has_frame)
    {
      attributes.x = widget->style->xthickness;
      attributes.y = widget->style->ythickness;
    }
  else
    {
      attributes.x = 0;
      attributes.y = 0;
    }
  
Elliot Lee's avatar
Elliot Lee committed
973
  attributes.width = widget->allocation.width - attributes.x * 2;
974
  attributes.height = requisition.height - attributes.y * 2;
Owen Taylor's avatar
Owen Taylor committed
975
  attributes.cursor = gdk_cursor_new (GDK_XTERM);
976
  attributes_mask |= GDK_WA_CURSOR;
Elliot Lee's avatar
Elliot Lee committed
977 978 979 980

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

981
  gdk_cursor_destroy (attributes.cursor);
982

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

985 986
  gtk_entry_realize_cursor_gc (entry);

987 988
  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
989 990

  gdk_window_show (entry->text_area);
991

992
  gtk_im_context_set_client_window (entry->im_context, entry->text_area);
993

Owen Taylor's avatar
Owen Taylor committed
994
  gtk_entry_adjust_scroll (entry);
Elliot Lee's avatar
Elliot Lee committed
995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006
}

static void
gtk_entry_unrealize (GtkWidget *widget)
{
  GtkEntry *entry;

  g_return_if_fail (widget != NULL);
  g_return_if_fail (GTK_IS_ENTRY (widget));

  entry = GTK_ENTRY (widget);

1007 1008
  gtk_im_context_set_client_window (entry->im_context, entry->text_area);
  
Elliot Lee's avatar
Elliot Lee committed
1009 1010 1011 1012
  if (entry->text_area)
    {
      gdk_window_set_user_data (entry->text_area, NULL);
      gdk_window_destroy (entry->text_area);
1013
      entry->text_area = NULL;
Elliot Lee's avatar
Elliot Lee committed
1014
    }
1015

1016 1017 1018 1019 1020 1021
  if (entry->cursor_gc)
    {
      gdk_gc_unref (entry->cursor_gc);
      entry->cursor_gc = NULL;
    }

Owen Taylor's avatar
Owen Taylor committed
1022
  if (entry->popup_menu)
1023 1024 1025 1026
    {
      gtk_widget_destroy (entry->popup_menu);
      entry->popup_menu = NULL;
    }
Owen Taylor's avatar
Owen Taylor committed
1027

1028 1029
  if (GTK_WIDGET_CLASS (parent_class)->unrealize)
    (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
Elliot Lee's avatar
Elliot Lee committed
1030 1031 1032 1033 1034 1035
}

static void
gtk_entry_size_request (GtkWidget      *widget,
			GtkRequisition *requisition)
{
1036 1037 1038
  GtkEntry *entry;
  PangoFontMetrics metrics;
  PangoFont *font;
Havoc Pennington's avatar
Havoc Pennington committed
1039
  gint xborder, yborder;
1040
  PangoContext *context;
1041
  
Elliot Lee's avatar
Elliot Lee committed
1042 1043 1044 1045
  g_return_if_fail (widget != NULL);
  g_return_if_fail (GTK_IS_ENTRY (widget));
  g_return_if_fail (requisition != NULL);

1046
  entry = GTK_ENTRY (widget);
1047
  
1048 1049
  /* hackish for now, get metrics
   */
1050 1051 1052 1053 1054
  context = gtk_widget_get_pango_context (widget);
  font = pango_context_load_font (context, widget->style->font_desc);
  pango_font_get_metrics (font,
			  pango_context_get_language (context),
			  &metrics);
1055 1056 1057 1058
  
  g_object_unref (G_OBJECT (font));

  entry->ascent = metrics.ascent;
1059
  entry->descent = metrics.descent;
Havoc Pennington's avatar
Havoc Pennington committed
1060 1061 1062

  xborder = INNER_BORDER;
  yborder = INNER_BORDER;
1063
  
Havoc Pennington's avatar
Havoc Pennington committed
1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074
  if (entry->has_frame)
    {
      xborder += widget->style->xthickness;
      yborder += widget->style->ythickness;
    }
  else
    {
      /* add 1 pixel to draw focus rect in widget->window */
      xborder += 1;
      yborder += 1;
    }
1075 1076 1077 1078 1079 1080 1081 1082 1083 1084

  if (entry->width_chars < 0)
    requisition->width = MIN_ENTRY_WIDTH + xborder * 2;
  else
    {
      requisition->width =
        PANGO_PIXELS (metrics.approximate_char_width) * entry->width_chars +
        xborder * 2;
    }
    
1085
  requisition->height = ((metrics.ascent + metrics.descent) / PANGO_SCALE + 
Havoc Pennington's avatar
Havoc Pennington committed
1086
                         yborder * 2);
Elliot Lee's avatar
Elliot Lee committed
1087 1088
}

1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171
static void
get_borders (GtkEntry *entry,
             gint     *xborder,
             gint     *yborder)
{
  GtkWidget *widget;

  widget = GTK_WIDGET (entry);
  
  if (entry->has_frame)
    {
      if (xborder)
        *xborder = widget->style->xthickness;
      if (yborder)
        *yborder = widget->style->ythickness;
    }
  else
    {
      /* 1 pixel for focus rect */
      if (xborder)
        *xborder = 1;
      if (yborder)
        *yborder = 1;
    }
}

static void
get_text_area_size (GtkEntry *entry,
                    gint     *x,
                    gint     *y,
                    gint     *width,
                    gint     *height)
{
  gint xborder, yborder;
  GtkRequisition requisition;
  GtkWidget *widget;

  widget = GTK_WIDGET (entry);
  
  gtk_widget_get_child_requisition (widget, &requisition);

  get_borders (entry, &xborder, &yborder);

  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;
  GtkWidget *widget;  

  widget = GTK_WIDGET (entry);
      
  gtk_widget_get_child_requisition (widget, &requisition);

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

  if (y)
    *y = widget->allocation.y + (widget->allocation.height - requisition.height) / 2;

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

  if (height)
    *height = requisition.height;
}

Elliot Lee's avatar
Elliot Lee committed
1172 1173 1174 1175 1176
static void
gtk_entry_size_allocate (GtkWidget     *widget,
			 GtkAllocation *allocation)
{
  GtkEntry *entry;
1177
  GtkEditable *editable;
Havoc Pennington's avatar
Havoc Pennington committed
1178
  
Elliot Lee's avatar
Elliot Lee committed
1179 1180 1181 1182 1183 1184
  g_return_if_fail (widget != NULL);
  g_return_if_fail (GTK_IS_ENTRY (widget));
  g_return_if_fail (allocation != NULL);

  widget->allocation = *allocation;
  entry = GTK_ENTRY (widget);
1185
  editable = GTK_EDITABLE (widget);
Havoc Pennington's avatar
Havoc Pennington committed
1186
  
Elliot Lee's avatar
Elliot Lee committed
1187 1188
  if (GTK_WIDGET_REALIZED (widget))
    {
1189 1190 1191 1192
      /* 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
       */
1193 1194 1195 1196
      gint x, y, width, height;

      get_widget_window_size (entry, &x, &y, &width, &height);
      
Elliot Lee's avatar
Elliot Lee committed
1197
      gdk_window_move_resize (widget->window,
1198 1199 1200 1201
                              x, y, width, height);   

      get_text_area_size (entry, &x, &y, &width, &height);
      
Elliot Lee's avatar
Elliot Lee committed
1202
      gdk_window_move_resize (entry->text_area,
1203
                              x, y, width, height);
Elliot Lee's avatar
Elliot Lee committed
1204

Owen Taylor's avatar
Owen Taylor committed
1205
      gtk_entry_recompute (entry);
Elliot Lee's avatar
Elliot Lee committed
1206 1207 1208
    }
}

Owen Taylor's avatar
Owen Taylor committed
1209 1210
static void
gtk_entry_draw_focus (GtkWidget *widget)
Elliot Lee's avatar
Elliot Lee committed
1211
{
Owen Taylor's avatar
Owen Taylor committed
1212
  gint width, height;
Havoc Pennington's avatar
Havoc Pennington committed
1213
  GtkEntry *entry;
1214
  gboolean interior_focus;
Havoc Pennington's avatar
Havoc Pennington committed
1215
  
Owen Taylor's avatar
Owen Taylor committed
1216 1217
  g_return_if_fail (widget != NULL);
  g_return_if_fail (GTK_IS_ENTRY (widget));
Elliot Lee's avatar
Elliot Lee committed
1218

1219 1220
  gtk_widget_style_get (widget, "interior_focus", &interior_focus, NULL);

Havoc Pennington's avatar
Havoc Pennington committed
1221 1222
  entry = GTK_ENTRY (widget);
  
Owen Taylor's avatar
Owen Taylor committed
1223
  if (GTK_WIDGET_DRAWABLE (widget))
Havoc Pennington's avatar
Havoc Pennington committed
1224 1225 1226 1227
    {      
      if (entry->has_frame)
        {
          gint x = 0, y = 0;
Elliot Lee's avatar
Elliot Lee committed
1228

Havoc Pennington's avatar
Havoc Pennington committed
1229 1230
          gdk_window_get_size (widget->window, &width, &height);

1231
          if (GTK_WIDGET_HAS_FOCUS (widget) && !interior_focus)
Havoc Pennington's avatar
Havoc Pennington committed
1232 1233 1234 1235 1236 1237
            {
              x += 1;
              y += 1;
              width -= 2;
              height -= 2;
            }
Elliot Lee's avatar
Elliot Lee committed
1238

Havoc Pennington's avatar
Havoc Pennington committed
1239 1240 1241 1242 1243 1244 1245 1246
          gtk_paint_shadow (widget->style, widget->window,
                            GTK_STATE_NORMAL, GTK_SHADOW_IN,
                            NULL, widget, "entry",
                            x, y, width, height);
        }
      else
        gdk_window_clear (widget->window);
        
1247
      if (GTK_WIDGET_HAS_FOCUS (widget) && !interior_focus)
Havoc Pennington's avatar
Havoc Pennington committed
1248 1249 1250 1251 1252 1253
        {
          gdk_window_get_size (widget->window, &width, &height);
          gtk_paint_focus (widget->style, widget->window, 
                           NULL, widget, "entry",
                           0, 0, width - 1, height - 1);
        }
Owen Taylor's avatar
Owen Taylor committed
1254 1255 1256 1257 1258 1259
    }
}

static gint
gtk_entry_expose (GtkWidget      *widget,
		  GdkEventExpose *event)
Elliot Lee's avatar
Elliot Lee committed
1260 1261 1262 1263 1264 1265 1266
{
  GtkEntry *entry;

  g_return_val_if_fail (widget != NULL, FALSE);
  g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE);
  g_return_val_if_fail (event != NULL, FALSE);

Owen Taylor's avatar
Owen Taylor committed
1267 1268 1269
  entry = GTK_ENTRY (widget);

  if (widget->window == event->window)
1270
    gtk_entry_draw_focus (widget);
Owen Taylor's avatar
Owen Taylor committed
1271 1272 1273
  else if (entry->text_area == event->window)
    {
      gtk_entry_draw_text (GTK_ENTRY (widget));
Owen Taylor's avatar
Owen Taylor committed
1274 1275 1276

      if ((entry->visible || entry->invisible_char != 0) &&
	  GTK_WIDGET_HAS_FOCUS (widget) &&
1277
	  entry->selection_bound == entry->current_pos && entry->cursor_visible)
Owen Taylor's avatar
Owen Taylor committed
1278 1279 1280 1281
	gtk_entry_draw_cursor (GTK_ENTRY (widget), CURSOR_STANDARD);

      if (entry->dnd_position != -1)
	gtk_entry_draw_cursor (GTK_ENTRY (widget), CURSOR_DND);
Owen Taylor's avatar
Owen Taylor committed
1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293
    }

  return FALSE;
}

static gint
gtk_entry_button_press (GtkWidget      *widget,
			GdkEventButton *event)
{
  GtkEntry *entry = GTK_ENTRY (widget);
  GtkEditable *editable = GTK_EDITABLE (widget);
  gint tmp_pos;
Owen Taylor's avatar
Owen Taylor committed
1294
  gint sel_start, sel_end;
1295

Elliot Lee's avatar
Elliot Lee committed
1296
  entry = GTK_ENTRY (widget);
1297 1298
  editable = GTK_EDITABLE (widget);
  
Owen Taylor's avatar
Owen Taylor committed
1299 1300
  if (event->window != entry->text_area ||
      (entry->button && event->button != entry->button))
1301
    return FALSE;