* Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
* 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/.
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
#include <config.h>
editable = GTK_EDITABLE (widget);
attributes.window_type = GDK_WINDOW_CHILD;
-
+
get_widget_window_size (entry, &attributes.x, &attributes.y, &attributes.width, &attributes.height);
attributes.wclass = GDK_INPUT_OUTPUT;
PangoFontMetrics *metrics;
gint xborder, yborder;
PangoContext *context;
-
+
context = gtk_widget_get_pango_context (widget);
metrics = pango_context_get_metrics (context,
widget->style->font_desc,
entry->descent = pango_font_metrics_get_descent (metrics);
get_borders (entry, &xborder, &yborder);
-
+
xborder += INNER_BORDER;
yborder += INNER_BORDER;
-
+
if (entry->width_chars < 0)
requisition->width = MIN_ENTRY_WIDTH + xborder * 2;
else
gint char_width = pango_font_metrics_get_approximate_char_width (metrics);
requisition->width = PANGO_PIXELS (char_width) * entry->width_chars + xborder * 2;
}
-
+
requisition->height = PANGO_PIXELS (entry->ascent + entry->descent) + yborder * 2;
pango_font_metrics_unref (metrics);
if (y)
*y = yborder;
-
+
if (width)
*width = GTK_WIDGET (entry)->allocation.width - xborder * 2;
{
GtkRequisition requisition;
GtkWidget *widget = GTK_WIDGET (entry);
-
+
gtk_widget_get_child_requisition (widget, &requisition);
if (x)
if(ientry->text_max_size > 0)
allocation->width = MIN(ientry->text_max_size, allocation->width);
-
+
widget->allocation = *allocation;
-
+
if (GTK_WIDGET_REALIZED (widget))
{
/* We call gtk_widget_get_child_requisition, since we want (for
gint x, y, width, height;
get_widget_window_size (entry, &x, &y, &width, &height);
-
+
gdk_window_move_resize (widget->window,
- allocation->x, allocation->y, allocation->width, allocation->height);
+ allocation->x, allocation->y, allocation->width, allocation->height);
get_text_area_size (entry, &x, &y, &width, &height);
-
+
gdk_window_move_resize (entry->text_area,
- 0, allocation->height - height, allocation->width, height);
+ 0, allocation->height - height, allocation->width, height);
gtk_entry_recompute (entry);
}
if (entry->dnd_position != -1)
gtk_entry_draw_cursor (GTK_ENTRY (widget), CURSOR_DND);
-
+
gtk_entry_draw_text (GTK_ENTRY (widget));
}
"gtk-entry-select-on-focus",
&select_on_focus,
NULL);
-
+
if (select_on_focus && entry->editable && !entry->in_click)
gtk_editable_select_region (GTK_EDITABLE (widget), 0, -1);
}
-static void
+static void
gtk_entry_direction_changed (GtkWidget *widget,
GtkTextDirection previous_dir)
{
GtkEntry *entry = GTK_ENTRY (widget);
gtk_entry_recompute (entry);
-
+
GTK_WIDGET_CLASS (parent_class)->direction_changed (widget, previous_dir);
}
GtkStateType previous_state)
{
GtkEntry *entry = GTK_ENTRY (widget);
-
+
if (GTK_WIDGET_REALIZED (widget))
{
gdk_window_set_background (widget->window, &widget->style->bg[GTK_WIDGET_STATE (widget)]);
if (!GTK_WIDGET_IS_SENSITIVE (widget))
{
/* Clear any selection */
- gtk_editable_select_region (GTK_EDITABLE (entry), entry->current_pos, entry->current_pos);
+ gtk_editable_select_region (GTK_EDITABLE (entry), entry->current_pos, entry->current_pos);
}
-
+
gtk_widget_queue_clear (widget);
}
if (*position < 0 || *position > entry->text_length)
*position = entry->text_length;
-
+
g_object_ref (G_OBJECT (editable));
-
+
if (new_text_length <= 63)
text = buf;
else
text[new_text_length] = '\0';
strncpy (text, new_text, new_text_length);
-
+
g_signal_emit_by_name (editable, "insert_text", text, new_text_length, position);
if (new_text_length > 63)
start_pos = 0;
if (start_pos > end_pos)
start_pos = end_pos;
-
+
g_object_ref (G_OBJECT (editable));
g_signal_emit_by_name (editable, "delete_text", start_pos, end_pos);
g_object_unref (G_OBJECT (editable));
}
-static void
+static void
gtk_entry_style_set (GtkWidget *widget,
GtkStyle *previous_style)
{
/* NUL terminate for safety and convenience */
entry->text[entry->n_bytes] = '\0';
-
+
if (entry->current_pos > *position)
entry->current_pos += n_chars;
-
+
if (entry->selection_bound > *position)
entry->selection_bound += n_chars;
start_pos = 0;
if (end_pos < 0 || end_pos > entry->text_length)
end_pos = entry->text_length;
-
+
if (start_pos < end_pos)
{
gint start_index = g_utf8_offset_to_pointer (entry->text, start_pos) - entry->text;
g_memmove (entry->text + start_index, entry->text + end_index, entry->n_bytes + 1 - end_index);
entry->text_length -= (end_pos - start_pos);
entry->n_bytes -= (end_index - start_index);
-
+
if (entry->current_pos > start_pos)
entry->current_pos -= MIN (entry->current_pos, end_pos) - start_pos;
/* We might have deleted the selection
*/
gtk_entry_update_primary_selection (entry);
-
+
gtk_entry_recompute (entry);
-
+
g_signal_emit_by_name (editable, "changed");
g_object_notify (G_OBJECT (editable), "text");
}
GTK_TEXT_DIR_LTR : GTK_TEXT_DIR_RTL;
GtkTextDirection widget_direction = gtk_widget_get_direction (GTK_WIDGET (entry));
gboolean split_cursor;
-
+
PangoLayout *layout = gtk_entry_ensure_layout (entry, TRUE);
gint index = g_utf8_offset_to_pointer (entry->text, offset) - entry->text;
-
+
PangoRectangle strong_pos, weak_pos;
-
+
g_object_get (gtk_widget_get_settings (GTK_WIDGET (entry)),
"gtk-split-cursor", &split_cursor,
NULL);
gtk_editable_select_region (GTK_EDITABLE (entry), entry->selection_bound, new_pos);
else
gtk_editable_set_position (GTK_EDITABLE (entry), new_pos);
-
+
gtk_entry_pend_cursor_blink (entry);
}
GtkEditable *editable = GTK_EDITABLE (entry);
gint start_pos = entry->current_pos;
gint end_pos = entry->current_pos;
-
+
gtk_entry_reset_im_context (entry);
if (!entry->editable)
gtk_editable_delete_selection (editable);
return;
}
-
+
switch (type)
{
case GTK_DELETE_CHARS:
start_pos = gtk_entry_move_forward_word (entry, start_pos);
start_pos = gtk_entry_move_backward_word (entry, start_pos);
}
-
+
/* Fall through */
case GTK_DELETE_WORD_ENDS:
while (count < 0)
break;
case GTK_DELETE_DISPLAY_LINES:
case GTK_DELETE_PARAGRAPHS:
- gtk_editable_delete_text (editable, 0, -1);
+ gtk_editable_delete_text (editable, 0, -1);
break;
case GTK_DELETE_WHITESPACE:
gtk_entry_delete_whitespace (entry);
break;
}
-
+
gtk_entry_pend_cursor_blink (entry);
}
gtk_entry_queue_draw (entry);
entry->recompute_idle = FALSE;
-
+
update_im_cursor_location (entry);
GDK_THREADS_LEAVE ();
if (!entry->recompute_idle)
{
entry->recompute_idle = g_idle_add_full (G_PRIORITY_HIGH_IDLE + 15, /* between resize and redraw */
- recompute_idle_func, entry, NULL);
+ recompute_idle_func, entry, NULL);
}
}
gint i;
gint char_len;
gchar buf[7];
-
+
char_len = g_unichar_to_utf8 (ch, buf);
-
+
i = 0;
while (i < count)
{
++i;
}
}
-
+
static PangoLayout *
gtk_entry_create_layout (GtkEntry *entry,
gboolean include_preedit)
{
PangoLayout *layout = gtk_widget_create_pango_layout (GTK_WIDGET (entry), NULL);
PangoAttrList *tmp_attrs = pango_attr_list_new ();
-
+
gchar *preedit_string = NULL;
gint preedit_length = 0;
PangoAttrList *preedit_attrs = NULL;
pango_layout_set_single_paragraph_mode (layout, TRUE);
-
+
if (include_preedit)
{
gtk_im_context_get_preedit_string (entry->im_context,
if (preedit_length)
{
GString *tmp_string = g_string_new (NULL);
-
+
gint cursor_index = g_utf8_offset_to_pointer (entry->text, entry->current_pos) - entry->text;
-
+
if (entry->visible)
{
g_string_prepend_len (tmp_string, entry->text, entry->n_bytes);
gint ch_len;
gint preedit_len_chars;
gunichar invisible_char;
-
+
ch_len = g_utf8_strlen (entry->text, entry->n_bytes);
preedit_len_chars = g_utf8_strlen (preedit_string, -1);
ch_len += preedit_len_chars;
invisible_char = entry->invisible_char;
else
invisible_char = ' '; /* just pick a char */
-
+
append_char (tmp_string, invisible_char, ch_len);
-
+
/* Fix cursor index to point to invisible char corresponding
* to the preedit, fix preedit_length to be the length of
* the invisible chars representing the preedit
preedit_len_chars *
g_unichar_to_utf8 (invisible_char, NULL);
}
-
+
pango_layout_set_text (layout, tmp_string->str, tmp_string->len);
-
+
pango_attr_list_splice (tmp_attrs, preedit_attrs,
cursor_index, preedit_length);
-
+
g_string_free (tmp_string, TRUE);
}
else
{
GString *str = g_string_new (NULL);
gunichar invisible_char;
-
+
if (entry->invisible_char != 0)
invisible_char = entry->invisible_char;
else
invisible_char = ' '; /* just pick a char */
-
+
append_char (str, invisible_char, entry->text_length);
pango_layout_set_text (layout, str->str, str->len);
g_string_free (str, TRUE);
}
}
-
+
pango_layout_set_attributes (layout, tmp_attrs);
if (preedit_string)
g_free (preedit_string);
if (preedit_attrs)
pango_attr_list_unref (preedit_attrs);
-
+
pango_attr_list_unref (tmp_attrs);
return layout;
entry->cached_layout = gtk_entry_create_layout (entry, include_preedit);
entry->cache_includes_preedit = include_preedit;
}
-
+
return entry->cached_layout;
}
gint area_width, area_height;
gint y_pos;
PangoLayoutLine *line;
-
+
layout = gtk_entry_ensure_layout (entry, TRUE);
- get_text_area_size (entry, NULL, NULL, &area_width, &area_height);
-
+ get_text_area_size (entry, NULL, NULL, &area_width, &area_height);
+
area_height = PANGO_SCALE * (area_height);
-
+
line = pango_layout_get_lines (layout)->data;
pango_layout_line_get_extents (line, NULL, &logical_rect);
-
+
/* Align primarily for locale's ascent/descent */
- y_pos = ((area_height - entry->ascent - entry->descent) / 2 +
+ y_pos = ((area_height - entry->ascent - entry->descent) / 2 +
entry->ascent + logical_rect.y);
-
+
/* Now see if we need to adjust to fit in actual drawn string */
if (logical_rect.height > area_height)
y_pos = 0;
else if (y_pos + logical_rect.height > area_height)
y_pos = area_height - logical_rect.height;
-
+
y_pos = y_pos / PANGO_SCALE;
if (x)
{
GtkWidget *widget;
PangoLayoutLine *line;
-
+
if (!entry->visible && entry->invisible_char == 0)
return;
-
+
if (GTK_WIDGET_DRAWABLE (entry))
{
PangoLayout *layout = gtk_entry_ensure_layout (entry, TRUE);
gint x, y;
gint start_pos, end_pos;
-
+
widget = GTK_WIDGET (entry);
-
+
get_layout_position (entry, &x, &y);
get_text_area_size (entry, NULL, NULL, &area_width, &area_height);
- gdk_draw_layout (entry->text_area, widget->style->text_gc [widget->state],
+ gdk_draw_layout (entry->text_area, widget->style->text_gc [widget->state],
x, y,
layout);
-
-
+
+
if (gtk_editable_get_selection_bounds (GTK_EDITABLE (entry), &start_pos, &end_pos))
{
gint *ranges;
GdkGC *selection_gc;
line = pango_layout_get_lines (layout)->data;
-
+
pango_layout_line_get_x_ranges (line, start_index, end_index, &ranges, &n_ranges);
pango_layout_get_extents (layout, NULL, &logical_rect);
-
+
if (GTK_WIDGET_HAS_FOCUS (entry))
{
selection_gc = widget->style->base_gc [GTK_STATE_SELECTED];
selection_gc = widget->style->base_gc [GTK_STATE_ACTIVE];
text_gc = widget->style->text_gc [GTK_STATE_ACTIVE];
}
-
+
for (i=0; i < n_ranges; i++)
{
GdkRectangle rect;
rect.y = y;
rect.width = (ranges[2*i + 1] - ranges[2*i]) / PANGO_SCALE;
rect.height = logical_rect.height / PANGO_SCALE;
-
+
gdk_draw_rectangle (entry->text_area, selection_gc, TRUE,
rect.x, rect.y, rect.width, rect.height);
}
gdk_gc_set_clip_region (text_gc, clip_region);
- gdk_draw_layout (entry->text_area, text_gc,
+ gdk_draw_layout (entry->text_area, text_gc,
x, y,
layout);
gdk_gc_set_clip_region (text_gc, NULL);
-
+
gdk_region_destroy (clip_region);
g_free (ranges);
}
GdkColor *cursor_color;
gtk_widget_style_get (widget, property_name, &cursor_color, NULL);
-
+
gc_values_mask = GDK_GC_FOREGROUND;
if (cursor_color)
{
}
else
gc_values.foreground = *fallback;
-
+
gdk_rgb_find_color (widget->style->colormap, &gc_values.foreground);
return gtk_gc_get (widget->style->depth, widget->style->colormap,
&gc_values, gc_values_mask);
cursor_info->primary_gc = make_cursor_gc (widget,
"cursor-color",
&widget->style->black);
-
+
return g_object_ref (cursor_info->primary_gc);
}
else
{
static GdkColor gray = { 0, 0x8888, 0x8888, 0x8888 };
-
+
if (!cursor_info->secondary_gc)
cursor_info->secondary_gc = make_cursor_gc (widget,
"secondary-cursor-color",
&gray);
-
+
return g_object_ref (cursor_info->secondary_gc);
}
}
gint i;
gfloat cursor_aspect_ratio;
gint offset;
-
+
g_return_if_fail (direction != GTK_TEXT_DIR_NONE);
-
+
gtk_widget_style_get (widget, "cursor-aspect-ratio", &cursor_aspect_ratio, NULL);
-
+
stem_width = location->height * cursor_aspect_ratio + 1;
arrow_width = stem_width + 1;
offset = stem_width / 2;
else
offset = stem_width - stem_width / 2;
-
+
for (i = 0; i < stem_width; i++)
gdk_draw_line (drawable, gc,
location->x + i - offset, location->y,
{
x = location->x - offset - 1;
y = location->y + location->height - arrow_width * 2 - arrow_width + 1;
-
+
for (i = 0; i < arrow_width; i++)
{
gdk_draw_line (drawable, gc,
{
x = location->x + stem_width - offset;
y = location->y + location->height - arrow_width * 2 - arrow_width + 1;
-
- for (i = 0; i < arrow_width; i++)
+
+ for (i = 0; i < arrow_width; i++)
{
gdk_draw_line (drawable, gc,
x, y + i + 1,
(gdk_keymap_get_direction (gdk_keymap_get_default ()) == PANGO_DIRECTION_LTR) ?
GTK_TEXT_DIR_LTR : GTK_TEXT_DIR_RTL;
GtkTextDirection widget_direction = gtk_widget_get_direction (GTK_WIDGET (entry));
-
+
if (GTK_WIDGET_DRAWABLE (entry) && GTK_ENTRY(entry)->cursor_visible)
{
GtkWidget *widget = GTK_WIDGET (entry);
GdkGC *gc;
gdk_window_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),
NULL);
dir1 = widget_direction;
-
+
if (split_cursor)
{
x1 = strong_x;
&cursor_location, dir1,
dir2 != GTK_TEXT_DIR_NONE);
g_object_unref (gc);
-
+
if (dir2 != GTK_TEXT_DIR_NONE)
{
cursor_location.x = xoffset + x2;
const gchar *text;
PangoRectangle strong_pos, weak_pos;
gint index;
-
+
if (type == CURSOR_STANDARD)
{
text = pango_layout_get_text (layout);
if (entry->dnd_position > entry->current_pos)
index += entry->preedit_length;
}
-
+
pango_layout_get_cursor_pos (layout, index, &strong_pos, &weak_pos);
if (strong_x)
return;
item_entry = GTK_ITEM_ENTRY(entry);
-
+
gdk_window_get_size (entry->text_area, &text_area_width, NULL);
text_area_width -= 2 * INNER_BORDER;
entry->scroll_offset += (strong_x - text_area_width) + 1;
}
}
-
+
break;
case GTK_JUSTIFY_RIGHT:
-
+
/* RIGHT JUSTIFICATION FOR NUMBERS */
if(entry->text){
entry->scroll_offset= -(text_area_width - strong_x) + 1;
if(entry->scroll_offset < 0) entry->scroll_offset = 0;
}
- }
+ }
}
else
entry->scroll_offset=0;
break;
case GTK_JUSTIFY_CENTER:
-
+
if(entry->text){
-
+
entry->scroll_offset= -(text_area_width - text_width)/2;
if(entry->scroll_offset > 0){
if(item_entry->text_max_size != 0 &&
const gchar *text;
text = pango_layout_get_text (layout);
-
+
index = g_utf8_offset_to_pointer (text, start) - text;
while (count != 0)
strong = keymap_direction == gtk_widget_get_direction (GTK_WIDGET (entry));
}
-
+
if (count > 0)
{
pango_layout_move_cursor_visually (layout, strong, index, 0, 1, &new_index, &new_trailing);
break;
index = new_index;
-
+
while (new_trailing--)
index = g_utf8_next_char (entry->text + new_index) - entry->text;
}
-
+
return g_utf8_pointer_to_offset (text, text + index);
}
do
new_pos++;
while (new_pos < entry->text_length && !log_attrs[new_pos].is_cursor_position);
-
+
count--;
}
while (count < 0 && new_pos > 0)
do
new_pos--;
while (new_pos > 0 && !log_attrs[new_pos].is_cursor_position);
-
+
count++;
}
-
+
g_free (log_attrs);
}
gint n_attrs;
pango_layout_get_log_attrs (layout, &log_attrs, &n_attrs);
-
+
/* Find the next word end */
new_pos++;
while (new_pos < n_attrs && !log_attrs[new_pos].is_word_end)
pango_layout_get_log_attrs (layout, &log_attrs, &n_attrs);
start = end = entry->current_pos;
-
+
while (start > 0 && log_attrs[start-1].is_white)
start--;
* Like gtk_editable_get_chars, but if the editable is not
* visible, return asterisks; also convert result to UTF-8.
*/
-static char *
+static char *
gtk_entry_get_public_chars (GtkEntry *entry,
gint start,
gint end)
{
if (end < 0)
end = entry->text_length;
-
+
if (entry->visible)
return gtk_editable_get_chars (GTK_EDITABLE (entry), start, end);
else
gchar *str;
gint i;
gint n_chars = end - start;
-
+
str = g_malloc (n_chars + 1);
for (i = 0; i < n_chars; i++)
str[i] = '*';
str[i] = '\0';
-
+
return str;
}
{
GtkEntry *entry = GTK_ENTRY (data);
gint start, end;
-
+
if (gtk_editable_get_selection_bounds (GTK_EDITABLE (entry), &start, &end))
{
gchar *str = gtk_entry_get_public_chars (entry, start, end);
static const GtkTargetEntry targets[] = {
{ "UTF8_STRING", 0, 0 },
{ "STRING", 0, 0 },
- { "TEXT", 0, 0 },
+ { "TEXT", 0, 0 },
{ "COMPOUND_TEXT", 0, 0 }
};
-
+
GtkClipboard *clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
gint start, end;
-
+
if (gtk_editable_get_selection_bounds (GTK_EDITABLE (entry), &start, &end))
{
if (!gtk_clipboard_set_with_owner (clipboard, targets, G_N_ELEMENTS (targets),
* Also useful to convert mouse events into coordinates inside the
* #PangoLayout, e.g. to take some action if some part of the entry text
* is clicked.
- *
+ *
* Note that as the user scrolls around in the entry the offsets will
* change; you'll need to connect to the "notify::scroll_offset"
* signal to track this. Remember when using the #PangoLayout
* 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_item_entry_get_layout_offsets (GtkItemEntry *entry,
gint *y)
{
gint text_area_x, text_area_y;
-
+
g_return_if_fail (GTK_IS_ITEM_ENTRY (entry));
/* this gets coords relative to text area */
/* convert to widget coords */
get_text_area_size (GTK_ENTRY(entry), &text_area_x, &text_area_y, NULL, NULL);
-
+
if (x)
*x += text_area_x;
GDK_THREADS_ENTER ();
entry = GTK_ENTRY (data);
-
+
g_assert (GTK_WIDGET_HAS_FOCUS (entry));
g_assert (entry->selection_bound == entry->current_pos);
}
else
{
- if (entry->blink_timeout)
- {
+ if (entry->blink_timeout)
+ {
gtk_timeout_remove (entry->blink_timeout);
entry->blink_timeout = 0;
}
-
+
entry->cursor_visible = TRUE;
}
-
+
}
static void
{
if (entry->blink_timeout != 0)
gtk_timeout_remove (entry->blink_timeout);
-
+
entry->blink_timeout = gtk_timeout_add (get_cursor_time (entry) * CURSOR_PEND_MULTIPLIER,
blink_cb,
entry);