diff options
author | Owen Taylor <otaylor@redhat.com> | 1998-12-09 06:36:57 +0000 |
---|---|---|
committer | Owen Taylor <otaylor@src.gnome.org> | 1998-12-09 06:36:57 +0000 |
commit | 207757e70d8b2d9aa8335d968fd7ac79796264ab (patch) | |
tree | ae572a9674c8dc7b8a0ae7200e6d4e7c5c7632e8 /gtk/gtkentry.c | |
parent | af84227184f9cbe2c87f0aa09d5c93564150bb70 (diff) | |
download | gtk+-207757e70d8b2d9aa8335d968fd7ac79796264ab.tar.gz |
Destroy widgets _after_ propagating unrealize signals through the widget
Mon Dec 7 10:27:09 1998 Owen Taylor <otaylor@redhat.com>
* gtk/gtkwidget.c: Destroy widgets _after_ propagating unrealize
signals through the widget heirarchy. This is unpleasant, as it
causes more X traffic, but is necessary, because we have to clean
up our Input Contexts before destroying the X windows.
(from matsu-981109-0.patch)
Mon Dec 7 10:18:18 1998 Owen Taylor <otaylor@redhat.com>
Applied gtk-a-higuti-981202-0 :
[ a-higuti@math.sci.hokudai.ac.jp (Akira Higuchi) ]
* gdk/gdk.h gdk/gdk.c
(gdk_mbstowcs): New function. Nearly equals to mbstowcs, but
implemented by a combination of Xlib functions, so
it works even with X_LOCALE.
(gdk_wcstombs): New function.
(g_mbtowc): Removed. No longer needed.
* gdk/gdk.h gdk/gdkfont.c gdk/gdkdraw.c:
Added _wc() variants to gdk_text_width(),
gdk_char_width(), gdk_draw_text(),
* gdk/gdki18n.h
(mblen, mbtowc, wctomb, mbstowcs, wcstombs,
wcslen, wcscpy, wcsncpy):
Removed. No longer needed.
(iswalnum): Removed.
(gdk_iswalnum): New macro.
(gdk_iswspace): New macro.
* gdk/gdktype.h
(GdkWChar): New typedef.
* gtk/gtkentry.h, gtk/gtkentry.c
There are many changes according to the change of the
internal representation of text, from multibyte string
to wide characters.
* gtk/gtkprivate.h, gtk/gtkmain.c
Removed the variable gtk_use_mb and related codes.
* gtk/gtkspinbutton.c
Some changes according to the change of type of entry->text.
* gtk/gtktext.h, gtk/gtktext.c
Changed the internal representation of text. We use GdkWchar
if a fontset is supplied. If not, we use guchar to save
memory.
Diffstat (limited to 'gtk/gtkentry.c')
-rw-r--r-- | gtk/gtkentry.c | 702 |
1 files changed, 306 insertions, 396 deletions
diff --git a/gtk/gtkentry.c b/gtk/gtkentry.c index 77079d2ae4..76e6d5b7b4 100644 --- a/gtk/gtkentry.c +++ b/gtk/gtkentry.c @@ -18,9 +18,6 @@ */ #include <ctype.h> #include <string.h> -#ifdef USE_XIM -#include "gdk/gdkx.h" -#endif #include "gdk/gdkkeysyms.h" #include "gdk/gdki18n.h" #include "gtkentry.h" @@ -28,7 +25,6 @@ #include "gtkselection.h" #include "gtksignal.h" #include "gtkstyle.h" -#include "gtkprivate.h" #define MIN_ENTRY_WIDTH 150 #define DRAW_TIMEOUT 20 @@ -84,6 +80,9 @@ static void gtk_entry_style_set (GtkWidget *widget, GtkStyle *previous_style); static void gtk_entry_state_changed (GtkWidget *widget, GtkStateType previous_state); +#ifdef USE_XIM +static void gtk_entry_update_ic_attr (GtkWidget *widget); +#endif static void gtk_entry_queue_draw (GtkEntry *entry); static gint gtk_entry_timer (gpointer data); static gint gtk_entry_position (GtkEntry *entry, @@ -143,8 +142,6 @@ static void gtk_entry_set_selection (GtkEditable *editable, gint end); static void gtk_entry_recompute_offsets (GtkEntry *entry); -static gint gtk_entry_find_char (GtkEntry *entry, - gint position); static gint gtk_entry_find_position (GtkEntry *entry, gint position); static void gtk_entry_set_position_from_editable (GtkEditable *editable, @@ -353,9 +350,10 @@ gtk_entry_init (GtkEntry *entry) entry->button = 0; entry->visible = 1; - entry->nchars = 0; - entry->char_pos = NULL; entry->char_offset = NULL; + entry->text_mb = NULL; + entry->text_mb_dirty = TRUE; + entry->use_wchar = FALSE; gtk_entry_grow_text (entry); } @@ -480,14 +478,27 @@ gtk_entry_set_editable(GtkEntry *entry, gchar* gtk_entry_get_text (GtkEntry *entry) { - static char empty_str[2] = ""; - g_return_val_if_fail (entry != NULL, NULL); g_return_val_if_fail (GTK_IS_ENTRY (entry), NULL); + if (!entry->text_mb_dirty) + return entry->text_mb; + + if (entry->text_mb) + g_free(entry->text_mb); + if (!entry->text) - return empty_str; - return entry->text; + { + entry->text_mb = g_new(gchar, 1); + entry->text_mb[0] = 0; + } + else + { + entry->text_mb = gtk_entry_get_chars(GTK_EDITABLE(entry), 0, -1); + } + entry->text_mb_dirty = 0; + + return entry->text_mb; } static void @@ -500,26 +511,22 @@ gtk_entry_finalize (GtkObject *object) entry = GTK_ENTRY (object); -#ifdef USE_XIM - if (GTK_EDITABLE(entry)->ic) - { - gdk_ic_destroy (GTK_EDITABLE(entry)->ic); - GTK_EDITABLE(entry)->ic = NULL; - } -#endif - if (entry->timer) gtk_timeout_remove (entry->timer); entry->text_size = 0; + if (entry->text) g_free (entry->text); - if (entry->char_pos) - g_free (entry->char_pos); if (entry->char_offset) g_free (entry->char_offset); entry->text = NULL; + if (entry->text_mb) + g_free (entry->text_mb); + entry->text_mb = NULL; + + if (entry->backing_pixmap) if (entry->backing_pixmap) gdk_pixmap_unref (entry->backing_pixmap); @@ -581,21 +588,37 @@ gtk_entry_realize (GtkWidget *widget) gdk_window_set_background (entry->text_area, &widget->style->base[GTK_WIDGET_STATE (widget)]); #ifdef USE_XIM - if (gdk_im_ready ()) + if (gdk_im_ready () && (editable->ic_attr = gdk_ic_attr_new ()) != NULL) { - GdkPoint spot; - GdkRectangle rect; gint width, height; GdkEventMask mask; + GdkColormap *colormap; + GdkICAttr *attr = editable->ic_attr; + GdkICAttributesType attrmask = GDK_IC_ALL_REQ; GdkIMStyle style; - GdkIMStyle supported_style = GDK_IM_PREEDIT_NONE | GDK_IM_PREEDIT_NOTHING | - GDK_IM_PREEDIT_POSITION | - GDK_IM_STATUS_NONE | GDK_IM_STATUS_NOTHING; + GdkIMStyle supported_style = GDK_IM_PREEDIT_NONE | + GDK_IM_PREEDIT_NOTHING | + GDK_IM_PREEDIT_POSITION | + GDK_IM_STATUS_NONE | + GDK_IM_STATUS_NOTHING; if (widget->style && widget->style->font->type != GDK_FONT_FONTSET) supported_style &= ~GDK_IM_PREEDIT_POSITION; - style = gdk_im_decide_style (supported_style); + attr->style = style = gdk_im_decide_style (supported_style); + attr->client_window = entry->text_area; + + if ((colormap = gtk_widget_get_colormap (widget)) != + gtk_widget_get_default_colormap ()) + { + attrmask |= GDK_IC_PREEDIT_COLORMAP; + attr->preedit_colormap = colormap; + } + attrmask |= GDK_IC_PREEDIT_FOREGROUND; + attrmask |= GDK_IC_PREEDIT_BACKGROUND; + attr->preedit_foreground = widget->style->fg[GTK_STATE_NORMAL]; + attr->preedit_background = widget->style->base[GTK_STATE_NORMAL]; + switch (style & GDK_IM_PREEDIT_MASK) { case GDK_IM_PREEDIT_POSITION: @@ -604,46 +627,32 @@ gtk_entry_realize (GtkWidget *widget) g_warning ("over-the-spot style requires fontset"); break; } + gdk_window_get_size (entry->text_area, &width, &height); - rect.x = 0; - rect.y = 0; - rect.width = width; - rect.height = height; - spot.x = 0; - spot.y = height; - editable->ic = gdk_ic_new (entry->text_area, entry->text_area, - style, - "spotLocation", &spot, - "area", &rect, - "fontSet", GDK_FONT_XFONT (widget->style->font), - NULL); + + attrmask |= GDK_IC_PREEDIT_POSITION_REQ; + attr->spot_location.x = 0; + attr->spot_location.y = height; + attr->preedit_area.x = 0; + attr->preedit_area.y = 0; + attr->preedit_area.width = width; + attr->preedit_area.height = height; + attr->preedit_fontset = widget->style->font; + break; - default: - editable->ic = gdk_ic_new (entry->text_area, entry->text_area, - style, NULL); } + editable->ic = gdk_ic_new (attr, attrmask); if (editable->ic == NULL) g_warning ("Can't create input context."); else { - GdkColormap *colormap; - mask = gdk_window_get_events (entry->text_area); mask |= gdk_ic_get_events (editable->ic); gdk_window_set_events (entry->text_area, mask); - if ((colormap = gtk_widget_get_colormap (widget)) != - gtk_widget_get_default_colormap ()) - { - gdk_ic_set_attr (editable->ic, "preeditAttributes", - "colorMap", GDK_COLORMAP_XCOLORMAP (colormap), - NULL); - } - gdk_ic_set_attr (editable->ic,"preeditAttributes", - "foreground", widget->style->fg[GTK_STATE_NORMAL].pixel, - "background", widget->style->base[GTK_STATE_NORMAL].pixel, - NULL); + if (GTK_WIDGET_HAS_FOCUS(widget)) + gdk_im_begin (editable->ic, entry->text_area); } } #endif @@ -666,6 +675,19 @@ gtk_entry_unrealize (GtkWidget *widget) entry = GTK_ENTRY (widget); +#ifdef USE_XIM + if (GTK_EDITABLE (widget)->ic) + { + gdk_ic_destroy (GTK_EDITABLE (widget)->ic); + GTK_EDITABLE (widget)->ic = NULL; + } + if (GTK_EDITABLE (widget)->ic_attr) + { + gdk_ic_attr_destroy (GTK_EDITABLE (widget)->ic_attr); + GTK_EDITABLE (widget)->ic_attr = NULL; + } +#endif + if (entry->text_area) { gdk_window_set_user_data (entry->text_area, NULL); @@ -765,17 +787,16 @@ gtk_entry_size_allocate (GtkWidget *widget, entry_adjust_scroll (entry); #ifdef USE_XIM - if (editable->ic && (gdk_ic_get_style (editable->ic) & GDK_IM_PREEDIT_POSITION)) + if (editable->ic && + (gdk_ic_get_style (editable->ic) & GDK_IM_PREEDIT_POSITION)) { gint width, height; - GdkRectangle rect; gdk_window_get_size (entry->text_area, &width, &height); - rect.x = 0; - rect.y = 0; - rect.width = width; - rect.height = height; - gdk_ic_set_attr (editable->ic, "preeditAttributes", "area", &rect, NULL); + editable->ic_attr->preedit_area.width = width; + editable->ic_attr->preedit_area.height = height; + gdk_ic_set_attr (editable->ic, editable->ic_attr, + GDK_IC_PREEDIT_AREA); } #endif } @@ -1236,13 +1257,9 @@ gtk_entry_draw_text (GtkEntry *entry) GtkWidget *widget; GtkEditable *editable; GtkStateType selected_state; - gint start_char; gint start_pos; gint end_pos; - gint end_char; gint start_xoffset; - gint selection_start_char; - gint selection_end_char; gint selection_start_pos; gint selection_end_pos; gint selection_start_xoffset; @@ -1251,8 +1268,8 @@ gtk_entry_draw_text (GtkEntry *entry) gint y; GdkDrawable *drawable; gint use_backing_pixmap; - gchar *stars; - gchar *toprint; + GdkWChar *stars; + GdkWChar *toprint; g_return_if_fail (entry != NULL); g_return_if_fail (GTK_IS_ENTRY (entry)); @@ -1305,12 +1322,10 @@ gtk_entry_draw_text (GtkEntry *entry) y = (height - (widget->style->font->ascent + widget->style->font->descent)) / 2; y += widget->style->font->ascent; - start_char = gtk_entry_find_position (entry, entry->scroll_offset); - start_pos = entry->char_pos[start_char]; - start_xoffset = entry->char_offset[start_char] - entry->scroll_offset; + start_pos = gtk_entry_find_position (entry, entry->scroll_offset); + start_xoffset = entry->char_offset[start_pos] - entry->scroll_offset; - end_char = gtk_entry_find_position (entry, entry->scroll_offset + width); - end_pos = entry->char_pos[end_char]; + end_pos = gtk_entry_find_position (entry, entry->scroll_offset + width); if (end_pos < entry->text_length) end_pos += 1; @@ -1324,13 +1339,10 @@ gtk_entry_draw_text (GtkEntry *entry) selection_start_pos = CLAMP (selection_start_pos, start_pos, end_pos); selection_end_pos = CLAMP (selection_end_pos, start_pos, end_pos); - selection_start_char = gtk_entry_find_char(entry,selection_start_pos); - selection_end_char = gtk_entry_find_char(entry,selection_end_pos); - selection_start_xoffset = - entry->char_offset[selection_start_char] - entry->scroll_offset; + entry->char_offset[selection_start_pos] - entry->scroll_offset; selection_end_xoffset = - entry->char_offset[selection_end_char] -entry->scroll_offset; + entry->char_offset[selection_end_pos] -entry->scroll_offset; /* if entry->visible, print a bunch of stars. If not, print the standard text. */ if (entry->visible) @@ -1341,24 +1353,18 @@ gtk_entry_draw_text (GtkEntry *entry) { gint i; - stars = g_malloc (end_char - start_char); - for (i = 0; i < end_char - start_char; i++) + stars = g_new (GdkWChar, end_pos - start_pos); + for (i = 0; i < end_pos - start_pos; i++) stars[i] = '*'; toprint = stars; - - /* Since '*' is always one byte, work in bytes */ - start_pos = start_char; - selection_start_pos = selection_start_char; - selection_end_pos = selection_end_char; - end_pos = end_char; } if (selection_start_pos > start_pos) - gdk_draw_text (drawable, widget->style->font, - widget->style->fg_gc[GTK_WIDGET_STATE (widget)], - INNER_BORDER + start_xoffset, y, - toprint, - selection_start_pos - start_pos); + gdk_draw_text_wc (drawable, widget->style->font, + widget->style->fg_gc[GTK_WIDGET_STATE (widget)], + INNER_BORDER + start_xoffset, y, + toprint, + selection_start_pos - start_pos); if ((selection_end_pos >= start_pos) && (selection_start_pos < end_pos) && @@ -1371,19 +1377,19 @@ gtk_entry_draw_text (GtkEntry *entry) INNER_BORDER, selection_end_xoffset - selection_start_xoffset, height - 2*INNER_BORDER); - gdk_draw_text (drawable, widget->style->font, - widget->style->fg_gc[selected_state], - INNER_BORDER + selection_start_xoffset, y, - toprint + selection_start_pos - start_pos, - selection_end_pos - selection_start_pos); + gdk_draw_text_wc (drawable, widget->style->font, + widget->style->fg_gc[selected_state], + INNER_BORDER + selection_start_xoffset, y, + toprint + selection_start_pos - start_pos, + selection_end_pos - selection_start_pos); } if (selection_end_pos < end_pos) - gdk_draw_text (drawable, widget->style->font, - widget->style->fg_gc[GTK_WIDGET_STATE (widget)], - INNER_BORDER + selection_end_xoffset, y, - toprint + selection_end_pos - start_pos, - end_pos - selection_end_pos); + gdk_draw_text_wc (drawable, widget->style->font, + widget->style->fg_gc[GTK_WIDGET_STATE (widget)], + INNER_BORDER + selection_end_xoffset, y, + toprint + selection_end_pos - start_pos, + end_pos - selection_end_pos); /* free the space allocated for the stars if it's neccessary. */ if (!entry->visible) g_free (toprint); @@ -1424,7 +1430,7 @@ gtk_entry_draw_cursor_on_drawable (GtkEntry *entry, GdkDrawable *drawable) widget = GTK_WIDGET (entry); editable = GTK_EDITABLE (entry); - xoffset = INNER_BORDER + entry->char_offset[gtk_entry_find_char (entry, editable->current_pos)]; + xoffset = INNER_BORDER + entry->char_offset[editable->current_pos]; xoffset -= entry->scroll_offset; gdk_window_get_size (entry->text_area, NULL, &text_area_height); @@ -1444,14 +1450,16 @@ gtk_entry_draw_cursor_on_drawable (GtkEntry *entry, GdkDrawable *drawable) } #ifdef USE_XIM - if (gdk_im_ready() && editable->ic && - gdk_ic_get_style (editable->ic) & GDK_IM_PREEDIT_POSITION) + if (GTK_WIDGET_HAS_FOCUS(widget) && gdk_im_ready() && editable->ic && + (gdk_ic_get_style (editable->ic) & GDK_IM_PREEDIT_POSITION)) { - GdkPoint spot; + editable->ic_attr->spot_location.x = xoffset; + editable->ic_attr->spot_location.y = + (text_area_height + (widget->style->font->ascent + - widget->style->font->descent) + 1) / 2; - spot.x = xoffset; - spot.y = (text_area_height + (widget->style->font->ascent - widget->style->font->descent) + 1) / 2; - gdk_ic_set_attr (editable->ic, "preeditAttributes", "spotLocation", &spot, NULL); + gdk_ic_set_attr (editable->ic, + editable->ic_attr, GDK_IC_SPOT_LOCATION); } #endif } @@ -1486,7 +1494,7 @@ gtk_entry_find_position (GtkEntry *entry, gint x) { gint start = 0; - gint end = entry->nchars; + gint end = entry->text_length; gint half; if (x <= 0) @@ -1514,7 +1522,7 @@ static gint gtk_entry_position (GtkEntry *entry, gint x) { - return entry->char_pos[gtk_entry_find_position(entry, x)]; + return gtk_entry_find_position(entry, x); } void @@ -1543,13 +1551,13 @@ entry_adjust_scroll (GtkEntry *entry) gdk_window_get_size (entry->text_area, &text_area_width, NULL); /* Display as much text as we can */ - max_offset = MAX(0, entry->char_offset[entry->nchars] - text_area_width); + max_offset = MAX(0, entry->char_offset[entry->text_length] - text_area_width); if (entry->scroll_offset > max_offset) entry->scroll_offset = max_offset; /* And make sure cursor is on screen */ - xoffset = entry->char_offset[gtk_entry_find_char (entry, GTK_EDITABLE(entry)->current_pos)]; + xoffset = entry->char_offset[GTK_EDITABLE(entry)->current_pos]; xoffset -= entry->scroll_offset; if (xoffset < 0) @@ -1574,15 +1582,12 @@ gtk_entry_grow_text (GtkEntry *entry) entry->text_size = 128; else entry->text_size *= 2; - entry->text = g_realloc (entry->text, entry->text_size); - entry->char_pos = g_realloc (entry->char_pos, - entry->text_size * sizeof(guint16)); + entry->text = g_realloc (entry->text, entry->text_size * sizeof(GdkWChar)); entry->char_offset = g_realloc (entry->char_offset, entry->text_size * sizeof(guint)); if (entry->text_length == 0) /* initial allocation */ { - entry->char_pos[0] = 0; entry->char_offset[0] = 0; } @@ -1596,28 +1601,51 @@ gtk_entry_insert_text (GtkEditable *editable, gint new_text_length, gint *position) { - gchar *text; - gint start_char; - gint end_char; + GdkWChar *text; gint start_pos; - gint last_char; gint end_pos; gint last_pos; gint max_length; gint i; - gint insertion_chars; - guint16 *insertion_pos = NULL; /* Quiet the compiler */ + guchar *new_text_nt; + gint insertion_length; + GdkWChar *insertion_text; GtkEntry *entry; + GtkWidget *widget; g_return_if_fail (editable != NULL); g_return_if_fail (GTK_IS_ENTRY (editable)); entry = GTK_ENTRY (editable); + widget = GTK_WIDGET (editable); + + if ((entry->text_length == 0) && (entry->use_wchar == FALSE)) + { + if (!GTK_WIDGET_REALIZED (widget)) + gtk_widget_ensure_style (widget); + if ((widget->style) && (widget->style->font->type == GDK_FONT_FONTSET)) + entry->use_wchar = TRUE; + } if (new_text_length < 0) - new_text_length = strlen (new_text); + { + new_text_nt = (gchar *)new_text; + new_text_length = strlen (new_text); + if (new_text_length <= 0) return; + } + else if (new_text_length == 0) + { + return; + } + else + { + /* make a null-terminated copy of new_text */ + new_text_nt = g_new (gchar, new_text_length + 1); + memcpy (new_text_nt, new_text, new_text_length); + new_text_nt[new_text_length] = 0; + } /* The algorithms here will work as long as, the text size (a * multiple of 2), fits into a guint16 but we specify a shorter @@ -1629,49 +1657,42 @@ gtk_entry_insert_text (GtkEditable *editable, else max_length = MIN (2047, entry->text_max_length); + /* Convert to wide characters */ + insertion_text = g_new (GdkWChar, new_text_length); + if (entry->use_wchar) + insertion_length = gdk_mbstowcs (insertion_text, new_text_nt, + new_text_length); + else + for (insertion_length=0; new_text_nt[insertion_length]; insertion_length++) + insertion_text[insertion_length] = new_text_nt[insertion_length]; + if (new_text_nt != (guchar *)new_text) + g_free (new_text_nt); + /* Make sure we do not exceed the maximum size of the entry. */ - if (new_text_length + entry->text_length > max_length) - new_text_length = max_length - entry->text_length; + if (insertion_length + entry->text_length > max_length) + insertion_length = max_length - entry->text_length; /* Don't insert anything, if there was nothing to insert. */ - if (new_text_length <= 0) - return; - - /* Find the length of the inserted text in characters, chop off - partial/invalid characters */ - if (gtk_use_mb) + if (insertion_length <= 0) { - gint len = 0; - - insertion_pos = g_new (guint16, new_text_length+1); - insertion_chars = 0; - - for (i=0; i<new_text_length; i+=len) - { - len = mblen (&new_text[i], MIN(MB_CUR_MAX,new_text_length-i)); - if (len < 0) - break; - insertion_pos[insertion_chars] = i; - insertion_chars++; - } - insertion_pos[insertion_chars] = i; - - new_text_length = i; + g_free(insertion_text); + return; } - else - insertion_chars = new_text_length; /* Make sure we are inserting at integral character position */ - start_char = gtk_entry_find_char (entry, *position); - start_pos = entry->char_pos[start_char]; + start_pos = *position; + if (start_pos < 0) + start_pos = 0; + else if (start_pos > entry->text_length) + start_pos = entry->text_length; - end_pos = start_pos + new_text_length; - last_pos = new_text_length + entry->text_length; + end_pos = start_pos + insertion_length; + last_pos = insertion_length + entry->text_length; if (editable->selection_start_pos >= *position) - editable->selection_start_pos += new_text_length; + editable->selection_start_pos += insertion_length; if (editable->selection_end_pos >= *position) - editable->selection_end_pos += new_text_length; + editable->selection_end_pos += insertion_length; while (last_pos >= entry->text_size) gtk_entry_grow_text (entry); @@ -1680,33 +1701,8 @@ gtk_entry_insert_text (GtkEditable *editable, for (i = last_pos - 1; i >= end_pos; i--) text[i] = text[i- (end_pos - start_pos)]; for (i = start_pos; i < end_pos; i++) - text[i] = new_text[i - start_pos]; - - if (gtk_use_mb) - { - /* Fix up the character positions */ - - end_char = start_char + insertion_chars; - last_char = entry->nchars + insertion_chars; - - for (i = last_char; i >= end_char; i--) - entry->char_pos[i] - = entry->char_pos[i - insertion_chars] + new_text_length; - - for (i = 1; i < insertion_chars ; i++) - entry->char_pos[start_char+i] = - entry->char_pos[start_char] + insertion_pos[i]; - - g_free (insertion_pos); - } - else - { - end_char = end_pos; - last_char = last_pos; - - for (i = start_char ; i <= last_char ; i++) - entry->char_pos[i] = i; - } + text[i] = insertion_text[i - start_pos]; + g_free (insertion_text); /* Fix up the the character offsets */ @@ -1714,32 +1710,31 @@ gtk_entry_insert_text (GtkEditable *editable, { gint offset = 0; - for (i = last_char; i >= end_char; i--) + for (i = last_pos; i >= end_pos; i--) entry->char_offset[i] - = entry->char_offset[i - insertion_chars]; + = entry->char_offset[i - insertion_length]; - for (i=start_char; i<end_char; i++) + for (i=start_pos; i<end_pos; i++) { - entry->char_offset[i] = entry->char_offset[start_char] + offset; + entry->char_offset[i] = entry->char_offset[start_pos] + offset; if (entry->visible) { - offset += gdk_text_width (GTK_WIDGET (entry)->style->font, - entry->text + entry->char_pos[i], - entry->char_pos[i+1] - entry->char_pos[i]); + offset += gdk_char_width_wc (GTK_WIDGET (entry)->style->font, + entry->text[i]); } else { - offset += gdk_text_width (GTK_WIDGET (entry)->style->font, "*", 1); + offset += gdk_char_width (GTK_WIDGET (entry)->style->font, '*'); } } - for (i = end_char ; i <= last_char ; i++) + for (i = end_pos; i <= last_pos; i++) entry->char_offset[i] += offset; } - entry->text_length += new_text_length; - entry->nchars += insertion_chars; + entry->text_length += insertion_length; *position = end_pos; + entry->text_mb_dirty = 1; gtk_entry_queue_draw (entry); } @@ -1750,64 +1745,30 @@ gtk_entry_recompute_offsets (GtkEntry *entry) gint i; gint offset = 0; - for (i=0; i<entry->nchars; i++) + for (i=0; i<entry->text_length; i++) { entry->char_offset[i] = offset; if (entry->visible) { - offset += gdk_text_width (GTK_WIDGET (entry)->style->font, - entry->text + entry->char_pos[i], - entry->char_pos[i+1] - entry->char_pos[i]); + offset += gdk_char_width_wc (GTK_WIDGET (entry)->style->font, + entry->text[i]); } else { - offset += gdk_text_width (GTK_WIDGET (entry)->style->font, "*", 1); + offset += gdk_char_width (GTK_WIDGET (entry)->style->font, '*'); } } entry->char_offset[i] = offset; } -/* Given a position in the entry, find the character index of the - * last character with position <= the given position - */ -static gint -gtk_entry_find_char (GtkEntry *entry, gint position) -{ - gint start = 0; - gint end = entry->nchars; - gint half; - - if (position >= entry->char_pos[end]) - return end; - if (position < 0) - return 0; - - /* invariant - char_pos[start] <= position < char_pos[end] */ - - while (start != end) - { - half = (start+end)/2; - if (half == start) - return half; - else if (entry->char_pos[half] <= position) - start = half; - else - end = half; - } - - return start; -} - static void gtk_entry_delete_text (GtkEditable *editable, gint start_pos, gint end_pos) { - gchar *text; + GdkWChar *text; gint deletion_length; - gint start_char; - gint end_char; gint i; GtkEntry *entry; @@ -1820,11 +1781,6 @@ gtk_entry_delete_text (GtkEditable *editable, if (end_pos < 0) end_pos = entry->text_length; - start_char = gtk_entry_find_char (entry, start_pos); - end_char = gtk_entry_find_char (entry, end_pos); - start_pos = entry->char_pos[start_char]; - end_pos = entry->char_pos[end_char]; - if (editable->selection_start_pos > start_pos) editable->selection_start_pos -= MIN(end_pos, editable->selection_start_pos) - start_pos; if (editable->selection_end_pos > start_pos) @@ -1841,10 +1797,10 @@ gtk_entry_delete_text (GtkEditable *editable, if (GTK_WIDGET_REALIZED (entry)) { gint deletion_width = - entry->char_offset[end_char] - entry->char_offset[start_char]; + entry->char_offset[end_pos] - entry->char_offset[start_pos]; - for (i = 0 ; i <= entry->nchars - end_char; i++) - entry->char_offset[start_char+i] = entry->char_offset[end_char+i] - deletion_width; + for (i = 0 ; i <= entry->text_length - end_pos; i++) + entry->char_offset[start_pos+i] = entry->char_offset[end_pos+i] - deletion_width; } for (i = end_pos; i < entry->text_length; i++) @@ -1853,15 +1809,11 @@ gtk_entry_delete_text (GtkEditable *editable, for (i = entry->text_length - deletion_length; i < entry->text_length; i++) text[i] = '\0'; - for (i = 0 ; i <= entry->nchars - end_char; i++) - entry->char_pos[start_char+i] = entry->char_pos[end_char+i] - deletion_length; - - entry->nchars -= end_char - start_char; - entry->text_length -= deletion_length; editable->current_pos = start_pos; } + entry->text_mb_dirty = 1; gtk_entry_queue_draw (entry); } @@ -1878,9 +1830,7 @@ gtk_entry_get_chars (GtkEditable *editable, gint start_pos, gint end_pos) { - gchar *retval; GtkEntry *entry; - gchar c; g_return_val_if_fail (editable != NULL, NULL); g_return_val_if_fail (GTK_IS_ENTRY (editable), NULL); @@ -1895,14 +1845,27 @@ gtk_entry_get_chars (GtkEditable *editable, if (start_pos <= end_pos) { - c = entry->text[end_pos]; - entry->text[end_pos] = '\0'; - - retval = g_strdup (&entry->text[start_pos]); - - entry->text[end_pos] = c; - - return retval; + guchar *mbstr; + if (entry->use_wchar) + { + GdkWChar ch; + if (end_pos >= entry->text_size) + gtk_entry_grow_text(entry); + ch = entry->text[end_pos]; + entry->text[end_pos] = 0; + mbstr = gdk_wcstombs (entry->text + start_pos); + entry->text[end_pos] = ch; + return (gchar *)mbstr; + } + else + { + gint i; + mbstr = g_new (gchar, end_pos - start_pos + 1); + for (i=0; i<end_pos-start_pos; i++) + mbstr[i] = entry->text[start_pos + i]; + mbstr[i] = 0; + return (gchar *)mbstr; + } } else return NULL; @@ -1913,47 +1876,16 @@ gtk_entry_move_cursor (GtkEditable *editable, gint x, gint y) { - gint len; - GtkEntry *entry; entry = GTK_ENTRY (editable); /* Horizontal motion */ - if (x > 0) - { - while (x-- != 0) - { - if (gtk_use_mb) - { - if (editable->current_pos < entry->text_length) - { - len = mblen (entry->text+editable->current_pos, MB_CUR_MAX); - editable->current_pos += (len>0)? len:1; - } - if (editable->current_pos > entry->text_length) - editable->current_pos = entry->text_length; - } - else - { - if (editable->current_pos < entry->text_length) - editable->current_pos ++; - } - } - } - else if (x < 0) - { - while (x++ != 0) - { - if (0 < editable->current_pos) - { - if (gtk_use_mb) - editable->current_pos = - entry->char_pos[gtk_entry_find_char (entry, editable->current_pos - 1)]; - else - editable->current_pos--; - } - } - } + if ((gint)editable->current_pos < -x) + editable->current_pos = 0; + else if (editable->current_pos + x > entry->text_length) + editable->current_pos = entry->text_length; + else + editable->current_pos += x; /* Ignore vertical motion */ } @@ -1974,26 +1906,18 @@ static void gtk_entry_move_word (GtkEditable *editable, gint n) { - if (n > 0) - { - while (n-- != 0) - gtk_move_forward_word (GTK_ENTRY (editable)); - } - else if (n < 0) - { - while (n++ != 0) - gtk_move_backward_word (GTK_ENTRY (editable)); - } + while (n-- > 0) + gtk_move_forward_word (GTK_ENTRY (editable)); + while (n++ < 0) + gtk_move_backward_word (GTK_ENTRY (editable)); } static void gtk_move_forward_word (GtkEntry *entry) { GtkEditable *editable; - gchar *text; + GdkWChar *text; gint i; - wchar_t c; - gint len; editable = GTK_EDITABLE (entry); @@ -2002,45 +1926,20 @@ gtk_move_forward_word (GtkEntry *entry) text = entry->text; i = editable->current_pos; - if (gtk_use_mb) + if ((entry->use_wchar) ? (!gdk_iswalnum (text[i])) : (!isalnum (text[i]))) + for (; i < entry->text_length; i++) + { + if ((entry->use_wchar) ? gdk_iswalnum (text[i]) : isalnum (text[i])) + break; + } + + for (; i < entry->text_length; i++) { - len = mbtowc (&c, text+i, MB_CUR_MAX); - if (!iswalnum(c)) - for (; i < entry->text_length; i+=len) - { - len = mbtowc (&c, text+i, MB_CUR_MAX); - if (len < 1 || iswalnum(c)) - break; - } - - for (; i < entry->text_length; i+=len) - { - len = mbtowc (&c, text+i, MB_CUR_MAX); - if (len < 1 || !iswalnum(c)) - break; - } - - editable->current_pos = i; - if (editable->current_pos > entry->text_length) - editable->current_pos = entry->text_length; + if ((entry->use_wchar) ? (!gdk_iswalnum (text[i])) : (!isalnum (text[i]))) + break; } - else - { - if (!isalnum (text[i])) - for (; i < entry->text_length; i++) - { - if (isalnum(text[i])) - break; - } - - for (; i < entry->text_length; i++) - { - if (!isalnum(text[i])) - break; - } - editable->current_pos = i; - } + editable->current_pos = i; } } @@ -2048,70 +1947,34 @@ static void gtk_move_backward_word (GtkEntry *entry) { GtkEditable *editable; - gchar *text; + GdkWChar *text; gint i; - wchar_t c; editable = GTK_EDITABLE (entry); if (entry->text && editable->current_pos > 0) { text = entry->text; - - if (gtk_use_mb) + i = editable->current_pos - 1; + if ((entry->use_wchar) ? (!gdk_iswalnum (text[i])) : (!isalnum (text[i]))) + for (; i >= 0; i--) + { + if ((entry->use_wchar) ? gdk_iswalnum (text[i]) : isalnum (text[i])) + break; + } + for (; i >= 0; i--) { - i = gtk_entry_find_char (entry, editable->current_pos - 1); - - mbtowc (&c, text+entry->char_pos[i], MB_CUR_MAX); - if (!iswalnum(c)) - for (; i >= 0; i--) - { - mbtowc (&c, text+entry->char_pos[i], MB_CUR_MAX); - if (iswalnum(c)) - break; - } - - for (; i >= 0; i--) + if ((entry->use_wchar) ? (!gdk_iswalnum (text[i])) : (!isalnum (text[i]))) { - mbtowc (&c, text+entry->char_pos[i], MB_CUR_MAX); - if (!iswalnum(c)) - { - i++; - break; - } + i++; + break; } - - if (i < 0) - i = 0; - - editable->current_pos = entry->char_pos[i]; } - else - { - i = editable->current_pos - 1; - - if (!isalnum(text[i])) - for (; i >= 0; i--) - { - if (isalnum(text[i])) - break; - } - - for (; i >= 0; i--) - { - if (!isalnum(text[i])) - { - i++; - break; - } - } - if (i < 0) - i = 0; + if (i < 0) + i = 0; - editable->current_pos = i; - } - + editable->current_pos = i; } } @@ -2122,10 +1985,10 @@ gtk_entry_move_to_column (GtkEditable *editable, gint column) entry = GTK_ENTRY (editable); - if (column < 0 || column > entry->nchars) + if (column < 0 || column > entry->text_length) editable->current_pos = entry->text_length; else - editable->current_pos = entry->char_pos[column]; + editable->current_pos = column; } static void @@ -2311,6 +2174,45 @@ gtk_entry_set_max_length (GtkEntry *entry, entry->text_max_length = max; } +#ifdef USE_XIM +static void +gtk_entry_update_ic_attr (GtkWidget *widget) +{ + GtkEditable *editable = (GtkEditable *) widget; + GdkICAttributesType mask = 0; + + gdk_ic_get_attr (editable->ic, editable->ic_attr, + GDK_IC_PREEDIT_FOREGROUND | + GDK_IC_PREEDIT_BACKGROUND | + GDK_IC_PREEDIT_FONTSET); + + if (editable->ic_attr->preedit_foreground.pixel != + widget->style->fg[GTK_STATE_NORMAL].pixel) + { + mask |= GDK_IC_PREEDIT_FOREGROUND; + editable->ic_attr->preedit_foreground + = widget->style->fg[GTK_STATE_NORMAL]; + } + if (editable->ic_attr->preedit_background.pixel != + widget->style->base[GTK_STATE_NORMAL].pixel) + { + mask |= GDK_IC_PREEDIT_BACKGROUND; + editable->ic_attr->preedit_background + = widget->style->base[GTK_STATE_NORMAL]; + } + if ((gdk_ic_get_style (editable->ic) & GDK_IM_PREEDIT_POSITION) && + !gdk_font_equal (editable->ic_attr->preedit_fontset, + widget->style->font)) + { + mask |= GDK_IC_PREEDIT_FONTSET; + editable->ic_attr->preedit_fontset = widget->style->font; + } + + if (mask) + gdk_ic_set_attr (editable->ic, editable->ic_attr, mask); +} +#endif /* USE_XIM */ + static void gtk_entry_style_set (GtkWidget *widget, GtkStyle *previous_style) @@ -2332,6 +2234,10 @@ gtk_entry_style_set (GtkWidget *widget, 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)]); + +#ifdef USE_XIM + gtk_entry_update_ic_attr (widget); +#endif } if (GTK_WIDGET_DRAWABLE (widget)) @@ -2349,6 +2255,10 @@ gtk_entry_state_changed (GtkWidget *widget, { gdk_window_set_background (widget->window, &widget->style->base[GTK_WIDGET_STATE (widget)]); gdk_window_set_background (GTK_ENTRY (widget)->text_area, &widget->style->base[GTK_WIDGET_STATE (widget)]); + +#ifdef USE_XIM + gtk_entry_update_ic_attr (widget); +#endif } if (GTK_WIDGET_DRAWABLE (widget)) |