[PATCH] Backport to 1.2.4 of snake_oil+mem cleanups



	Hi all,
here is the backport of Peter's snake_oil patch + my cleanups for 
address-entry.c.
Bye
Manu
--- ../balsa-1.2.4/libbalsa/address-entry.c	Tue Jan 15 20:47:56 2002
+++ balsa-1.2.4-peter/libbalsa/address-entry.c	Wed Jan 30 19:34:16 2002
@@ -21,21 +21,6 @@
  */
 
 /*
- * FIXME:
- *
- * Need to add credits, I think... How do we do that?
- *
- * Parts of this code is copied out of GTK+.  GTK+ is licensed
- * under the LGPL, and Balsa under the GPL.  The consensus among
- * all parties involved (Balsa maintainers, GTK+, and GNU (for
- * writing the license)) this is legal.  The new and cut&pasted
- * code has to be GPL-ed.
- *
- * I would like to thank the GTK+ Authors at this point
- * for their work.
- */
-
-/*
  * A subclass of gtkentry to support alias completion.
  */
 
@@ -49,12 +34,6 @@
 #include <sys/stat.h>
 #include <ctype.h>
 
-/* pawsa: the update of cursor pos is completely reduntant with gtk+-1.2.9
-   and since the char_offsets happens to be shorter than computed cursor_pos,
-   the entry tends to move the alignment left and right.
-   I disable it.
-*/
-#define DISABLE_UPDATE_CUR_POS
 /*
  * LibBalsa includes.
  */
@@ -62,12 +41,6 @@
 #include "address-entry.h"
 
 /*
- * Internal API definitiions.
- */
-#define DRAW_TIMEOUT	20
-#define INNER_BORDER	2
-
-/*
  * Global variable.  We need this for destroying this widget.
  */
 static GtkWidgetClass *parent_class = NULL;
@@ -87,25 +60,12 @@
 inputData *libbalsa_inputData_new(void);
 emailData *libbalsa_emailData_new(void);
 void libbalsa_emailData_free(emailData *addy);
-static gint libbalsa_address_entry_timer(gpointer);
-static gint libbalsa_address_entry_find_position(LibBalsaAddressEntry *, gint);
-static void libbalsa_address_entry_make_backing_pixmap(LibBalsaAddressEntry *,
-						       gint, gint);
-static void libbalsa_address_entry_queue_draw(LibBalsaAddressEntry *);
-static void libbalsa_address_entry_draw_cursor_on_drawable(
-					LibBalsaAddressEntry *, GdkDrawable *);
-static void libbalsa_address_entry_delete_text(GtkEditable *, 
-					       unsigned, unsigned);
-static void libbalsa_address_entry_draw(GtkWidget *, GdkRectangle *);
 static gint libbalsa_address_entry_button_press(GtkWidget *, GdkEventButton *);
-static void libbalsa_address_entry_draw_cursor(LibBalsaAddressEntry *);
-static void libbalsa_address_entry_draw_text(LibBalsaAddressEntry *);
 static gint libbalsa_address_entry_key_press(GtkWidget *, GdkEventKey *);
 inputData *libbalsa_address_entry_get_input(LibBalsaAddressEntry *entry);
 void libbalsa_address_entry_set_input(LibBalsaAddressEntry *entry,
 				      inputData *data);
 void libbalsa_address_entry_show(LibBalsaAddressEntry *entry);
-void libbalsa_address_entry_set_text(LibBalsaAddressEntry *, const gchar *);
 void libbalsa_force_no_match(emailData *);
 void libbalsa_address_entry_clear_match(LibBalsaAddressEntry *);
 void libbalsa_address_entry_set_focus(LibBalsaAddressEntry *, gint);
@@ -245,35 +205,10 @@
 
     object_class->destroy = libbalsa_address_entry_destroy;
 
-    gtk_widget_class->draw = libbalsa_address_entry_draw;
     klass->gtk_entry_button_press = gtk_widget_class->button_press_event;
     gtk_widget_class->button_press_event = libbalsa_address_entry_button_press;
     gtk_widget_class->key_press_event = libbalsa_address_entry_key_press;
-    /*
-     * FIXME: PLEASE HELP!
-     *
-     * If I set the focus_out function here, GTK+ spits out error messages
-     * a few times a second.  According to gdb, these happen inside poll(),
-     * inside GTK+.
-     *
-     * If src/sendmsg-window.c() assigns this function via
-     * gtk_signal_connect(), and nothing else changes, the bug does
-     * NOT appear.
-     *
-     * It is reproducable with:
-     * - The current source.
-     * - Using gtk+-1.2.8/gtk/gtkentry.c's focus_out() function.
-     * - An empty focus_out() function.
-     *
-     * It appears to be a stray GtkObject reference somewhere, that
-     * doesn't get released, which makes gtk/poll() call an invalid
-     * widget.
-     *
-     * Berend De Schouwer <bds@jhb.ucs.co.za>
-     */
-#if 0
     gtk_widget_class->focus_out_event = libbalsa_address_entry_focus_out;
-#endif
 }
 
 
@@ -468,6 +403,7 @@
     g_return_if_fail(data != NULL);
 
     g_list_foreach(data->list, (GFunc) libbalsa_emailData_free, NULL);
+    g_list_free(data->list);
     g_free(data);
 }
 
@@ -538,36 +474,25 @@
 libbalsa_strsplit(const gchar *str, gchar delimiter)
 {
     GList *glist;
-    gchar *data;
     const gchar *old, *current;
-    gint i, previous;
     gboolean quoted;
 
-    g_return_val_if_fail(str != NULL, NULL);
+    if (!str) return NULL;
 
     quoted = FALSE;
     glist = NULL;
-    previous = 0;
-    old = current = str;
-    for (i = 0; str[i]; i++) {
-	if (str[i] == '"') quoted = !quoted;
-	if ( (!quoted) && (str[i] == delimiter) ) {
-	    data = g_strndup(old, i - previous);
-	    glist = g_list_append(glist, data);
-	    previous = i + 1;
-	    old = current;
-	    old++;
+    old = str;
+    for (current=str;*current;current++) {
+	if (*current == '"') quoted = !quoted;
+	else if ( (!quoted) && (*current == delimiter) ) {
+	    glist = g_list_append(glist, g_strndup(old, current-old));
+	    old=current+1;
 	}
-	current++;
-    }
-    if (str) {
-	data = g_strndup(old, i - previous);
-	glist = g_list_append(glist, data);
     }
+    glist = g_list_append(glist, g_strndup(old, current-old));
     return glist;
 }
 
-
 /*************************************************************
  * libbalsa_length_of_address:
  *     Calculated how long an address would be when it is
@@ -706,7 +631,7 @@
 static inputData *
 libbalsa_fill_input(LibBalsaAddressEntry *address_entry)
 {
-    gint cursor = 0, size = 0, prev = 0;
+    gint cursor, size, prev=0;
     gchar *typed = NULL;
     GList *el, *current;
     GList *list = NULL;
@@ -723,30 +648,28 @@
     input = libbalsa_inputData_new();
     cursor = (gint) gtk_editable_get_position(GTK_EDITABLE(address_entry));
     typed = gtk_editable_get_chars(GTK_EDITABLE(address_entry), 0, -1);
-    if (typed == NULL)
+    if (!typed)
 	typed = g_strdup("");
 
     /*
      * Split the input string by comma, and store the result in
      * input->list.
      * str contains a list of e-mail addresses seperated by ','.
-     *
-     * FIXME: Breaks for '"Doe, John" <john@doe.com>'
      */
     el = libbalsa_strsplit(typed, ',');
     g_free(typed);
     /*
      * Store it all in a glist.
      */
-    if (el != NULL) {
+    if (el) {
 	for (current = el;
-	     current != NULL;
+	     current;
 	     current = g_list_next(current)) {
 	    addy = libbalsa_emailData_new();
-	    addy->user = g_strdup((gchar *)current->data);
+	    addy->user = (gchar *)current->data;
 	    input->list = g_list_append(input->list, addy);
 	}
-	g_list_foreach(el, (GFunc)g_free, NULL);
+	g_list_free(el);
     } else {
        addy = libbalsa_emailData_new();
        addy->user = g_strdup("");
@@ -758,69 +681,34 @@
      * We have to match the cursor in GtkEntry to the list.
      */
     g_assert(input->list != NULL);
-    size = prev = 0;
-    for (list = g_list_first(input->list);
-	 list != NULL;
-	 list = g_list_next(list)) {
-	if (cursor >= size) {
-	    prev = size;
-	    input->active = list;
-	}
+    size = 0;
+    for (list = g_list_first(input->list);list;list=g_list_next(list)) {
+	prev=size;
+	addy = (emailData *)list->data;
+	size += strlen(addy->user) + 1;
+	addy->user = g_strchug(addy->user);
+	if (cursor<size) break;
+    }
+    input->active = list;
+    /* Don't forget to strip out the leading space added because
+       the delimiter to split the addresses was just ',' so each
+       address begins with the space following the coma */
+    for (list = g_list_next(list);list;list=g_list_next(list)) {
 	addy = (emailData *)list->data;
-	size = size + strlen(addy->user) + 1;
 	addy->user = g_strchug(addy->user);
     }
-
     addy = (emailData *)input->active->data;
     addy->cursor = cursor - prev;
     if (input->active != input->list)
-	addy->cursor = addy->cursor - 1; /* Compensate for the ',' */
+	addy->cursor--; /* Compensate for the ',' */
     if (addy->cursor < 0) addy->cursor = 0;
-    if (addy->cursor > (tmp = strlen(addy->user)))
-        addy->cursor = tmp;
+    tmp = strlen(addy->user);
+    if (addy->cursor > tmp)
+	addy->cursor = tmp;
 
     return input;
 }
 
-
-/*************************************************************
- * libbalsa_address_entry_set_text:
- *     Sets the text string of a LibBalsaAddressEntry without
- *     drawing the text.
- *
- *   credits:
- *     Modified from gtk+-1.2.8/gtk/gtkentry.c
- *
- *   arguments:
- *     address_entry: The LibBalsaAddressEntry to act on.
- *     text:          A gchar* string to set the text to.
- *
- *   results:
- *     Sets the text in the widget.
- *************************************************************/
-void
-libbalsa_address_entry_set_text(LibBalsaAddressEntry *address,
-				const gchar *text)
-{
-    gint tmp_pos;
-
-    GtkEditable *editable;
-
-    g_return_if_fail(address != NULL);
-    g_return_if_fail(LIBBALSA_IS_ADDRESS_ENTRY(address));
-    g_return_if_fail(text != NULL);
-
-    editable = GTK_EDITABLE(address);
-    libbalsa_address_entry_delete_text(editable, 0, -1);
-
-    tmp_pos = 0;
-    gtk_editable_insert_text(editable, text, strlen(text), &tmp_pos);
-
-    editable->selection_start_pos = 0;
-    editable->selection_end_pos = 0;
-}
-
-
 /*************************************************************
  * libbalsa_delete_line:
  *     Deletes the text string of a LibBalsaAddressEntry.
@@ -878,7 +766,7 @@
 	if (list != NULL) {
 	    input->list = g_list_remove_link(input->list, list);
 	    libbalsa_emailData_free(list->data);
-	    g_list_free(list);
+	    g_list_free_1(list);
 	}
 
     /*
@@ -894,13 +782,13 @@
 	    input->active = NULL;
 	input->list = g_list_remove_link(input->list, list);
 	libbalsa_emailData_free(list->data);
-	g_list_free(list);
+	g_list_free_1(list);
 	if (input->active != NULL) {
 	    addy = input->active->data;
 	    g_assert(addy != NULL);
 	    addy->cursor = 0;
 	} else {
-	    libbalsa_address_entry_set_text(address_entry, "");
+	    gtk_entry_set_text(GTK_ENTRY(address_entry), "");
 	    libbalsa_inputData_free(address_entry->input);
 	    address_entry->input = libbalsa_fill_input(address_entry);
 	}
@@ -947,7 +835,7 @@
 	if (list != NULL) {
 	    input->list = g_list_remove_link(input->list, list);
 	    libbalsa_emailData_free(list->data);
-	    g_list_free(list);
+	    g_list_free_1(list);
 	}
 
     /*
@@ -964,17 +852,13 @@
 	}
 	input->list = g_list_remove_link(input->list, list);
 	libbalsa_emailData_free(list->data);
-	/*
-	list->next = NULL;
-	list->prev = NULL;
-	*/
-	g_list_free(list);
+	g_list_free_1(list);
 	if (input->active != NULL) {
 	    addy = input->active->data;
 	    g_assert(addy != NULL);
 	    addy->cursor = strlen(addy->user);
 	} else {
-	    libbalsa_address_entry_set_text(address_entry, "");
+	    gtk_entry_set_text(GTK_ENTRY(address_entry), "");
 	    libbalsa_inputData_free(address_entry->input);
 	    address_entry->input = libbalsa_fill_input(address_entry);
 	}
@@ -1019,440 +903,18 @@
     /*
      * Free all the following data.
      */
-    for (list = g_list_next(input->active);
-	 list != NULL;
-	 list = g_list_next(input->active)) {
-	 /*
-	  * Concatenate the two e-mails.
-	  */
-	 libbalsa_emailData_free(list->data);
-	 input->list = g_list_remove_link(input->list, list);
-	 list->data = NULL;
-	 list->prev = NULL;
-	 list->next = NULL;
-	 g_list_free(list);
-    }
+    g_list_foreach(g_list_next(input->active),(GFunc)libbalsa_emailData_free,NULL);
+    g_list_free(g_list_next(input->active));
+
+    /* input->active must be the last address */
+    input->active->next=NULL;
+
     /* libbalsa_inputData_free(address_entry->input); 
      * look above: the line below is not necessary */
     /* address_entry->input = input; */
     libbalsa_address_entry_show(address_entry);
 }
 
-
-/*************************************************************
- * libbalsa_address_entry_timer:
- *     Is this used to keep it thread-safe? (late at night)
- *     Attempts to call draw_text() if the timer expires.
- *
- *   credits:
- *     This is stolen from gtk+-1.2.8/gtk/gtkentry.c
- *
- *   arguments:
- *     address_entry: The LibBalsaAddressEntry to act on.
- *
- *   results:
- *     ???
- *************************************************************/
-static gint
-libbalsa_address_entry_timer(gpointer data)
-{
-    LibBalsaAddressEntry *address_entry;
-    GtkEntry *entry;
-
-    GDK_THREADS_ENTER ();
-
-    address_entry = LIBBALSA_ADDRESS_ENTRY(data);
-    entry = GTK_ENTRY(data);
-    entry->timer = 0;
-
-    GDK_THREADS_LEAVE ();
-    return TRUE;
-}
-
-
-/*************************************************************
- * libbalsa_address_entry_find_position:
- *     Find the cursor position?
- *
- *   credits:
- *     This is stolen from gtk+-1.2.8/gtk/gtkentry.c
- *
- *   arguments:
- *     address_entry: The LibBalsaAddressEntry to act on.
- *     x:             ???
- *
- *   results:
- *     ???
- *************************************************************/
-static gint
-libbalsa_address_entry_find_position(LibBalsaAddressEntry *address_entry,
-									gint x)
-{
-    GtkEntry *entry;
-    gint start = 0;
-    gint end;
-    gint half;
-
-    g_return_val_if_fail(address_entry != NULL, 0);
-    g_return_val_if_fail(LIBBALSA_IS_ADDRESS_ENTRY(address_entry), 0);
-
-    entry = GTK_ENTRY(address_entry);
-    end = entry->text_length;
-    if (x <= 0)
-	return 0;
-    if (x >= entry->char_offset[end])
-	return end;
-  
-    /* invariant - char_offset[start] <= x < char_offset[end] */
-
-    while (start != end) {
-	half = (start+end)/2;
-	if (half == start)
-	    return half;
-	else if (entry->char_offset[half] <= x)
-	    start = half;
-	else
-	    end = half;
-    }
-    return start;
-}
-
-
-/*************************************************************
- * libbalsa_address_entry_make_backing_pixmap:
- *     Makes a pixmap to draw on if we don't use the widget
- *     directly.
- *
- *   credits:
- *     This is stolen from gtk+-1.2.8/gtk/gtkentry.c
- *
- *   arguments:
- *     address_entry: The LibBalsaAddressEntry to act on.
- *     width:         ???
- *     height:        ???
- *
- *   results:
- *     ???
- *************************************************************/
-static void
-libbalsa_address_entry_make_backing_pixmap(LibBalsaAddressEntry *address_entry,
-							gint width, gint height)
-{
-    GtkEntry *entry;
-    gint pixmap_width, pixmap_height;
-
-    g_return_if_fail(address_entry != NULL);
-    g_return_if_fail(LIBBALSA_IS_ADDRESS_ENTRY(address_entry));
-
-    entry = GTK_ENTRY(address_entry);
-    if (!entry->backing_pixmap) {
-	/* allocate */
-	entry->backing_pixmap = gdk_pixmap_new(entry->text_area,
-		                               width, height, -1);
-    } else {
-	/* reallocate if sizes don't match */
-	gdk_window_get_size(entry->backing_pixmap,
-		            &pixmap_width, &pixmap_height);
-	if ((pixmap_width != width) || (pixmap_height != height)) {
-	    gdk_pixmap_unref(entry->backing_pixmap);
-	    entry->backing_pixmap = gdk_pixmap_new(entry->text_area,
-		                                   width, height, -1);
-	}
-    }
-}
-
-
-/*************************************************************
- * libbalsa_address_entry_queue_draw:
- *     ???
- *
- *   credits:
- *     This is stolen from gtk+-1.2.8/gtk/gtkentry.c
- *
- *   arguments:
- *     address_entry: The LibBalsaAddressEntry to act on.
- *
- *   results:
- *     Sets the text in the widget.
- *************************************************************/
-static void
-libbalsa_address_entry_queue_draw(LibBalsaAddressEntry *address_entry)
-{
-    GtkEntry *entry;
-    g_return_if_fail(address_entry != NULL);
-    g_return_if_fail(LIBBALSA_IS_ADDRESS_ENTRY(address_entry));
-
-    entry = GTK_ENTRY(address_entry);
-    if (!entry->timer)
-	entry->timer = gtk_timeout_add(DRAW_TIMEOUT,
-		                       libbalsa_address_entry_timer, entry);
-}
-
-
-/*************************************************************
- * libbalsa_address_entry_delete_text:
- *     ???
- *
- *   credits:
- *     This is stolen from gtk+-1.2.8/gtk/gtkentry.c
- *
- *   arguments:
- *     editable:	???
- *     start_pos:	???
- *     end_pos:		???
- *
- *   results:
- *     Modifies the text in the widget.
- *************************************************************/
-static void
-libbalsa_address_entry_delete_text(GtkEditable *editable, 
-				   unsigned start_pos, unsigned end_pos)
-{
-    GdkWChar *text;
-    gint deletion_length;
-    unsigned i;
-    GtkEntry *entry;
-  
-    g_return_if_fail(editable != NULL);
-    g_return_if_fail(LIBBALSA_IS_ADDRESS_ENTRY(editable));
-
-    entry = GTK_ENTRY(editable);
-
-    if (end_pos == (unsigned) -1)
-	end_pos = entry->text_length;
-
-    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)
-	editable->selection_end_pos -= MIN(end_pos, editable->selection_end_pos) - start_pos;
-  
-    if ((start_pos < end_pos) &&
-	(start_pos >= 0) &&
-	(end_pos <= entry->text_length)) {
-	text = entry->text;
-	deletion_length = end_pos - start_pos;
-
-	/* Fix up the character offsets */
-	if (GTK_WIDGET_REALIZED (entry)) {
-	    gint deletion_width = 
-		entry->char_offset[end_pos] - entry->char_offset[start_pos];
-	    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++)
-	    text[i - deletion_length] = text[i];
-
-	for (i = entry->text_length - deletion_length; i < entry->text_length; i++)
-	    text[i] = '\0';
-	entry->text_length -= deletion_length;
-	editable->current_pos = start_pos;
-    }
-
-    entry->text_mb_dirty = 1;
-    libbalsa_address_entry_queue_draw (LIBBALSA_ADDRESS_ENTRY(editable));
-}
-
-
-/*************************************************************
- * libbalsa_address_entry_draw_cursor_on_drawable:
- *     For once, its clear :)  Maybe.
- *     Usually you'll want to use
- *     libbalsa_address_entry_draw_cursor() instead.
- *
- *   credits:
- *     This is stolen from gtk+-1.2.8/gtk/gtkentry.c
- *
- *   arguments:
- *     address_entry: the widget.
- *     drawable:      foreground or background.
- *
- *   results:
- *     None?  Changes the appearance of the widget.
- *************************************************************/
-static void
-libbalsa_address_entry_draw_cursor_on_drawable(
-		    LibBalsaAddressEntry *address_entry, GdkDrawable *drawable)
-{
-    GtkWidget *widget;
-    GtkEditable *editable;
-    GtkEntry *entry;
-    gint xoffset;
-    gint text_area_height;
-
-    g_return_if_fail(address_entry != NULL);
-    g_return_if_fail(LIBBALSA_IS_ADDRESS_ENTRY(address_entry));
-
-    entry = GTK_ENTRY(address_entry);
-    widget = GTK_WIDGET (entry);
-    editable = GTK_EDITABLE (entry);
-
-    if (! (GTK_WIDGET_DRAWABLE(entry))) return;
-
-    xoffset = INNER_BORDER + entry->char_offset[editable->current_pos];
-    xoffset -= entry->scroll_offset;
-    gdk_window_get_size (entry->text_area, NULL, &text_area_height);
-
-    if (GTK_WIDGET_HAS_FOCUS(widget) &&
-	  (editable->selection_start_pos == editable->selection_end_pos)) {
-	gdk_draw_line(drawable, widget->style->fg_gc[GTK_STATE_NORMAL], 
-		      xoffset, INNER_BORDER,
-		      xoffset, text_area_height - INNER_BORDER);
-    } else {
-	gint yoffset = 
-	    (text_area_height - 
-	    (widget->style->font->ascent + widget->style->font->descent)) / 2
-	    + widget->style->font->ascent;
-	gtk_paint_flat_box(widget->style, drawable,
-		           GTK_WIDGET_STATE(widget), GTK_SHADOW_NONE,
-		           NULL, widget, "entry_bg", 
-		           xoffset, INNER_BORDER, 
-		           1, text_area_height - INNER_BORDER);
-	  
-	/*
-	 * Draw the character under the cursor again
-	 */
-	if ((editable->current_pos < entry->text_length) &&
-	      (editable->selection_start_pos == editable->selection_end_pos)) {
-	     GdkWChar c = editable->visible ?
-		                 *(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);
-	}
-    }
-
-    /*
-     * This #ifdef won't ever be true in Balsa.  Does this break
-     * things if GTK was compiled with USE_XIM?
-     */
-#ifdef USE_XIM
-    if (GTK_WIDGET_HAS_FOCUS(widget) && gdk_im_ready() && editable->ic && 
-	  (gdk_ic_get_style (editable->ic) & GDK_IM_PREEDIT_POSITION)) {
-	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;
-	gdk_ic_set_attr(editable->ic, editable->ic_attr, GDK_IC_SPOT_LOCATION);
-    }
-#endif
-}
-
-
-/*************************************************************
- * libbalsa_address_entry_draw_cursor:
- *     Draws the cursor.
- *
- *   credits:
- *     This is stolen from gtk+-1.2.8/gtk/gtkentry.c
- *
- *   arguments:
- *     address_entry: the widget.
- *
- *   results:
- *     None?  Changes the appearance of the widget.
- *************************************************************/
-static void
-libbalsa_address_entry_draw_cursor(LibBalsaAddressEntry *address_entry)
-{
-    g_return_if_fail(address_entry != NULL);
-    g_return_if_fail(LIBBALSA_IS_ADDRESS_ENTRY(address_entry));
-
-    libbalsa_address_entry_draw_cursor_on_drawable(address_entry,
-					GTK_ENTRY(address_entry)->text_area);
-}
-
-
-/*************************************************************
- * libbalsa_address_entry_draw:
- *     Draws the entire widget.
- *
- *   credits:
- *     This is stolen from gtk+-1.2.8/gtk/gtkentry.c
- *
- *   arguments:
- *     widget: the widget.
- *     area:   ignored.
- *
- *   results:
- *     None?  Changes the appearance of the widget.
- *************************************************************/
-static void
-libbalsa_address_entry_draw(GtkWidget *widget, GdkRectangle *area)
-{
-    g_return_if_fail(widget != NULL);
-    g_return_if_fail(LIBBALSA_IS_ADDRESS_ENTRY(widget));
-    g_return_if_fail(area != NULL);
- 
-    if (GTK_WIDGET_DRAWABLE(widget)) {
-	gtk_widget_draw_focus(widget);
-	libbalsa_address_entry_draw_text(LIBBALSA_ADDRESS_ENTRY(widget));
-    }
-}
-
-
-/*************************************************************
- * libbalsa_address_entry_adjust_scroll:
- *     ???
- *
- *   credits:
- *     This is stolen from gtk+-1.2.8/gtk/gtkentry.c
- *
- *   arguments:
- *     address_entry: the widget.
- *
- *   results:
- *     None?  Changes the appearance of the widget.
- *************************************************************/
-static void
-libbalsa_address_entry_adjust_scroll(LibBalsaAddressEntry *address_entry)
-{
-    GtkEntry *entry;
-    gint xoffset, max_offset;
-    gint text_area_width;
-
-    g_return_if_fail(address_entry != NULL);
-    g_return_if_fail(LIBBALSA_IS_ADDRESS_ENTRY(address_entry));
-
-    entry = GTK_ENTRY(address_entry);
-    if (!entry->text_area)
-	return;
-
-    gdk_window_get_size(entry->text_area, &text_area_width, NULL);
-    text_area_width -= 2 * INNER_BORDER;
-
-    /* Display as much text as we can */
-    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. Note that the cursor is
-     * actually drawn one pixel into the INNER_BORDER space on
-     * the right, when the scroll is at the utmost right. This
-     * looks better to to me than confining the cursor inside the
-     * border entirely, though it means that the cursor gets one
-     * pixel closer to the the edge of the widget on the right than
-     * on the left. This might need changing if one changed
-     * INNER_BORDER from 2 to 1, as one would do on a
-     * small-screen-real-estate display.
-     */
-    xoffset = entry->char_offset[GTK_EDITABLE(entry)->current_pos];
-    xoffset -= entry->scroll_offset;
-
-    if (xoffset < 0)
-	entry->scroll_offset += xoffset;
-    else if (xoffset > text_area_width)
-	entry->scroll_offset += xoffset - text_area_width;
-
-    gtk_widget_queue_draw(GTK_WIDGET(entry));
-}
-
-
 /*************************************************************
  * libbalsa_address_entry_button_press:
  *     This gets called when the user clicks a mouse button.
@@ -1545,7 +1007,7 @@
 {
     GtkEditable *editable;
     emailData *addy, *extra;
-    gchar *left, *right, *str;
+    gchar *p,*str;
     GList *list;
     unsigned i;
     inputData *input;
@@ -1592,8 +1054,7 @@
 	    */
 	   input->list = g_list_remove_link(input->list, input->active);
 	   libbalsa_emailData_free(addy);
-	   input->active->data = NULL;
-	   g_list_free(input->active);
+	   g_list_free_1(input->active);
 	   input->active = list;
        }
 
@@ -1601,18 +1062,12 @@
      * Normal character needs deleting.
      */
     } else {
-       left = g_strndup(addy->user, (addy->cursor - 1));
-       right = addy->user;
-       for (i = 0; i < addy->cursor; i++) right++;
-       str = g_strconcat(left, right, NULL);
-       g_free(addy->user);
-       g_free(left);
-       addy->user = str;
-       addy->cursor--;
-       if (*str == '\0')
-	   libbalsa_force_no_match(addy);
-       else if (address_entry->find_match)
-	   (*address_entry->find_match) (addy, TRUE);
+	addy->cursor--;
+	for (p=addy->user+addy->cursor;*p;p++) *p=*(p+1);
+	if (!*(addy->user))
+	    libbalsa_force_no_match(addy);
+	else if (address_entry->find_match)
+	    (*address_entry->find_match) (addy, TRUE);
     }
 }
 
@@ -1640,7 +1095,7 @@
 {
     GtkEditable *editable;
     emailData *addy, *extra;
-    gchar *left, *right, *str;
+    gchar *p, *str;
     GList *list;
     inputData *input;
     
@@ -1680,21 +1135,13 @@
 	     */
 	    input->list = g_list_remove_link(input->list, list);
 	    libbalsa_emailData_free(extra);
-	    list->data = NULL;
-	    g_list_free(list);
+	    g_list_free_1(list);
 	}
     /*
      * Normal character needs deleting.
      */
     } else {
-	unsigned i;
-	left = g_strndup(addy->user, addy->cursor);
-	right = addy->user;
-	for (i = 0; i <= addy->cursor; i++) right++;
-	str = g_strconcat(left, right, NULL);
-	g_free(addy->user);
-	g_free(left);
-	addy->user = str;
+	for (p=addy->user+addy->cursor;*p;p++) *p=*(p+1);
     }
 }
 
@@ -2118,7 +1565,7 @@
      */
     input = address_entry->input;
     addy = input->active->data;
-    if (input->active == g_list_last(input->list)) {
+    if (!g_list_next(input->active)) {
 	if (addy->cursor >= strlen(addy->user) && (addy->match == NULL)) {
 	    libbalsa_accept_match(address_entry);
 	    gtk_widget_activate(GTK_WIDGET(address_entry));
@@ -2161,7 +1608,7 @@
     gint address_start;
     gboolean found;
     emailData *addy;
-    gint pos;
+    gint pos,tmp;
 
     g_return_val_if_fail(address_entry != NULL, NULL);
     g_return_val_if_fail(LIBBALSA_IS_ADDRESS_ENTRY(address_entry), NULL);
@@ -2174,17 +1621,20 @@
 	 (list != NULL) && (found == FALSE);
 	 list = g_list_next(list)) {
 	addy = (emailData *)list->data;
-	address_start += libbalsa_length_of_address(addy);
+	tmp=libbalsa_length_of_address(addy);
+	address_start += tmp;
 	if (pos <= address_start) {
 	    found = TRUE;
-	    *cursor = libbalsa_length_of_address(addy) - (address_start - pos);
+	    *cursor = tmp - (address_start - pos);
 	}
 	address_start += 2; /* strlen(", ") */
 	previous = list;
     }
     g_assert(found == TRUE);
     if(*cursor<0) { /* error, correct it and print a warning.
-		       This needs to be fixed in long term. */
+		       This needs to be fixed in long term. 
+		       I found where this is triggered, I'll try
+		       to fix it definitely (MANU)*/
 	*cursor = 0;
 	g_warning("libbalsa_find_list_entry failed to compute the cursor.\n"
 		  "find a way to reproduce it and report it.");
@@ -2192,46 +1642,6 @@
     return previous;
 }
 
-#ifndef DISABLE_UPDATE_CUR_POS
-/*************************************************************
- * libbalsa_address_entry_update_cursor_pos:
- *     Sets the cursor position without modifying the
- *     selection information.
- *
- *   arguments:
- *     address_entry: the widget.
- *
- *   results:
- *     modifies address_entry->current_pos;
- *************************************************************/
-static void
-libbalsa_address_entry_update_cursor_pos(LibBalsaAddressEntry *address_entry)
-{
-    GList *list;
-    gint i;
-    gboolean found;
-    emailData *addy;
-
-    g_return_if_fail(address_entry != NULL);
-    g_return_if_fail(LIBBALSA_IS_ADDRESS_ENTRY(address_entry));
-
-    i = 0;
-    found = FALSE;
-    for (list = address_entry->input->list;
-	 (list != NULL) && (found == FALSE);
-	 list = g_list_next(list)) {
-	if (list == address_entry->input->active) {
-	    found = TRUE;
-	    addy = (emailData *)list->data;
-	    i = i + addy->cursor;
-	} else {
-	    addy = (emailData *)list->data;
-	    i = i + strlen(addy->user) + 2;
-	}
-    }
-    GTK_EDITABLE(address_entry)->current_pos = i;
-}
-#endif
 /*************************************************************
  * libbalsa_force_expand:
  *     force alias expansion.
@@ -2296,7 +1706,7 @@
     GtkEditable *editable;
     GList *start, *end, *list;
     gint start_pos, end_pos;
-    gchar *str, *left, *right, *new;
+    gchar *str, *left, *new;
     emailData *addy;
     gint i;
     size_t tmp;
@@ -2328,12 +1738,11 @@
 	addy = start->data;
 	str = libbalsa_make_address_string(addy);
 	libbalsa_force_no_match(addy);
-	left = g_strndup(str, start_pos);
-	right = str;
-	for (i = 0; i < end_pos; i++) right++;
-	new = g_strconcat(left, right, NULL);
-	g_free(str); /* also does g_free(right); */
-	g_free(left);
+	/* First we cut the string at the start_pos */
+	str[start_pos]='\0';
+	/* The we concat the first part with the end part */
+	new = g_strconcat(str, str+end_pos, NULL);
+	g_free(str);
 	g_free(addy->user);
 	addy->user = new;
 	addy->cursor = start_pos;
@@ -2363,10 +1772,8 @@
 	addy = end->data;
 	str = libbalsa_make_address_string(addy);
 	libbalsa_force_no_match(addy);
-	right = str;
-	for (i = 0; i < end_pos; i++) right++;
 	g_free(addy->user);
-	addy->user = g_strdup(right);
+	addy->user = g_strdup(str+end_pos);
 	g_free(str);
 
 	/*
@@ -2379,13 +1786,15 @@
 	/*
 	 * Delete the GList inbetween(!)
 	 */
-	for (list = g_list_next(start);
-	     list != end;
-	     list = g_list_next(start)) {
-	    libbalsa_emailData_free(list->data);
-	    list->data = NULL;
-	    g_list_remove_link(address_entry->input->list, list);
-	}
+	/* Unlink the part of the list to be deleted */
+	start->next->prev=NULL;
+	end->prev->next=NULL;
+	/* Free the unlinked part */
+	g_list_foreach(start->next,(GFunc)libbalsa_emailData_free,NULL);
+	g_list_free(start->next);
+	/* Re-link the remaining parts */
+	start->next=end;
+	end->prev=start;
     }
 
     editable->selection_start_pos = editable->selection_end_pos = 0;
@@ -2595,10 +2004,6 @@
 	break;
     }
 
-#ifndef DISABLE_UPDATE_CUR_POS
-    libbalsa_address_entry_update_cursor_pos(address_entry);
-#endif
-    
     /*
      * Since we emit signals from within the above code,
      * the widget might already be destroyed or at least
@@ -2624,8 +2029,6 @@
 	gtk_editable_claim_selection(editable,
 		editable->selection_start_pos != editable->selection_end_pos,
 		event->time);
-	libbalsa_address_entry_adjust_scroll(address_entry);
-	libbalsa_address_entry_queue_draw(address_entry);
     }
 
     /*
@@ -2635,217 +2038,6 @@
     return return_val;
 }
 
-
-/*************************************************************
- * libbalsa_address_entry_draw_text:
- *     Draws the widget.
- *
- *   credits:
- *     Most of this comes from gtk+-1.2.8/gtk/gtkentry.c
- *
- *   arguments:
- *     address_entry: the widget.
- *
- *   results:
- *     modifies address_entry
- *
- *   caveat:
- *     GTK doesn't offer multiple highlight colours, so we can
- *     only highlight either the selection, or the alias.
- *     Since the selection is a USER action, the selection
- *     gets preference in the highlight.
- *************************************************************/
-static void
-libbalsa_address_entry_draw_text(LibBalsaAddressEntry *address_entry)
-{
-    GtkWidget *widget;
-    GtkEditable *editable;
-    GtkEntry *entry;
-
-    GtkStateType selected_state;
-    gint start_pos;
-    gint end_pos;
-    gint start_xoffset;
-    gint colour_start_pos;
-    gint colour_end_pos;
-    gint colour_start_xoffset;
-    gint colour_end_xoffset;
-    gint width, height;
-    gint y;
-    GdkDrawable *drawable;
-    gint use_backing_pixmap;
-    GdkWChar *stars;
-    GdkWChar *toprint;
-
-    g_return_if_fail(address_entry != NULL);
-    g_return_if_fail(LIBBALSA_IS_ADDRESS_ENTRY(address_entry));
-
-    widget = GTK_WIDGET(address_entry);
-    editable = GTK_EDITABLE(address_entry);
-    entry = GTK_ENTRY(address_entry);
-
-    /*
-     * What is this used for???
-     */
-    if (entry->timer) {
-	gtk_timeout_remove(entry->timer);
-	entry->timer = 0;
-    }
-
-    /*
-     * Don't draw it if we don't have to.
-     */
-    if (! (GTK_WIDGET_DRAWABLE(address_entry))) return;
-
-    /*
-     * If there is no text, draw a rectangle.
-     */
-    if (!entry->text) {         
-	gtk_paint_flat_box(widget->style, entry->text_area,
-		           GTK_WIDGET_STATE(widget), GTK_SHADOW_NONE,
-		           NULL, widget, "entry_bg", 
-		           0, 0, -1, -1);
-	if (editable->editable)
-	    libbalsa_address_entry_draw_cursor(address_entry);
-	return;
-    }
-
-    gdk_window_get_size (entry->text_area, &width, &height);
-
-    g_assert(entry->text != NULL);
-    /*
-     * If the widget has focus, draw on a backing pixmap to avoid flickering
-     * and copy it to the text_area.
-     * Otherwise draw to text_area directly for better speed.
-     */
-    use_backing_pixmap = GTK_WIDGET_HAS_FOCUS(widget) && (entry->text != NULL);
-    if (use_backing_pixmap) {
-	libbalsa_address_entry_make_backing_pixmap
-	                                        (address_entry, width, height);
-	drawable = entry->backing_pixmap;
-    } else {
-	drawable = entry->text_area;
-    }
-
-    gtk_paint_flat_box(widget->style, drawable,
-		       GTK_WIDGET_STATE(widget), GTK_SHADOW_NONE,
-		       NULL, widget, "entry_bg", 
-		       0, 0, width, height);
-
-    y = (height - (widget->style->font->ascent + widget->style->font->descent))
-	/ 2;
-    y += widget->style->font->ascent;
-
-    start_pos = libbalsa_address_entry_find_position(address_entry,
-	                                             entry->scroll_offset);
-    start_xoffset = entry->char_offset[start_pos] - entry->scroll_offset;
-
-    end_pos = libbalsa_address_entry_find_position(address_entry,
-	                                        entry->scroll_offset + width);
-    if (end_pos < entry->text_length)
-	end_pos += 1;
-
-    /*
-     * First, grab the selection...
-     */
-    colour_start_pos = MIN(editable->selection_start_pos,
-	                   editable->selection_end_pos);
-    colour_end_pos = MAX(editable->selection_start_pos,
-		         editable->selection_end_pos);
-    
-    /*
-     * If there was no selection, grab the alias colour positions.
-     */
-    if (colour_start_pos == colour_end_pos) {
-	colour_start_pos = MIN(address_entry->alias_start_pos,
-	                       address_entry->alias_end_pos);
-	colour_end_pos = MAX(address_entry->alias_start_pos,
-		             address_entry->alias_end_pos);
-    }
-
-    /*
-     * Do we need to colour at all?
-     */
-    if (editable->has_selection || (colour_start_pos != colour_end_pos))
-	selected_state = GTK_STATE_SELECTED;
-    else
-	selected_state = GTK_STATE_ACTIVE;
-
-    /*
-     * Now clamp the values: Make sure they are valid.
-     */
-    colour_start_pos = CLAMP(colour_start_pos, start_pos, end_pos);
-    colour_end_pos = CLAMP(colour_end_pos, start_pos, end_pos);
-
-    colour_start_xoffset = 
-	entry->char_offset[colour_start_pos] - entry->scroll_offset;
-    colour_end_xoffset = 
-	entry->char_offset[colour_end_pos] - entry->scroll_offset;
-
-    /*
-     * if editable->visible, print a bunch of stars.
-     * If not, print the standard text.
-     */
-    if (editable->visible) {
-	  toprint = entry->text + start_pos;
-    } else {
-	  gint i;
-	  stars = g_new(GdkWChar, end_pos - start_pos);
-	  for (i = 0; i < end_pos - start_pos; i++)
-	      stars[i] = '*';
-	  toprint = stars;
-    }
-      
-    if (colour_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,
-		         colour_start_pos - start_pos);
-    }
-      
-    if ((colour_end_pos >= start_pos) && 
-	(colour_start_pos < end_pos) &&
-	(colour_start_pos != colour_end_pos)) {
-	gtk_paint_flat_box(widget->style, drawable, 
-		           selected_state, GTK_SHADOW_NONE,
-		           NULL, widget, "text",
-		           INNER_BORDER + colour_start_xoffset,
-		           INNER_BORDER,
-		           colour_end_xoffset - colour_start_xoffset,
-			   height - 2*INNER_BORDER);
-	gdk_draw_text_wc(drawable, widget->style->font,
-		         widget->style->fg_gc[selected_state],
-		         INNER_BORDER + colour_start_xoffset, y,
-		         toprint + colour_start_pos - start_pos,
-		         colour_end_pos - colour_start_pos);
-    }          
-       
-    if (colour_end_pos < end_pos) {
-	gdk_draw_text_wc(drawable, widget->style->font,
-		         widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
-		         INNER_BORDER + colour_end_xoffset, y,
-		         toprint + colour_end_pos - start_pos,
-		         end_pos - colour_end_pos);
-    }
-    
-    /*
-     * free the space allocated for the stars if it's neccessary.
-     */
-    if (!editable->visible)
-	g_free (toprint);
-
-    if (editable->editable)
-	libbalsa_address_entry_draw_cursor_on_drawable(address_entry, drawable);
-
-    if (use_backing_pixmap)
-	gdk_draw_pixmap(entry->text_area,
-		        widget->style->fg_gc[GTK_STATE_NORMAL],
-		        entry->backing_pixmap,
-		        0, 0, 0, 0, width, height);       
-}
-
-
 /*************************************************************
  * libbalsa_address_entry_show:
  *     Shows the widget.  This will work out the aliases,
@@ -2898,11 +2090,7 @@
 	 */
 	addy = (emailData *)list->data;
 	g_assert(addy != NULL);
-	if (addy->match != NULL) {
-	    out = g_strconcat("", addy->user, " (", addy->match, ")", NULL);
-	} else {
-	    out = g_strdup(addy->user);
-	}
+	out = libbalsa_make_address_string(addy);
 	/*
 	 * Copy the string, adding a delimiter if need be.
 	 */
@@ -2938,13 +2126,11 @@
     start = editable->selection_start_pos;
     end = editable->selection_end_pos;
     tmp_pos = 0;
-    libbalsa_address_entry_delete_text(editable, 0, -1);
+    gtk_editable_delete_text(editable, 0, -1);
     gtk_editable_insert_text(editable, show->str, show->len, &tmp_pos);
-    gtk_editable_set_position(GTK_EDITABLE(address_entry), cursor);
-    editable->selection_start_pos = start;
-    editable->selection_end_pos = end;
-    libbalsa_address_entry_draw_text(address_entry);
+    gtk_editable_set_position(editable, cursor);
     g_string_free(show, TRUE);
+    gtk_editable_select_region(editable, start, end);
 }
 
 


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