static const GtkBorder default_inner_border = { 2, 2, 2, 2 };
static GQuark quark_inner_border = 0;
static GQuark quark_password_hint = 0;
+static GQuark quark_cursor_hadjustment = 0;
typedef struct _GtkEntryPrivate GtkEntryPrivate;
gfloat xalign;
gint insert_pos;
guint blink_time; /* time in msec the cursor has blinked since last user event */
- guint real_changed : 1;
- guint change_count : 8;
+ guint interior_focus : 1;
+ guint real_changed : 1;
+ guint change_count : 8;
gint focus_width;
- gboolean interior_focus;
GtkShadowType shadow_type;
-
- GtkAdjustment *cursor_hadjustment;
};
typedef struct _GtkEntryPasswordHint GtkEntryPasswordHint;
quark_inner_border = g_quark_from_static_string ("gtk-entry-inner-border");
quark_password_hint = g_quark_from_static_string ("gtk-entry-password-hint");
+ quark_cursor_hadjustment = g_quark_from_static_string ("gtk-hadjustment");
g_object_class_install_property (gobject_class,
PROP_CURSOR_POSITION,
/**
* GtkEntry:shadow-type:
*
- * Which kind of shadow to draw around the entry when has-frame is set.
+ * Which kind of shadow to draw around the entry when
+ * #GtkEntry:has-frame is set to %TRUE.
*
* Since: 2.12
*/
/**
* GtkEntry:inner-border:
*
- * Sets the text area's border between the text and the frame
+ * Sets the text area's border between the text and the frame.
*
* Since: 2.10
*/
/**
* GtkSettings:gtk-entry-password-hint-timeout:
*
- * How long to show the last inputted character in hidden
+ * How long to show the last input character in hidden
* entries. This value is in milliseconds. 0 disables showing the
* last char. 600 is a good value for enabling it.
*
*/
gtk_settings_install_property (g_param_spec_uint ("gtk-entry-password-hint-timeout",
P_("Password Hint Timeout"),
- P_("How long to show the last inputted character in hidden entries"),
+ P_("How long to show the last input character in hidden entries"),
0, G_MAXUINT, 0,
GTK_PARAM_READWRITE));
GTK_WIDGET_STATE(widget), GTK_SHADOW_NONE,
&event->area, widget, "entry_bg",
0, 0, area_width, area_height);
-
- if ((entry->visible || entry->invisible_char != 0) &&
- GTK_WIDGET_HAS_FOCUS (widget) &&
- entry->selection_bound == entry->current_pos && entry->cursor_visible)
- gtk_entry_draw_cursor (GTK_ENTRY (widget), CURSOR_STANDARD);
if (entry->dnd_position != -1)
gtk_entry_draw_cursor (GTK_ENTRY (widget), CURSOR_DND);
gtk_entry_draw_text (GTK_ENTRY (widget));
+
+ if ((entry->visible || entry->invisible_char != 0) &&
+ GTK_WIDGET_HAS_FOCUS (widget) &&
+ entry->selection_bound == entry->current_pos && entry->cursor_visible)
+ gtk_entry_draw_cursor (GTK_ENTRY (widget), CURSOR_STANDARD);
}
return FALSE;
{
GtkEntry *entry = GTK_ENTRY (widget);
GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (entry);
+ gint focus_width;
+ gboolean interior_focus;
gtk_widget_style_get (widget,
- "focus-line-width", &priv->focus_width,
- "interior-focus", &priv->interior_focus,
+ "focus-line-width", &focus_width,
+ "interior-focus", &interior_focus,
NULL);
+
+ priv->focus_width = focus_width;
+ priv->interior_focus = interior_focus;
gtk_entry_recompute (entry);
gtk_entry_toggle_overwrite (GtkEntry *entry)
{
entry->overwrite_mode = !entry->overwrite_mode;
+ gtk_entry_pend_cursor_blink (entry);
+ gtk_widget_queue_draw (GTK_WIDGET (entry));
}
static void
entry->text_length -
password_hint->password_hint_position);
- /* Now remove this last inputted character, don't need
+ /* Now remove this last input character, don't need
* it anymore
*/
memset (password_hint->password_hint, 0, PASSWORD_HINT_MAX);
GtkWidget *widget = GTK_WIDGET (entry);
GdkRectangle cursor_location;
gboolean split_cursor;
-
+ PangoRectangle cursor_rect;
GtkBorder inner_border;
gint xoffset;
- gint strong_x, weak_x;
gint text_area_height;
- PangoDirection dir1 = PANGO_DIRECTION_NEUTRAL;
- PangoDirection dir2 = PANGO_DIRECTION_NEUTRAL;
- gint x1 = 0;
- gint x2 = 0;
+ gint cursor_index;
+ gboolean block;
+ gboolean block_at_line_end;
_gtk_entry_effective_inner_border (entry, &inner_border);
xoffset = inner_border.left - entry->scroll_offset;
gdk_drawable_get_size (entry->text_area, NULL, &text_area_height);
-
- gtk_entry_get_cursor_locations (entry, type, &strong_x, &weak_x);
- g_object_get (gtk_widget_get_settings (widget),
- "gtk-split-cursor", &split_cursor,
- NULL);
+ cursor_index = g_utf8_offset_to_pointer (entry->text, entry->current_pos + entry->preedit_cursor) - entry->text;
+ if (!entry->overwrite_mode)
+ block = FALSE;
+ else
+ block = _gtk_text_util_get_block_cursor_location (gtk_entry_ensure_layout (entry, TRUE),
+ cursor_index, &cursor_rect, &block_at_line_end);
+
+ if (!block)
+ {
+ gint strong_x, weak_x;
+ PangoDirection dir1 = PANGO_DIRECTION_NEUTRAL;
+ PangoDirection dir2 = PANGO_DIRECTION_NEUTRAL;
+ gint x1 = 0;
+ gint x2 = 0;
+
+ gtk_entry_get_cursor_locations (entry, type, &strong_x, &weak_x);
+
+ g_object_get (gtk_widget_get_settings (widget),
+ "gtk-split-cursor", &split_cursor,
+ NULL);
- dir1 = entry->resolved_dir;
+ dir1 = entry->resolved_dir;
- if (split_cursor)
- {
- x1 = strong_x;
+ if (split_cursor)
+ {
+ x1 = strong_x;
- if (weak_x != strong_x)
- {
- dir2 = (entry->resolved_dir == PANGO_DIRECTION_LTR) ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR;
- x2 = weak_x;
- }
- }
- else
- {
- if (keymap_direction == entry->resolved_dir)
- x1 = strong_x;
- else
- x1 = weak_x;
- }
+ if (weak_x != strong_x)
+ {
+ dir2 = (entry->resolved_dir == PANGO_DIRECTION_LTR) ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR;
+ x2 = weak_x;
+ }
+ }
+ else
+ {
+ if (keymap_direction == entry->resolved_dir)
+ x1 = strong_x;
+ else
+ x1 = weak_x;
+ }
- cursor_location.x = xoffset + x1;
- cursor_location.y = inner_border.top;
- cursor_location.width = 0;
- cursor_location.height = text_area_height - inner_border.top - inner_border.bottom;
+ cursor_location.x = xoffset + x1;
+ cursor_location.y = inner_border.top;
+ cursor_location.width = 0;
+ cursor_location.height = text_area_height - inner_border.top - inner_border.bottom;
- draw_insertion_cursor (entry,
- &cursor_location, TRUE, dir1,
- dir2 != PANGO_DIRECTION_NEUTRAL);
+ draw_insertion_cursor (entry,
+ &cursor_location, TRUE, dir1,
+ dir2 != PANGO_DIRECTION_NEUTRAL);
- if (dir2 != PANGO_DIRECTION_NEUTRAL)
- {
- cursor_location.x = xoffset + x2;
- draw_insertion_cursor (entry,
- &cursor_location, FALSE, dir2,
- TRUE);
- }
+ if (dir2 != PANGO_DIRECTION_NEUTRAL)
+ {
+ cursor_location.x = xoffset + x2;
+ draw_insertion_cursor (entry,
+ &cursor_location, FALSE, dir2,
+ TRUE);
+ }
+ }
+ else /* overwrite_mode */
+ {
+ PangoLayout *layout = gtk_entry_ensure_layout (entry, TRUE);
+ GdkColor cursor_color;
+ GdkRectangle rect;
+ cairo_t *cr;
+ gint x, y;
+
+ get_layout_position (entry, &x, &y);
+
+ rect.x = PANGO_PIXELS (cursor_rect.x) + x;
+ rect.y = PANGO_PIXELS (cursor_rect.y) + y;
+ rect.width = PANGO_PIXELS (cursor_rect.width);
+ rect.height = PANGO_PIXELS (cursor_rect.height);
+
+ cr = gdk_cairo_create (entry->text_area);
+
+ _gtk_widget_get_cursor_color (widget, &cursor_color);
+ gdk_cairo_set_source_color (cr, &cursor_color);
+ gdk_cairo_rectangle (cr, &rect);
+ cairo_fill (cr);
+
+ if (!block_at_line_end)
+ {
+ gdk_cairo_rectangle (cr, &rect);
+ cairo_clip (cr);
+ cairo_move_to (cr, x, y);
+ gdk_cairo_set_source_color (cr, &widget->style->base[widget->state]);
+ pango_cairo_show_layout (cr, layout);
+ }
+
+ cairo_destroy (cr);
+ }
}
}
static void
gtk_entry_move_adjustments (GtkEntry *entry)
{
- GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (entry);
PangoContext *context;
PangoFontMetrics *metrics;
gint x, layout_x, border_x, border_y;
gint char_width;
+ GtkAdjustment *adjustment;
- if (!priv->cursor_hadjustment)
+ adjustment = g_object_get_qdata (G_OBJECT (entry), quark_cursor_hadjustment);
+ if (!adjustment)
return;
/* Cursor position, layout offset, border width, and widget allocation */
char_width = pango_font_metrics_get_approximate_char_width (metrics) / PANGO_SCALE;
/* Scroll it */
- gtk_adjustment_clamp_page (priv->cursor_hadjustment,
+ gtk_adjustment_clamp_page (adjustment,
x - (char_width + 1), /* one char + one pixel before */
x + (char_width + 2)); /* one char + cursor + one pixel after */
}
return GTK_WIDGET (entry);
}
+/**
+ * gtk_entry_set_text:
+ * @entry: a #GtkEntry
+ * @text: the new text
+ *
+ * Sets the text in the widget to the given
+ * value, replacing the current contents.
+ */
void
gtk_entry_set_text (GtkEntry *entry,
const gchar *text)
g_signal_handler_unblock (entry, completion->priv->changed_id);
}
+/**
+ * gtk_entry_append_text:
+ * @entry: a #GtkEntry
+ * @text: the text to append
+ *
+ * Appends the given text to the contents of the widget.
+ *
+ * Deprecated: gtk_entry_append_text() is deprecated and should not
+ * be used in newly-written code. Use gtk_editable_insert_text()
+ * instead.
+ */
void
gtk_entry_append_text (GtkEntry *entry,
const gchar *text)
gtk_editable_insert_text (GTK_EDITABLE (entry), text, -1, &tmp_pos);
}
+/**
+ * gtk_entry_prepend_text:
+ * @entry: a #GtkEntry
+ * @text: the text to prepend
+ *
+ * Prepends the given text to the contents of the widget.
+ *
+ * Deprecated: gtk_entry_prepend_text() is deprecated and should not
+ * be used in newly-written code. Use gtk_editable_insert_text()
+ * instead.
+ */
void
gtk_entry_prepend_text (GtkEntry *entry,
const gchar *text)
gtk_editable_insert_text (GTK_EDITABLE (entry), text, -1, &tmp_pos);
}
+/**
+ * gtk_entry_set_position:
+ * @entry: a #GtkEntry
+ * @position: the position of the cursor. The cursor is displayed
+ * before the character with the given (base 0) index in the widget.
+ * The value must be less than or equal to the number of characters
+ * in the widget. A value of -1 indicates that the position should
+ * be set after the last character in the entry. Note that this
+ * position is in characters, not in bytes.
+ *
+ * Sets the cursor position in an entry to the given value.
+ *
+ * Deprecated: Use gtk_editable_set_position() instead.
+ */
void
gtk_entry_set_position (GtkEntry *entry,
gint position)
gtk_editable_set_position (GTK_EDITABLE (entry), position);
}
+/**
+ * gtk_entry_set_visibility:
+ * @entry: a #GtkEntry
+ * @visible: %TRUE if the contents of the entry are displayed
+ * as plaintext
+ *
+ * Sets whether the contents of the entry are visible or not.
+ * When visibility is set to %FALSE, characters are displayed
+ * as the invisible char, and will also appear that way when
+ * the text in the entry widget is copied elsewhere.
+ *
+ * The default invisible char is the asterisk '*', but it can
+ * be changed with gtk_entry_set_invisible_char().
+ */
void
gtk_entry_set_visibility (GtkEntry *entry,
gboolean visible)
* invisible char is an asterisk ('*'). If you set the invisible char
* to 0, then the user will get no feedback at all; there will be
* no text on the screen as they type.
- *
**/
void
gtk_entry_set_invisible_char (GtkEntry *entry,
* @entry: a #GtkEntry
*
* Retrieves the character displayed in place of the real characters
- * for entries with visisbility set to false. See gtk_entry_set_invisible_char().
+ * for entries with visibility set to false. See gtk_entry_set_invisible_char().
*
* Return value: the current invisible char, or 0, if the entry does not
* show invisible text at all.
return entry->invisible_char;
}
+/**
+ * gtk_entry_set_editable:
+ * @entry: a #GtkEntry
+ * @editable: %TRUE if the user is allowed to edit the text
+ * in the widget
+ *
+ * Determines if the user can edit the text in the editable
+ * widget or not.
+ *
+ * Deprecated: Use gtk_editable_set_editable() instead.
+ */
void
gtk_entry_set_editable (GtkEntry *entry,
gboolean editable)
* See also gtk_editable_get_chars().
*
* Return value: a pointer to the contents of the widget as a
- * string. This string points to internally allocated
+ * string. This string points to internally allocated
* storage in the widget and must not be freed, modified or
* stored.
**/
return entry->text;
}
+/**
+ * gtk_entry_select_region:
+ * @entry: a #GtkEntry
+ * @start: the starting position
+ * @end: the end position
+ *
+ * Selects a region of text. The characters that are selected are
+ * those characters at positions from @start_pos up to, but not
+ * including @end_pos. If @end_pos is negative, then the the characters
+ * selected will be those characters from @start_pos to the end of
+ * the text.
+ *
+ * Deprecated: Use gtk_editable_select_region() instead.
+ */
void
gtk_entry_select_region (GtkEntry *entry,
gint start,
/**
* gtk_entry_set_max_length:
- * @entry: a #GtkEntry.
+ * @entry: a #GtkEntry
* @max: the maximum length of the entry, or 0 for no maximum.
* (other than the maximum length of entries.) The value passed in will
* be clamped to the range 0-65536.
*
* (For experts: if @setting is %TRUE, the entry calls
* gtk_window_activate_default() on the window containing the entry, in
- * the default handler for the "activate" signal.)
- *
+ * the default handler for the #GtkWidget::activate signal.)
**/
void
gtk_entry_set_activates_default (GtkEntry *entry,
* <emphasis>request</emphasis>, the size can still be affected by
* how you pack the widget into containers. If @n_chars is -1, the
* size reverts to the default entry size.
- *
**/
void
gtk_entry_set_width_chars (GtkEntry *entry,
* gtk_entry_get_inner_border:
* @entry: a #GtkEntry
*
- * This function returns the entry's inner-border property. See
+ * This function returns the entry's #GtkEntry:inner-border property. See
* gtk_entry_set_inner_border() for more information.
*
* Return value: the entry's #GtkBorder, or %NULL if none was set.
* gtk_entry_layout_index_to_text_index() and
* gtk_entry_text_index_to_layout_index() are needed to convert byte
* indices in the layout to byte indices in the entry contents.
- *
**/
void
gtk_entry_get_layout_offsets (GtkEntry *entry,
{
gtk_tree_selection_unselect_all (gtk_tree_view_get_selection (GTK_TREE_VIEW (completion->priv->tree_view)));
gtk_tree_selection_unselect_all (gtk_tree_view_get_selection (GTK_TREE_VIEW (completion->priv->action_view)));
+
+ if (completion->priv->inline_selection &&
+ completion->priv->completion_prefix)
+ {
+ gtk_entry_set_text (GTK_ENTRY (completion->priv->entry),
+ completion->priv->completion_prefix);
+ gtk_editable_set_position (GTK_EDITABLE (widget), -1);
+ }
}
else if (completion->priv->current_selected < matches)
{
return FALSE;
if (completion->priv->completion_prefix == NULL)
- {
- completion->priv->completion_prefix = g_strdup (gtk_entry_get_text (GTK_ENTRY (completion->priv->entry)));
- }
-
+ completion->priv->completion_prefix = g_strdup (gtk_entry_get_text (GTK_ENTRY (completion->priv->entry)));
+
g_signal_emit_by_name (completion, "cursor_on_match", model,
&iter, &entry_set);
}
path = gtk_tree_path_new_from_indices (completion->priv->current_selected - matches, -1);
gtk_tree_view_set_cursor (GTK_TREE_VIEW (completion->priv->action_view),
path, NULL, FALSE);
+
+ if (completion->priv->inline_selection &&
+ completion->priv->completion_prefix)
+ {
+ gtk_entry_set_text (GTK_ENTRY (completion->priv->entry),
+ completion->priv->completion_prefix);
+ gtk_editable_set_position (GTK_EDITABLE (widget), -1);
+ }
}
gtk_tree_path_free (path);
event->keyval == GDK_Right ||
event->keyval == GDK_KP_Right)
{
+ gboolean retval = TRUE;
+
_gtk_entry_reset_im_context (GTK_ENTRY (widget));
_gtk_entry_completion_popdown (completion);
- if (completion->priv->inline_selection)
+ if (completion->priv->current_selected < 0)
+ {
+ retval = FALSE;
+ goto keypress_completion_out;
+ }
+ else if (completion->priv->inline_selection)
{
/* Escape rejects the tentative completion */
if (event->keyval == GDK_Escape)
{
- gtk_entry_set_text (GTK_ENTRY (completion->priv->entry), completion->priv->completion_prefix);
+ if (completion->priv->completion_prefix)
+ gtk_entry_set_text (GTK_ENTRY (completion->priv->entry),
+ completion->priv->completion_prefix);
+ else
+ gtk_entry_set_text (GTK_ENTRY (completion->priv->entry), "");
}
/* Move the cursor to the end for Right/Esc, to the
gtk_editable_set_position (GTK_EDITABLE (widget), -1);
else
gtk_editable_set_position (GTK_EDITABLE (widget), 0);
+ }
+keypress_completion_out:
+ if (completion->priv->inline_selection)
+ {
g_free (completion->priv->completion_prefix);
completion->priv->completion_prefix = NULL;
}
- return TRUE;
+ return retval;
}
else if (event->keyval == GDK_Tab ||
event->keyval == GDK_KP_Tab ||
{
GtkDirectionType dir = event->keyval == GDK_ISO_Left_Tab ?
GTK_DIR_TAB_BACKWARD : GTK_DIR_TAB_FORWARD;
-
+
_gtk_entry_reset_im_context (GTK_ENTRY (widget));
_gtk_entry_completion_popdown (completion);
- if (completion->priv->completion_prefix)
- {
- g_free (completion->priv->completion_prefix);
- completion->priv->completion_prefix = NULL;
- }
+ g_free (completion->priv->completion_prefix);
+ completion->priv->completion_prefix = NULL;
gtk_widget_child_focus (gtk_widget_get_toplevel (widget), dir);
event->keyval == GDK_KP_Enter ||
event->keyval == GDK_Return)
{
+ gboolean retval = TRUE;
+
_gtk_entry_reset_im_context (GTK_ENTRY (widget));
_gtk_entry_completion_popdown (completion);
gboolean entry_set;
sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (completion->priv->tree_view));
- if (!gtk_tree_selection_get_selected (sel, &model, &iter))
- return FALSE;
-
- g_signal_handler_block (widget, completion->priv->changed_id);
- g_signal_emit_by_name (completion, "match_selected",
- model, &iter, &entry_set);
- g_signal_handler_unblock (widget, completion->priv->changed_id);
-
- if (!entry_set)
+ if (gtk_tree_selection_get_selected (sel, &model, &iter))
{
- gchar *str = NULL;
+ g_signal_handler_block (widget, completion->priv->changed_id);
+ g_signal_emit_by_name (completion, "match_selected",
+ model, &iter, &entry_set);
+ g_signal_handler_unblock (widget, completion->priv->changed_id);
+
+ if (!entry_set)
+ {
+ gchar *str = NULL;
- gtk_tree_model_get (model, &iter,
- completion->priv->text_column, &str,
- -1);
+ gtk_tree_model_get (model, &iter,
+ completion->priv->text_column, &str,
+ -1);
- gtk_entry_set_text (GTK_ENTRY (widget), str);
+ gtk_entry_set_text (GTK_ENTRY (widget), str);
- /* move the cursor to the end */
- gtk_editable_set_position (GTK_EDITABLE (widget), -1);
+ /* move the cursor to the end */
+ gtk_editable_set_position (GTK_EDITABLE (widget), -1);
- g_free (str);
+ g_free (str);
+ }
}
-
- return TRUE;
+ else
+ retval = FALSE;
}
else if (completion->priv->current_selected - matches >= 0)
{
g_signal_emit_by_name (completion, "action_activated",
gtk_tree_path_get_indices (path)[0]);
gtk_tree_path_free (path);
-
- return TRUE;
}
+
+ g_free (completion->priv->completion_prefix);
+ completion->priv->completion_prefix = NULL;
+
+ return retval;
}
return FALSE;
/**
* gtk_entry_set_completion:
- * @entry: A #GtkEntry.
- * @completion: The #GtkEntryCompletion or %NULL.
+ * @entry: A #GtkEntry
+ * @completion: The #GtkEntryCompletion or %NULL
*
* Sets @completion to be the auxiliary completion object to use with @entry.
* All further configuration of the completion mechanism is done on
/**
* gtk_entry_get_completion:
- * @entry: A #GtkEntry.
+ * @entry: A #GtkEntry
*
* Returns the auxiliary completion object currently in use by @entry.
*
/**
* gtk_entry_set_cursor_hadjustment:
* @entry: a #GtkEntry
- * @adjustment: an adjustment which should be adjusted when the cursor is moved,
- * or %NULL
+ * @adjustment: an adjustment which should be adjusted when the cursor
+ * is moved, or %NULL
*
* Hooks up an adjustment to the cursor position in an entry, so that when
* the cursor is moved, the adjustment is scrolled to show that position.
gtk_entry_set_cursor_hadjustment (GtkEntry *entry,
GtkAdjustment *adjustment)
{
- GtkEntryPrivate *priv;
-
g_return_if_fail (GTK_IS_ENTRY (entry));
if (adjustment)
g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
- priv = GTK_ENTRY_GET_PRIVATE (entry);
- if (priv->cursor_hadjustment)
- g_object_unref (priv->cursor_hadjustment);
if (adjustment)
g_object_ref (adjustment);
- priv->cursor_hadjustment = adjustment;
+
+ g_object_set_qdata_full (G_OBJECT (entry),
+ quark_cursor_hadjustment,
+ adjustment,
+ g_object_unref);
}
/**
GtkAdjustment*
gtk_entry_get_cursor_hadjustment (GtkEntry *entry)
{
- GtkEntryPrivate *priv;
-
g_return_val_if_fail (GTK_IS_ENTRY (entry), NULL);
- priv = GTK_ENTRY_GET_PRIVATE (entry);
-
- return priv->cursor_hadjustment;
+ return g_object_get_qdata (G_OBJECT (entry), quark_cursor_hadjustment);
}
#define __GTK_ENTRY_C__