Re: GtkEntry needs to be fixed in order to work correctly with fonts (not fontsets) under non-latin1 single-byte locale



Vlad Harchev <hvv hippo ru> writes:

> > If you can get me a patch by tomorrow morning, my time, that:
> >  
> >  - Fixes all occurences of conversion between characters and bytes
> >    by direct assignment by using the GDK functions.
> > 
> >    (Note that this occurs in GtkText as well - see, e.g., line 3773)
> > 
> >  - Is thoroughly tested out. 
> >    
> > Then I'll consider it for inclusion in 1.2.10. But I don't want to
> > just make random changes in hopes of moving forward.
> > 
> > Thanks,
> >                                         Owen
> 
>  Here are the patch against gtkentry.c (tested with and without fontsets under
> russian locale, with and without use_std_env in XLC_LOCALE) - everything seems
> to work fine (and the bug is fixed by it of course).
> 
>  Also a small patch to GtkText attached of the similar brand. Though I never
> triggered a problem it potentially fixes, so it's not that necessary to apply
> it..

I had absolutely no trouble causing GTK+ to die with an assertion failure
in about two seconds with LC_ALL=koi8-r, a font (not fontset), and without
this patch.

So, I think it's pretty necessary to apply it if you want this to work.
 
>  What do you think of them? Will they go into gtk-1.2.10?

The attached patch is basically your patch, with some cleanups. I've
also added a small fix for the handling of '*' which was broken in
a similar way, though I don't think it was causing any problems.

I do plan to apply this for 1.2.10.

Thanks,
                                        Owen

? memprof.out1
? memprof.out2
? russian.xkm
Index: gtkentry.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkentry.c,v
retrieving revision 1.75.2.8
diff -u -r1.75.2.8 gtkentry.c
--- gtkentry.c	2001/02/22 20:38:13	1.75.2.8
+++ gtkentry.c	2001/03/15 20:15:44
@@ -374,6 +374,48 @@
   return GTK_WIDGET (gtk_type_new (GTK_TYPE_ENTRY));
 }
 
+static GdkWChar
+gtk_entry_get_invisible_char (GtkEntry *entry)
+{
+  GdkWChar ch;
+
+  if (entry->use_wchar)
+    gdk_mbstowcs (&ch, "*", 1);
+  else
+    ch = '*';
+
+  return ch;
+}
+
+/*
+ * Draws the string, noting that if entry->use_wchar is false, then
+ * the text is not really wide characters, but narrow characters
+ * stored as wide characters.
+ */
+static void
+gtk_entry_draw_wchars (GtkEntry       *entry,
+		       GdkDrawable    *drawable,
+		       GdkFont	      *font,
+		       GdkGC	      *gc,
+		       gint	       x,
+		       gint	       y,
+		       const GdkWChar *text,
+		       gint	       text_length)
+{
+  if (entry->use_wchar)
+    gdk_draw_text_wc (drawable, font, gc, x, y, text, text_length);
+  else
+    {
+      gint i;
+      gchar *mbstr = g_new (gchar, text_length);
+      
+      for (i = 0; i < text_length; i++)
+        mbstr[i] = text[i];
+      gdk_draw_text (drawable, font, gc, x, y, mbstr, text_length);
+      g_free(mbstr);
+    }
+}
+
 GtkWidget*
 gtk_entry_new_with_max_length (guint16 max)
 {
@@ -1398,19 +1440,20 @@
       else
 	{
 	  gint i;
+	  GdkWChar invisible_char = gtk_entry_get_invisible_char (entry);
 	  
 	  stars = g_new (GdkWChar, end_pos - start_pos);
 	  for (i = 0; i < end_pos - start_pos; i++)
-	    stars[i] = '*';
+	    stars[i] = invisible_char;
 	  toprint = stars;
 	}
       
       if (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);
+	gtk_entry_draw_wchars (entry, 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) &&
@@ -1423,19 +1466,19 @@
 				INNER_BORDER,
 				selection_end_xoffset - selection_start_xoffset,
 				height - 2*INNER_BORDER);
-	    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);
+	    gtk_entry_draw_wchars (entry, 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_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);
+	 gtk_entry_draw_wchars (entry, 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 (!editable->visible)
 	g_free (toprint);
@@ -1510,9 +1553,9 @@
 		                 *(entry->text + editable->current_pos) :
 		                 '*';
 	      
-	      gdk_draw_text_wc (drawable, widget->style->font,
-				widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
-				xoffset, yoffset, &c, 1);
+	      gtk_entry_draw_wchars (entry, drawable, widget->style->font,
+				     widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+				     xoffset, yoffset, &c, 1);
 	    }
 	}
 
@@ -1780,21 +1823,23 @@
       gint offset = 0;
       
       for (i = last_pos; i >= end_pos; i--)
-	entry->char_offset[i] 
-	  = entry->char_offset[i - insertion_length];
+	entry->char_offset[i] = entry->char_offset[i - insertion_length];
       
       for (i=start_pos; i<end_pos; i++)
 	{
+	  GdkWChar ch;
+
 	  entry->char_offset[i] = entry->char_offset[start_pos] + offset;
+
 	  if (editable->visible)
-	    {
-	      offset += gdk_char_width_wc (GTK_WIDGET (entry)->style->font,
-					   entry->text[i]);
-	    }
+	    ch = entry->text[i];
+	  else 
+	    ch = gtk_entry_get_invisible_char (entry);
+
+	  if (entry->use_wchar)
+	    offset += gdk_char_width_wc (GTK_WIDGET (entry)->style->font, ch);
 	  else
-	    {
-	      offset += gdk_char_width (GTK_WIDGET (entry)->style->font, '*');
-	    }
+	    offset += gdk_char_width (GTK_WIDGET (entry)->style->font, ch);
 	}
       for (i = end_pos; i <= last_pos; i++)
 	entry->char_offset[i] += offset;
@@ -1813,21 +1858,25 @@
 {
   gint i;
   gint offset = 0;
+  GtkEditable *editable = GTK_EDITABLE (entry);
 
   for (i=0; i<entry->text_length; i++)
     {
+      GdkWChar ch;
+
       entry->char_offset[i] = offset;
-      if (GTK_EDITABLE (entry)->visible)
-	{
-	  offset += gdk_char_width_wc (GTK_WIDGET (entry)->style->font,
-				       entry->text[i]);
-	}
+
+      if (editable->visible)
+	ch = entry->text[i];
       else
-	{
-	  offset += gdk_char_width (GTK_WIDGET (entry)->style->font, '*');
-	}
-    }
+	ch = gtk_entry_get_invisible_char (entry);
 
+      if (entry->use_wchar)
+	offset += gdk_char_width_wc (GTK_WIDGET (entry)->style->font, ch);
+      else
+	offset += gdk_char_width (GTK_WIDGET (entry)->style->font, ch);
+    }
+  
   entry->char_offset[i] = offset;
 }
 
Index: gtktext.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtktext.c,v
retrieving revision 1.79.2.10
diff -u -r1.79.2.10 gtktext.c
--- gtktext.c	2001/02/22 20:38:15	1.79.2.10
+++ gtktext.c	2001/03/15 20:15:44
@@ -5041,7 +5041,7 @@
 	        pixel_width = gdk_text_width_wc (gc_values.font,
 						 buffer.wc, len);
 	      else
-	      pixel_width = gdk_text_width (gc_values.font,
+		pixel_width = gdk_text_width (gc_values.font,
 					      buffer.ch, len);
 	    }
 	  else
@@ -5205,15 +5205,26 @@
 	{
 	  if (font->type == GDK_FONT_FONT)
 	    gdk_gc_set_font (text->gc, font);
-
+	  
 	  gdk_gc_set_foreground (text->gc, MARK_CURRENT_FORE (text, &text->cursor_mark));
-
-	  gdk_draw_text_wc (text->text_area, font,
-			 text->gc,
-			 text->cursor_pos_x,
-			 text->cursor_pos_y - text->cursor_char_offset,
-			 &text->cursor_char,
-			 1);
+	  
+          if (text->use_wchar)
+	    gdk_draw_text_wc (text->text_area, font,
+			      text->gc,
+			      text->cursor_pos_x,
+			      text->cursor_pos_y - text->cursor_char_offset,
+			      &text->cursor_char,
+			      1);
+	  else
+	    {
+	      guchar ch = text->cursor_char;
+	      gdk_draw_text (text->text_area, font,
+			     text->gc,
+			     text->cursor_pos_x,
+			     text->cursor_pos_y - text->cursor_char_offset,
+			     (gchar *)&ch,
+			     1);         
+	    }
 	}
     }
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]