sync with sylpheed 0.7.0cvs16
[claws.git] / src / gtkstext.c
index c6605ea90a5c11256f8353d38e8d597e6fd51543..eaa312ec606c5cd79dd26cab01fa6df6aaae3070 100644 (file)
  */
 
 /*
- * Modified by the Sylpheed Team and others 2001. Interesting 
+ * Modified by the Sylpheed Team and others 2001-2002. Interesting
  * parts are marked using comment block following this one.
- * This modification is based on the GtkSText of GTK 1.2.8
+ * This modification is based on the GtkText of GTK 1.2.10
  */
 
-/* SYLPHEED: 
- * comment here 
+/* SYLPHEED:
+ * comment here
  */
 
 #ifdef HAVE_CONFIG_H
-#      include "config.h"
+#  include "config.h"
 #endif
 
 #include <ctype.h>
 #include <gtk/gtkmain.h>
 #include <gtk/gtkselection.h>
 #include <gtk/gtksignal.h>
-#include <gtkstext.h>
 
-/* SYLPHEED: 
+#include "compose.h"
+#include "gtkstext.h"
+
+
+/* line_arrow.xbm */
+#define line_arrow_width 6
+#define line_arrow_height 9
+static unsigned char line_arrow_bits[] = {
+   0x00, 0x00, 0x04, 0x0c, 0x18, 0x3f, 0x18, 0x0c, 0x04};
+
+/* line-wrap.xbm */
+#define line_wrap_width 6
+#define line_wrap_height 9
+static unsigned char line_wrap_bits[] = {
+  0x1e, 0x3e, 0x30, 0x30, 0x39, 0x1f, 0x0f, 0x0f, 0x1f, };
+
+/* SYLPHEED:
  * compile time settings 
  */
 #define INITIAL_BUFFER_SIZE      1024
@@ -68,8 +83,6 @@
 #define KEY_SCROLL_PIXELS        10
 #define SCROLL_TIME              100
 #define FREEZE_LENGTH            1024        
-
-
 /* Freeze text when inserting or deleting more than this many characters */
 
 /* SYLPHEED:
@@ -126,7 +139,7 @@ enum {
   ARG_WORD_WRAP
 };
 
-typedef struct _TextProperty             TextProperty;
+typedef struct _TextProperty          TextProperty;
 typedef struct _TabStopMark           TabStopMark;
 typedef struct _PrevTabCont           PrevTabCont;
 typedef struct _FetchLinesData        FetchLinesData;
@@ -221,67 +234,67 @@ struct _LineParams
 };
 
 
-static void  gtk_stext_class_init     (GtkSTextClass   *klass);
-static void  gtk_stext_set_arg        (GtkObject      *object,
+static void  gtk_stext_class_init    (GtkSTextClass   *klass);
+static void  gtk_stext_set_arg       (GtkObject      *object,
                                      GtkArg         *arg,
                                      guint           arg_id);
-static void  gtk_stext_get_arg        (GtkObject      *object,
+static void  gtk_stext_get_arg       (GtkObject      *object,
                                      GtkArg         *arg,
                                      guint           arg_id);
-static void  gtk_stext_init           (GtkSText        *text);
-static void  gtk_stext_destroy        (GtkObject      *object);
-static void  gtk_stext_finalize       (GtkObject      *object);
-static void  gtk_stext_realize        (GtkWidget      *widget);
-static void  gtk_stext_unrealize      (GtkWidget      *widget);
-static void  gtk_stext_style_set            (GtkWidget      *widget,
+static void  gtk_stext_init          (GtkSText        *text);
+static void  gtk_stext_destroy       (GtkObject      *object);
+static void  gtk_stext_finalize      (GtkObject      *object);
+static void  gtk_stext_realize       (GtkWidget      *widget);
+static void  gtk_stext_unrealize     (GtkWidget      *widget);
+static void  gtk_stext_style_set     (GtkWidget      *widget,
                                      GtkStyle       *previous_style);
-static void  gtk_stext_state_changed  (GtkWidget      *widget,
+static void  gtk_stext_state_changed (GtkWidget      *widget,
                                      GtkStateType    previous_state);
-static void  gtk_stext_draw_focus     (GtkWidget      *widget);
-static void  gtk_stext_size_request   (GtkWidget      *widget,
+static void  gtk_stext_draw_focus    (GtkWidget      *widget);
+static void  gtk_stext_size_request  (GtkWidget      *widget,
                                      GtkRequisition *requisition);
-static void  gtk_stext_size_allocate  (GtkWidget      *widget,
+static void  gtk_stext_size_allocate (GtkWidget      *widget,
                                      GtkAllocation  *allocation);
-static void  gtk_stext_adjustment     (GtkAdjustment  *adjustment,
+static void  gtk_stext_adjustment    (GtkAdjustment  *adjustment,
                                      GtkSText        *text);
-static void  gtk_stext_disconnect     (GtkAdjustment  *adjustment,
+static void  gtk_stext_disconnect    (GtkAdjustment  *adjustment,
                                      GtkSText        *text);
 
-static void gtk_stext_insert_text       (GtkEditable       *editable,
+static void gtk_stext_insert_text      (GtkEditable       *editable,
                                        const gchar       *new_text,
                                        gint               new_text_length,
                                        gint               *position);
-static void gtk_stext_delete_text       (GtkEditable        *editable,
+static void gtk_stext_delete_text      (GtkEditable        *editable,
                                        gint               start_pos,
                                        gint               end_pos);
-static void gtk_stext_update_text       (GtkEditable       *editable,
+static void gtk_stext_update_text      (GtkEditable       *editable,
                                        gint               start_pos,
                                        gint               end_pos);
-static gchar *gtk_stext_get_chars       (GtkEditable       *editable,
+static gchar *gtk_stext_get_chars      (GtkEditable       *editable,
                                        gint               start,
                                        gint               end);
-static void gtk_stext_set_selection     (GtkEditable       *editable,
+static void gtk_stext_set_selection    (GtkEditable       *editable,
                                        gint               start,
                                        gint               end);
-static void gtk_stext_real_set_editable (GtkEditable       *editable,
+static void gtk_stext_real_set_editable(GtkEditable       *editable,
                                        gboolean           is_editable);
 
 /* Event handlers */
-static void  gtk_stext_draw              (GtkWidget         *widget,
+static void  gtk_stext_draw             (GtkWidget         *widget,
                                         GdkRectangle      *area);
-static gint  gtk_stext_expose            (GtkWidget         *widget,
+static gint  gtk_stext_expose           (GtkWidget         *widget,
                                         GdkEventExpose    *event);
-static gint  gtk_stext_button_press      (GtkWidget         *widget,
+static gint  gtk_stext_button_press     (GtkWidget         *widget,
                                         GdkEventButton    *event);
-static gint  gtk_stext_button_release    (GtkWidget         *widget,
+static gint  gtk_stext_button_release   (GtkWidget         *widget,
                                         GdkEventButton    *event);
-static gint  gtk_stext_motion_notify     (GtkWidget         *widget,
+static gint  gtk_stext_motion_notify    (GtkWidget         *widget,
                                         GdkEventMotion    *event);
-static gint  gtk_stext_key_press         (GtkWidget         *widget,
+static gint  gtk_stext_key_press        (GtkWidget         *widget,
                                         GdkEventKey       *event);
-static gint  gtk_stext_focus_in          (GtkWidget         *widget,
+static gint  gtk_stext_focus_in         (GtkWidget         *widget,
                                         GdkEventFocus     *event);
-static gint  gtk_stext_focus_out         (GtkWidget         *widget,
+static gint  gtk_stext_focus_out        (GtkWidget         *widget,
                                         GdkEventFocus     *event);
 
 static void move_gap (GtkSText* text, guint index);
@@ -402,6 +415,7 @@ static void gtk_stext_kill_line           (GtkEditable *editable,
                                          gint         direction);
 
 /* To be removed */
+#if 0
 static void gtk_stext_move_forward_character    (GtkSText          *text);
 static void gtk_stext_move_backward_character   (GtkSText          *text);
 static void gtk_stext_move_forward_word         (GtkSText          *text);
@@ -417,19 +431,19 @@ static void gtk_stext_delete_forward_word       (GtkSText          *text);
 static void gtk_stext_delete_backward_word      (GtkSText          *text);
 static void gtk_stext_delete_line               (GtkSText          *text);
 static void gtk_stext_delete_to_line_end        (GtkSText          *text);
+#endif
 static void gtk_stext_select_word               (GtkSText          *text,
                                                guint32           time);
 static void gtk_stext_select_line               (GtkSText          *text,
                                                guint32           time);
 
 static void gtk_stext_set_position  (GtkEditable       *editable,
-                                   gint               position);
-
+                                    gint               position);
 
 /* SYLPHEED:
  * cursor timer
  */
-static void gtk_stext_enable_blink      (GtkSText *text);
+static void gtk_stext_enable_blink  (GtkSText *text);
 static void gtk_stext_disable_blink (GtkSText *text);
 
 /* #define DEBUG_GTK_STEXT */
@@ -491,31 +505,32 @@ static GMemChunk  *text_property_chunk = NULL;
 static GtkWidgetClass *parent_class = NULL;
 
 
+#if 0
 static const GtkTextFunction control_keys[26] =
 {
-  (GtkTextFunction)gtk_stext_move_beginning_of_line,    /* a */
-  (GtkTextFunction)gtk_stext_move_backward_character,   /* b */
+  (GtkTextFunction)gtk_stext_move_beginning_of_line,   /* a */
+  (GtkTextFunction)gtk_stext_move_backward_character,  /* b */
   (GtkTextFunction)gtk_editable_copy_clipboard,        /* c */
-  (GtkTextFunction)gtk_stext_delete_forward_character,  /* d */
-  (GtkTextFunction)gtk_stext_move_end_of_line,          /* e */
-  (GtkTextFunction)gtk_stext_move_forward_character,    /* f */
+  (GtkTextFunction)gtk_stext_delete_forward_character, /* d */
+  (GtkTextFunction)gtk_stext_move_end_of_line,         /* e */
+  (GtkTextFunction)gtk_stext_move_forward_character,   /* f */
   NULL,                                                /* g */
-  (GtkTextFunction)gtk_stext_delete_backward_character, /* h */
+  (GtkTextFunction)gtk_stext_delete_backward_character,/* h */
   NULL,                                                /* i */
   NULL,                                                /* j */
-  (GtkTextFunction)gtk_stext_delete_to_line_end,        /* k */
+  (GtkTextFunction)gtk_stext_delete_to_line_end,       /* k */
   NULL,                                                /* l */
   NULL,                                                /* m */
-  (GtkTextFunction)gtk_stext_move_next_line,            /* n */
+  (GtkTextFunction)gtk_stext_move_next_line,           /* n */
   NULL,                                                /* o */
-  (GtkTextFunction)gtk_stext_move_previous_line,        /* p */
+  (GtkTextFunction)gtk_stext_move_previous_line,       /* p */
   NULL,                                                /* q */
   NULL,                                                /* r */
   NULL,                                                /* s */
   NULL,                                                /* t */
-  (GtkTextFunction)gtk_stext_delete_line,               /* u */
+  (GtkTextFunction)gtk_stext_delete_line,              /* u */
   (GtkTextFunction)gtk_editable_paste_clipboard,       /* v */
-  (GtkTextFunction)gtk_stext_delete_backward_word,      /* w */
+  (GtkTextFunction)gtk_stext_delete_backward_word,     /* w */
   (GtkTextFunction)gtk_editable_cut_clipboard,         /* x */
   NULL,                                                /* y */
   NULL,                                                /* z */
@@ -523,12 +538,12 @@ static const GtkTextFunction control_keys[26] =
 
 static const GtkTextFunction alt_keys[26] =
 {
-  NULL,                                                /* a */
-  (GtkTextFunction)gtk_stext_move_backward_word,        /* b */
-  NULL,                                                /* c */
-  (GtkTextFunction)gtk_stext_delete_forward_word,       /* d */
+  NULL,                                           /* a */
+  (GtkTextFunction)gtk_stext_move_backward_word,  /* b */
+  NULL,                                           /* c */
+  (GtkTextFunction)gtk_stext_delete_forward_word, /* d */
   NULL,                                           /* e */
-  (GtkTextFunction)gtk_stext_move_forward_word,         /* f */
+  (GtkTextFunction)gtk_stext_move_forward_word,   /* f */
   NULL,                                           /* g */
   NULL,                                           /* h */
   NULL,                                           /* i */
@@ -550,20 +565,9 @@ static const GtkTextFunction alt_keys[26] =
   NULL,                                           /* y */
   NULL,                                           /* z */
 };
+#endif
 
 
-/* line_arrow.xbm */
-#define line_arrow_width 6
-#define line_arrow_height 9
-static unsigned char line_arrow_bits[] = {
-   0x00, 0x00, 0x04, 0x0c, 0x18, 0x3f, 0x18, 0x0c, 0x04};
-
-/* line-wrap.xbm */  
-#define line_wrap_width 6
-#define line_wrap_height 9
-static unsigned char line_wrap_bits[] = {
-  0x1e, 0x3e, 0x30, 0x30, 0x39, 0x1f, 0x0f, 0x0f, 0x1f, };
-
 /**********************************************************************/
 /*                             Widget Crap                           */
 /**********************************************************************/
@@ -778,19 +782,19 @@ gtk_stext_init (GtkSText *text)
   text->button = 0;
   
   text->current_font = NULL;
-
+  
   /* SYLPHEED:
    * timer for blinking cursor
    */
-  text->cursor_visible                   = FALSE;              /* don't know whether gtktext stores this somewhere */ 
-  text->cursor_timer_on                          = TRUE;
-  text->cursor_off_ms                    = 500;
-  text->cursor_on_ms                     = 500;
-  text->cursor_timer_id                          = 0;
+  text->cursor_visible = FALSE;                /* don't know whether gtktext stores this somewhere */
+  text->cursor_timer_on = TRUE;
+  text->cursor_off_ms = 500;
+  text->cursor_on_ms = 500;
+  text->cursor_timer_id = 0;
   text->cursor_idle_time_timer_id = 0;
-  text->wrap_rmargin                     = 0;
-  text->cursor_type                              = STEXT_CURSOR_LINE; 
-  text->persist_column                   = 0;
+  text->wrap_rmargin = 0;
+  text->cursor_type = GTK_STEXT_CURSOR_LINE; 
+  text->persist_column = 0;
   
   init_properties (text);
   
@@ -815,6 +819,15 @@ gtk_stext_new (GtkAdjustment *hadj,
                         "vadjustment", vadj,
                         NULL);
 
+  /* SYLPHEED:
+   * force widget name to be GtkText so it silently adapts
+   * the GtkText widget's style...
+   */
+#if 0
+  gtk_widget_set_name (text, "GtkText");
+  gtk_widget_ensure_style (text);
+#endif
+
   return text;
 }
 
@@ -999,6 +1012,15 @@ gtk_stext_thaw (GtkSText *text)
   draw_cursor (text, FALSE);
 }
 
+/* SYLPHEED */
+void
+gtk_stext_compact_buffer (GtkSText    *text)
+{
+  g_return_if_fail (text != NULL);
+  g_return_if_fail (GTK_IS_STEXT (text));
+  move_gap (text, gtk_stext_get_length(text));
+}
+
 void
 gtk_stext_insert (GtkSText    *text,
                 GdkFont    *font,
@@ -1307,10 +1329,10 @@ gtk_stext_destroy (GtkObject *object)
     }
 
   /* SYLPHEED:
-   * cursor timer 
+   * cursor timer
    */
-  gtk_stext_disable_blink(text);   
-  
+  gtk_stext_disable_blink (text);
+
   GTK_OBJECT_CLASS(parent_class)->destroy (object);
 }
 
@@ -1402,10 +1424,10 @@ gtk_stext_realize (GtkWidget *widget)
   attributes.y = (widget->style->klass->ythickness + TEXT_BORDER_ROOM);
   attributes.width = MAX (1, (gint)widget->allocation.width - (gint)attributes.x * 2);
   attributes.height = MAX (1, (gint)widget->allocation.height - (gint)attributes.y * 2);
-  
+
   attributes.cursor = gdk_cursor_new (GDK_XTERM);
   attributes_mask |= GDK_WA_CURSOR;
-
+  
   text->text_area = gdk_window_new (widget->window, &attributes, attributes_mask);
   gdk_window_set_user_data (text->text_area, text);
 
@@ -1607,25 +1629,25 @@ clear_focus_area (GtkSText *text, gint area_x, gint area_y, gint area_width, gin
   gint xthick = TEXT_BORDER_ROOM + widget->style->klass->xthickness;
   
   gint width, height;
+
   if (area_width == 0 || area_height == 0)
     return;
   
-   if (widget->style->bg_pixmap[GTK_STATE_NORMAL])
-     {
-       gdk_window_get_size (widget->style->bg_pixmap[GTK_STATE_NORMAL], &width, &height);
-       gdk_gc_set_ts_origin (text->bg_gc,
-                           (- (gint)text->first_onscreen_hor_pixel + xthick) % width,
-                           (- (gint)text->first_onscreen_ver_pixel + ythick) % height);
-       gc = text->bg_gc;
-     }
-   else
-     gc = widget->style->bg_gc[widget->state];
-  
-  
-   gdk_draw_rectangle (GTK_WIDGET (text)->window, gc, TRUE,
+  if (widget->style->bg_pixmap[GTK_STATE_NORMAL])
+    {
+      gdk_window_get_size (widget->style->bg_pixmap[GTK_STATE_NORMAL], &width, &height);
+      
+      gdk_gc_set_ts_origin (text->bg_gc,
+                           (- (gint)text->first_onscreen_hor_pixel + xthick) % width,
+                           (- (gint)text->first_onscreen_ver_pixel + ythick) % height);
+
+      gc = text->bg_gc;
+    }
+  else
+    gc = widget->style->bg_gc[widget->state];
+
+
+  gdk_draw_rectangle (GTK_WIDGET (text)->window, gc, TRUE,
                      area_x, area_y, area_width, area_height);
 }
 
@@ -1684,11 +1706,11 @@ gtk_stext_draw_focus (GtkWidget *widget)
       /* top rect */
       clear_focus_area (text, x, y, width, yextra);
       /* left rect */
-      clear_focus_area (text, x, y + yextra,
-                       xextra, y + height - 2 * yextra);
+      clear_focus_area (text, x, y + yextra, 
+                       xextra, y + height - 2 * yextra);
       /* right rect */
-      clear_focus_area (text, x + width - xextra, y + yextra,
-                       xextra, height - 2 * ythick);
+      clear_focus_area (text, x + width - xextra, y + yextra, 
+                       xextra, height - 2 * ythick);
       /* bottom rect */
       clear_focus_area (text, x, x + height - yextra, width, yextra);
     }
@@ -2136,9 +2158,7 @@ gtk_stext_key_press (GtkWidget   *widget,
          break;
        case GDK_Page_Up:   scroll_int (text, -text->vadj->page_increment); break;
        case GDK_Page_Down: scroll_int (text, +text->vadj->page_increment); break;
-       case GDK_Up:        
-               scroll_int (text, -KEY_SCROLL_PIXELS); 
-               break;
+       case GDK_Up:        scroll_int (text, -KEY_SCROLL_PIXELS); break;
        case GDK_Down:      scroll_int (text, +KEY_SCROLL_PIXELS); break;
        case GDK_Return:
          if (event->state & GDK_CONTROL_MASK)
@@ -2159,7 +2179,8 @@ gtk_stext_key_press (GtkWidget   *widget,
       
       text->point = find_mark (text, text->cursor_mark.index);
       
-      extend_selection = event->state & GDK_SHIFT_MASK;
+      extend_selection = (event->state & GDK_SHIFT_MASK) &&
+                        (event->keyval != GDK_Return);
       extend_start = FALSE;
       
       if (extend_selection)
@@ -2173,15 +2194,17 @@ gtk_stext_key_press (GtkWidget   *widget,
            }
          
          extend_start = (text->point.index == editable->selection_start_pos);
-         gtk_stext_disable_blink(text);
+         /* SYLPHEED: cursor */
+         gtk_stext_disable_blink (text);
+       }
+      else
+       {
+         gtk_stext_enable_blink (text);
        }
 
        /* SYLPHEED:
         * cursor
         */
-       if (!extend_selection)  
-               gtk_stext_enable_blink(text);
-               
        if (event->keyval != GDK_Up && event->keyval != GDK_Down) {
                reset_persist_col_pos(text);
        }
@@ -2189,8 +2212,17 @@ gtk_stext_key_press (GtkWidget   *widget,
       switch (event->keyval)
        {
        case GDK_Home:
-         if (event->state & GDK_CONTROL_MASK)
-           move_cursor_buffer_ver (text, -1);
+         if (event->state & GDK_CONTROL_MASK) {
+               if (text->wrap_rmargin == 0) {
+                       /* SYLPHEED: old behaviour */
+                       move_cursor_buffer_ver (text, -1);
+               }
+               else {
+                       /* SYLPHEED: contrived, but "trusty" */
+                       move_cursor_buffer_ver(text, -1);
+                       move_cursor_to_display_row_start(text);
+               }
+         }     
          else {
                if (text->wrap_rmargin > 0) {
                        /* SYLPHEED: line start */
@@ -2202,8 +2234,17 @@ gtk_stext_key_press (GtkWidget   *widget,
          }     
          break;
        case GDK_End:
-         if (event->state & GDK_CONTROL_MASK)
-           move_cursor_buffer_ver (text, +1);
+         if (event->state & GDK_CONTROL_MASK) {
+               /* SYLPHEED: a little bit contrived... */
+               if (text->wrap_rmargin == 0) {
+                       /* old behaviour */
+                       move_cursor_buffer_ver (text, +1);
+               }
+               else {
+                       move_cursor_buffer_ver(text, +1);
+                       move_cursor_to_display_row_end(text);
+               }
+         }             
          else {
                if (text->wrap_rmargin > 0) {
                        /* SYLPHEED: line end */
@@ -2231,7 +2272,7 @@ gtk_stext_key_press (GtkWidget   *widget,
                break;
        case GDK_Down:      
                move_cursor_to_display_row_down(text);
-//             move_cursor_ver (text, +1); 
+/*             move_cursor_ver (text, +1);  */
                break;
        case GDK_Left:
          if (event->state & GDK_CONTROL_MASK)
@@ -2271,19 +2312,15 @@ gtk_stext_key_press (GtkWidget   *widget,
            }
          break;
        case GDK_Delete:
-               {
-                       if (event->state & GDK_CONTROL_MASK) {
-                               gtk_stext_delete_forward_word (text);
-                       }       
-                       else if (event->state & GDK_SHIFT_MASK)
-                       {
-                               extend_selection = FALSE;
-                               gtk_editable_cut_clipboard (editable);
-                       }
-                       else {
-                               gtk_stext_delete_forward_character (text);
-                       }       
-               }               
+         if (event->state & GDK_CONTROL_MASK)
+           gtk_stext_delete_forward_word (text);
+         else if (event->state & GDK_SHIFT_MASK)
+           {
+             extend_selection = FALSE;
+             gtk_editable_cut_clipboard (editable);
+           }
+         else
+           gtk_stext_delete_forward_character (text);
          break;
        case GDK_Tab:
          position = text->point.index;
@@ -2305,7 +2342,8 @@ gtk_stext_key_press (GtkWidget   *widget,
          
        default:
          return_val = FALSE;
-         
+
+#if 0
          if (event->state & GDK_CONTROL_MASK)
            {
              if ((key >= 'A') && (key <= 'Z'))
@@ -2333,6 +2371,10 @@ gtk_stext_key_press (GtkWidget   *widget,
              break;
            }
          else if (event->length > 0)
+#endif
+         if (!(event->state & GDK_CONTROL_MASK) &&
+             !(event->state & GDK_MOD1_MASK)    &&
+              (event->length > 0))
            {
              extend_selection = FALSE;
              
@@ -2397,8 +2439,9 @@ gtk_stext_focus_in (GtkWidget     *widget,
 #endif
   
   draw_cursor (GTK_STEXT(widget), TRUE);
+  /* SYLPHEED: cursor */
   GTK_STEXT(widget)->cursor_visible = TRUE;
-  gtk_stext_enable_blink(GTK_STEXT(widget));
+  gtk_stext_enable_blink (GTK_STEXT(widget));
   
   return FALSE;
 }
@@ -2415,12 +2458,12 @@ gtk_stext_focus_out (GtkWidget     *widget,
   
   GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
   gtk_widget_draw_focus (widget);
+  
   /* SYLPHEED:
    * should disable blink before undrawing the cursor - disabling blink
    * redraws the cursor.
    */
-  gtk_stext_disable_blink(GTK_STEXT(widget));
+  gtk_stext_disable_blink (GTK_STEXT(widget));
   undraw_cursor (GTK_STEXT(widget), TRUE);
   GTK_STEXT(widget)->cursor_visible = FALSE;
   
@@ -4219,9 +4262,9 @@ static void move_cursor_to_display_row_start(GtkSText *text)
 }
 
 /* dumb */
-static gboolean range_intersect(gint x1, gint x2, gint y1, gint y2)
+static gboolean range_intersect(guint x1, guint x2, guint y1, guint y2)
 {
-       gint tmp;
+       guint tmp;
        if (x1 > x2) { tmp = x1; x1 = x2; x2 = tmp; }
        if (y1 > y2) { tmp = y1; y1 = y2; y1 = tmp; }
        if (y1 < x1) { tmp = x1; x1 = y1; y1 = tmp; tmp = x2; x2 = y2; y2 = tmp; }
@@ -4261,28 +4304,26 @@ static void move_cursor_to_display_row_up(GtkSText *text)
        int                       new_index;
        int                   col;
        GtkSPropertyMark  mark;
-       
+
        mark = find_this_line_start_mark(text, text->cursor_mark.index, &text->cursor_mark);
 
        /* top of buffer */
        if (mark.index == 0) {
-               XDEBUG ( ("%s(%d) top of buffer", __FILE__, __LINE__) );        
-               return;
+               XDEBUG ( ("%s(%d) top of buffer", __FILE__, __LINE__) );
        }
 
-       /* we need to previous DISPLAY row not the previous BUFFER line, so we go one line back,
-        * and iterate over the lines until we have a LineParams that matches the original */
-
+       /* we need previous DISPLAY row not the previous BUFFER line, so we go to start
+        * of paragraph, and iterate over the lines until we have a LineParams that matches 
+        * the original */
        lp  = CACHE_DATA(text->current_line);
        col = (text->cursor_mark.index - lp.start.index);
        data.start = lp.start.index;
        data.end   = lp.end.index;
 
        /* get the previous line */
-       if (mark.index - 1 > 0) {
+       if (mark.index != 0) {
                decrement_mark(&mark);
-               XDEBUG( ("%s(%d) mark decrement", __FILE__, __LINE__) );
-               if (mark.index - 1 > 0) {
+               if (mark.index != 0) {
                        GtkSPropertyMark smark = mark;
                        XDEBUG( ("%s(%d) finding line start mark", __FILE__, __LINE__) );
                        mark = find_this_line_start_mark(text, smark.index -1,  &smark);
@@ -4316,6 +4357,19 @@ typedef struct {
        LineParams   lp;
 } fdrf; 
 
+#if defined(AHX_DEBUG)
+static void print_line(GtkSText *text, guint start, guint end)
+{
+       gchar *buf = alloca(2048), *walk = buf;
+
+       memset(buf, 0, 2048);
+       for (; start <= end; start++) {
+               *walk++ = GTK_STEXT_INDEX(text, start);
+       }               
+       XDEBUG( ("%s", buf) );  
+}
+#endif
+
 static gint forward_display_row_fetcher(GtkSText *text,
                                                                                LineParams *lp,
                                                                                fdrf       *data)
@@ -4325,6 +4379,7 @@ static gint forward_display_row_fetcher(GtkSText *text,
                                __FILE__, __LINE__, data->start, data->end, lp->start.index, lp->end.index) );
                data->lp = *lp;
                data->completed = TRUE;
+               print_line(text, lp->start.index, lp->end.index);
                return TRUE;
        }
        else if (range_intersect(data->start, data->end, lp->start.index, lp->end.index)) {
@@ -4367,6 +4422,7 @@ static void move_cursor_to_display_row_down       (GtkSText *text)
                        new_index = data.lp.end.index;
                }
                /* and move the cursor */
+               XDEBUG( ("%s(%d) - FW set pos %d", __FILE__, __LINE__, new_index) );
                gtk_stext_set_position_X(GTK_EDITABLE(text), new_index);                
        }
 }
@@ -4404,25 +4460,25 @@ gtk_stext_move_cursor (GtkEditable *editable,
     }
 }
 
-static void
+void
 gtk_stext_move_forward_character (GtkSText *text)
 {
   move_cursor_hor (text, 1);
 }
 
-static void
+void
 gtk_stext_move_backward_character (GtkSText *text)
 {
   move_cursor_hor (text, -1);
 }
 
-static void
+void
 gtk_stext_move_next_line (GtkSText *text)
 {
   move_cursor_ver (text, 1);
 }
 
-static void
+void
 gtk_stext_move_previous_line (GtkSText *text)
 {
   move_cursor_ver (text, -1);
@@ -4444,7 +4500,7 @@ gtk_stext_move_word (GtkEditable *editable,
     }
 }
 
-static void
+void
 gtk_stext_move_forward_word (GtkSText *text)
 {
   text->cursor_virtual_x = 0;
@@ -4476,7 +4532,7 @@ gtk_stext_move_forward_word (GtkSText *text)
   draw_cursor (text, FALSE);
 }
 
-static void
+void
 gtk_stext_move_backward_word (GtkSText *text)
 {
   text->cursor_virtual_x = 0;
@@ -4556,14 +4612,14 @@ gtk_stext_move_to_column (GtkEditable *editable,
   draw_cursor (text, FALSE);
 }
 
-static void
+void
 gtk_stext_move_beginning_of_line (GtkSText *text)
 {
   gtk_stext_move_to_column (GTK_EDITABLE (text), 0);
   
 }
 
-static void
+void
 gtk_stext_move_end_of_line (GtkSText *text)
 {
   gtk_stext_move_to_column (GTK_EDITABLE (text), -1);
@@ -4594,13 +4650,13 @@ gtk_stext_kill_char (GtkEditable *editable,
     }
 }
 
-static void
+void
 gtk_stext_delete_forward_character (GtkSText *text)
 {
   gtk_stext_kill_char (GTK_EDITABLE (text), 1);
 }
 
-static void
+void
 gtk_stext_delete_backward_character (GtkSText *text)
 {
   gtk_stext_kill_char (GTK_EDITABLE (text), -1);
@@ -4610,9 +4666,8 @@ static void
 gtk_stext_kill_word (GtkEditable *editable,
                    gint         direction)
 {
-  if (editable->selection_start_pos != editable->selection_end_pos) {
+  if (editable->selection_start_pos != editable->selection_end_pos)
     gtk_editable_delete_selection (editable);
-  }    
   else
     {
       gint old_pos = editable->current_pos;
@@ -4629,13 +4684,13 @@ gtk_stext_kill_word (GtkEditable *editable,
     }
 }
 
-static void
+void
 gtk_stext_delete_forward_word (GtkSText *text)
 {
   gtk_stext_kill_word (GTK_EDITABLE (text), 1);
 }
 
-static void
+void
 gtk_stext_delete_backward_word (GtkSText *text)
 {
   gtk_stext_kill_word (GTK_EDITABLE (text), -1);
@@ -4658,17 +4713,31 @@ gtk_stext_kill_line (GtkEditable *editable,
     }
 }
 
-static void
+void
 gtk_stext_delete_line (GtkSText *text)
 {
   gtk_stext_move_to_column (GTK_EDITABLE (text), 0);
-  gtk_stext_kill_line (GTK_EDITABLE (text), 1);
+  if (GTK_STEXT_INDEX(text, GTK_EDITABLE (text)->current_pos) == LINE_DELIM)
+    {
+      gtk_stext_kill_char (GTK_EDITABLE (text), 1);
+    }
+  else
+    {
+      gtk_stext_kill_line (GTK_EDITABLE (text), 1);
+    }
 }
 
-static void
+void
 gtk_stext_delete_to_line_end (GtkSText *text)
 {
-  gtk_stext_kill_line (GTK_EDITABLE (text), 1);
+  if (GTK_STEXT_INDEX(text, GTK_EDITABLE (text)->current_pos) == LINE_DELIM)
+    {
+      gtk_stext_kill_char (GTK_EDITABLE (text), 1);
+    }
+  else
+    {
+      gtk_stext_kill_line (GTK_EDITABLE (text), 1);
+    }
 }
 
 static void
@@ -5065,7 +5134,10 @@ find_line_params (GtkSText* text,
        max_display_pixels = text->wrap_rmargin * ch_width; 
   }    
   
-  if (GTK_EDITABLE (text)->editable || !text->word_wrap)
+  /* SYLPHEED - we don't draw ugly word wrapping thing 
+   * if our wrap margin is set */
+  if (!text->wrap_rmargin &&
+      ((GTK_EDITABLE (text)->editable || !text->word_wrap)))
     max_display_pixels -= LINE_WRAP_ROOM;
   
   lp.wraps             = 0;
@@ -5165,6 +5237,16 @@ find_line_params (GtkSText* text,
                      /* If whole line is one word, revert to char wrapping */
                      if (lp.end.index == lp.start.index)
                        {
+                         /* SYLPHEED: don't wrap URLs */
+                          if (gtkut_stext_is_uri_string(text, lp.end.index,
+                                        gtk_stext_get_length(text)))
+                            {
+                             lp.end = saved_mark;
+                             lp.displayable_chars = saved_characters + 1;
+                              lp.wraps = 0;
+                              goto no_url_wrap;
+                            }
+
                          lp.end = saved_mark;
                          lp.displayable_chars = saved_characters;
                          decrement_mark (&lp.end);
@@ -5187,6 +5269,7 @@ find_line_params (GtkSText* text,
          lp.displayable_chars += 1;
        }
       
+no_url_wrap:
       lp.font_ascent = MAX (font->ascent, lp.font_ascent);
       lp.font_descent = MAX (font->descent, lp.font_descent);
       lp.pixel_width  += ch_width;
@@ -5400,7 +5483,7 @@ draw_line (GtkSText* text,
                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
@@ -5556,60 +5639,72 @@ undraw_cursor (GtkSText* text, gint absolute)
       GTK_WIDGET_DRAWABLE (text) && text->line_start_cache)
     {
       GdkFont* font;
-         gint pixel_width, pixel_height;
-         GdkGC *gc;
+      gint pixel_width;
+      gint pixel_height;
       
       g_assert(text->cursor_mark.property);
 
-         gc = gdk_gc_new(text->text_area);
-         g_assert(gc);
-         gdk_gc_copy(gc, text->gc);
-
       font = MARK_CURRENT_FONT(text, &text->cursor_mark);
 
-         /* SYLPHEED:
-          * changed the cursor to a real block (TM)
-          */
-         if (text->cursor_type == STEXT_CURSOR_BLOCK) { 
-                 if (text->use_wchar)
-                       pixel_width = gdk_char_width_wc(font, text->cursor_char);               
-                 else
-                       pixel_width = gdk_char_width(font, text->cursor_char);
-                 pixel_width -= 1;
-                 pixel_height = LINE_HEIGHT(CACHE_DATA(text->current_line));
-
-                 draw_bg_rect (text, &text->cursor_mark,
-                                               text->cursor_pos_x,
-                                               text->cursor_pos_y - (pixel_height + 1),
-                                               pixel_width + 1, 
-                                               pixel_height + 1,
-                                               FALSE);
-        }      
-        else {
-             draw_bg_rect (text, &text->cursor_mark,
-                               text->cursor_pos_x - 1,
-                                           text->cursor_pos_y - text->cursor_char_offset - font->ascent,
-                                               2, font->descent + font->ascent + 1, FALSE);
-                                                                                         
-        }
-      
+      /* SYLPHEED:
+       * changed the cursor to a real block (TM)
+       */
+      if (text->cursor_type == GTK_STEXT_CURSOR_BLOCK)
+       {
+         if (text->cursor_char)
+           {
+             if (text->use_wchar)
+               pixel_width = gdk_char_width_wc (font, text->cursor_char);
+             else
+               pixel_width = gdk_char_width (font, (guchar)text->cursor_char);
+           }
+         else
+           {
+               pixel_width = gdk_char_width (font, 'W');
+           }
+
+         pixel_height = LINE_HEIGHT(CACHE_DATA(text->current_line));
+
+         draw_bg_rect (text, &text->cursor_mark,
+                       text->cursor_pos_x,
+                       text->cursor_pos_y - (pixel_height + 1),
+                       pixel_width,
+                       pixel_height + 1,
+                       FALSE);
+       }
+      else
+       {
+         draw_bg_rect (text, &text->cursor_mark, 
+                       text->cursor_pos_x,
+                       text->cursor_pos_y - text->cursor_char_offset - font->ascent,
+                       2, font->descent + font->ascent + 1, FALSE);
+       }
+
       if (text->cursor_char)
        {
          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);         
+           }
        }
-
-       gdk_gc_copy(text->gc, gc);
-       gdk_gc_unref(gc);
     }
 }
 
@@ -5641,7 +5736,6 @@ static void
 draw_cursor (GtkSText* text, gint absolute)
 {
   GtkEditable *editable = (GtkEditable *)text;
-  gint pixel_width, pixel_height;
   
   TDEBUG (("in draw_cursor\n"));
   
@@ -5654,46 +5748,51 @@ draw_cursor (GtkSText* text, gint absolute)
       GTK_WIDGET_DRAWABLE (text) && text->line_start_cache)
     {
       GdkFont* font;
-         GdkGC*          gc;
+      gint pixel_width;
+      gint pixel_height;
       
       g_assert (text->cursor_mark.property);
 
-         gc = gdk_gc_new(text->text_area);
-         g_assert (gc);
-         gdk_gc_copy(gc, text->gc);
-         font = MARK_CURRENT_FONT (text, &text->cursor_mark);
-         if (text->cursor_type == STEXT_CURSOR_BLOCK) {
-                 /* SYLPHEED:
-                  * changed the cursor to a real block (TM)
-                  */
-                 if (text->use_wchar) {
-                       pixel_width = gdk_char_width_wc(font, text->cursor_char);               
-                 }
-                 else {
-                       pixel_width = gdk_char_width(font, text->cursor_char);
-                 }
-                 pixel_width -= 1;
-
-                 pixel_height = LINE_HEIGHT(CACHE_DATA(text->current_line));
-                 gdk_gc_set_foreground (text->gc, &GTK_WIDGET (text)->style->text[GTK_STATE_NORMAL]);
-                 gdk_gc_set_function(text->gc, GDK_INVERT);
-                 gdk_draw_rectangle(text->text_area, text->gc, TRUE, 
-                                                        text->cursor_pos_x, 
-                                                        text->cursor_pos_y - pixel_height,
-                                                        pixel_width, 
-                                                        pixel_height);
-         }
-         else {
-               gdk_gc_set_line_attributes(text->gc, 2, GDK_LINE_SOLID, GDK_CAP_NOT_LAST, GDK_JOIN_MITER);
-               gdk_gc_set_foreground(text->gc, &GTK_WIDGET (text)->style->text[GTK_STATE_NORMAL]);
-           gdk_draw_line(text->text_area, text->gc, text->cursor_pos_x,
-                             text->cursor_pos_y + font->descent - text->cursor_char_offset,
-                                         text->cursor_pos_x,
-                                         text->cursor_pos_y - text->cursor_char_offset - font->ascent );
-                                                                                                  
-         }
-         gdk_gc_copy(text->gc, gc);                                            
-         gdk_gc_unref(gc);
+      font = MARK_CURRENT_FONT (text, &text->cursor_mark);
+
+      /* SYLPHEED:
+       * change the cursor to a real block (TM)
+       */
+      if (text->cursor_type == GTK_STEXT_CURSOR_BLOCK)
+       {
+         if (text->cursor_char)
+           {
+             if (text->use_wchar)
+               pixel_width = gdk_char_width_wc (font, text->cursor_char);
+             else
+               pixel_width = gdk_char_width (font, (guchar)text->cursor_char);
+           }
+         else
+           {
+               pixel_width = gdk_char_width (font, 'W');
+           }
+
+         pixel_height = LINE_HEIGHT(CACHE_DATA(text->current_line));
+
+         gdk_gc_set_foreground (text->gc, &GTK_WIDGET (text)->style->text[GTK_STATE_NORMAL]);
+         gdk_gc_set_function (text->gc, GDK_INVERT);
+         gdk_draw_rectangle (text->text_area, text->gc, TRUE,
+                             text->cursor_pos_x,
+                             text->cursor_pos_y - pixel_height,
+                             pixel_width,
+                             pixel_height);
+         gdk_gc_set_function (text->gc, GDK_COPY);
+       }
+      else
+       {
+         gdk_gc_set_line_attributes(text->gc, 2, GDK_LINE_SOLID, GDK_CAP_NOT_LAST, GDK_JOIN_MITER);
+         gdk_gc_set_foreground (text->gc, &GTK_WIDGET (text)->style->text[GTK_STATE_NORMAL]);
+
+         gdk_draw_line (text->text_area, text->gc, text->cursor_pos_x + 1,
+                        text->cursor_pos_y + font->descent - text->cursor_char_offset,
+                        text->cursor_pos_x + 1,
+                        text->cursor_pos_y - text->cursor_char_offset - font->ascent);
+       }
     }
 }
 
@@ -5944,82 +6043,109 @@ gtk_stext_set_selection  (GtkEditable   *editable,
  * cursor timer
  */
 
-static gint stext_blink_timer_proc(GtkSText *text)
+static gint
+stext_blink_timer_proc (GtkSText *text)
 {
-       if (text->cursor_state_on) {
-               text->cursor_state_on = FALSE;
-               undraw_cursor(text, TRUE);
-               /* kill this timer... */
-               gtk_timeout_remove(text->cursor_timer_id);
-               text->cursor_timer_id = gtk_timeout_add(text->cursor_off_ms, (GtkFunction) stext_blink_timer_proc, (gpointer) text); 
-       }
-       else {
-               text->cursor_state_on = TRUE;
-               draw_cursor(text, TRUE);
-               /* kill this timer... */
-               gtk_timeout_remove(text->cursor_timer_id);
-               text->cursor_timer_id = gtk_timeout_add(text->cursor_on_ms, (GtkFunction) stext_blink_timer_proc, (gpointer) text);
-       }
-       return TRUE;
+  if (text->cursor_state_on)
+    {
+      text->cursor_state_on = FALSE;
+      undraw_cursor (text, TRUE);
+      /* kill this timer... */
+      gtk_timeout_remove (text->cursor_timer_id);
+      text->cursor_timer_id = gtk_timeout_add (text->cursor_off_ms,
+                                              (GtkFunction) stext_blink_timer_proc,
+                                              (gpointer) text);
+    }
+  else
+    {
+      text->cursor_state_on = TRUE;
+      draw_cursor (text, TRUE);
+      /* kill this timer... */
+      gtk_timeout_remove (text->cursor_timer_id);
+      text->cursor_timer_id = gtk_timeout_add (text->cursor_on_ms,
+                                              (GtkFunction) stext_blink_timer_proc,
+                                              (gpointer) text);
+    }
+
+  return TRUE;
 }
 
-static gint stext_idle_timer_proc(GtkSText *text) 
+static gint
+stext_idle_timer_proc (GtkSText *text)
 {
-       /* make sure the cursor timer is off */
-       if (text->cursor_timer_id) {
-               gtk_timeout_remove(text->cursor_timer_id);
-               text->cursor_timer_id = 0;
-       }
-       /* assuming it's always on when calling this function ... */
-       text->cursor_state_on = TRUE;
-       text->cursor_timer_id = gtk_timeout_add(text->cursor_on_ms, (GtkFunction) stext_blink_timer_proc, (gpointer) text); 
-       /* make sure we kill the timer (could perhaps make this function return FALSE (not documented in
-        * the current docs). should check the source. */
-       gtk_idle_remove( text->cursor_idle_time_timer_id ); 
-       text->cursor_idle_time_timer_id = 0;
-       return TRUE;
+  /* make sure the cursor timer is off */
+  if (text->cursor_timer_id)
+    {
+      gtk_timeout_remove (text->cursor_timer_id);
+      text->cursor_timer_id = 0;
+    }
+
+  /* assuming it's always on when calling this function ... */
+  text->cursor_state_on = TRUE;
+  text->cursor_timer_id = gtk_timeout_add (text->cursor_on_ms,
+                                          (GtkFunction) stext_blink_timer_proc,
+                                          (gpointer) text);
+  /* make sure we kill the timer (could perhaps make this function return
+     FALSE (not documented in the current docs). should check the source. */
+  gtk_idle_remove (text->cursor_idle_time_timer_id);
+  text->cursor_idle_time_timer_id = 0;
+
+  return TRUE;
 }
 
-static void gtk_stext_enable_blink      (GtkSText *text)
+static void
+gtk_stext_enable_blink (GtkSText *text)
 {
-       if (text->cursor_timer_on) { 
-               gtk_stext_disable_blink(text);
-               text->cursor_idle_time_timer_id = gtk_idle_add((GtkFunction) stext_idle_timer_proc, (gpointer) text);
-       }
+  if (text->cursor_timer_on)
+    {
+      gtk_stext_disable_blink (text);
+      text->cursor_idle_time_timer_id = gtk_idle_add ((GtkFunction) stext_idle_timer_proc,
+                                                     (gpointer) text);
+    }
 }
 
-static void gtk_stext_disable_blink (GtkSText *text)
+static void
+gtk_stext_disable_blink (GtkSText *text)
 {
-       if (text->cursor_timer_on) {
-               if (text->cursor_idle_time_timer_id) {
-                       gtk_idle_remove( text->cursor_idle_time_timer_id );
-                       text->cursor_idle_time_timer_id = 0;
-               }
-               if (text->cursor_timer_id) {
-                       gtk_timeout_remove( text->cursor_timer_id );
-                       text->cursor_timer_id = 0;
-               }
-               draw_cursor(text, TRUE);
-       }               
+  if (text->cursor_timer_on)
+    {
+      if (text->cursor_idle_time_timer_id)
+       {
+         gtk_idle_remove (text->cursor_idle_time_timer_id);
+         text->cursor_idle_time_timer_id = 0;
+       }
+      if (text->cursor_timer_id)
+       {
+         gtk_timeout_remove (text->cursor_timer_id);
+         text->cursor_timer_id = 0;
+       }
+      draw_cursor(text, TRUE);
+    }
 }
 
-void gtk_stext_set_blink(GtkSText *text, gboolean blinkin_on)
+void
+gtk_stext_set_blink (GtkSText *text, gboolean blinking_on)
 {
-       if (text->cursor_timer_on != blinkin_on) {
-               if (text->cursor_timer_on) {
-                       /* text widget already created? */
-                       if (text->cursor_visible) {
-                               gtk_stext_disable_blink(text);
-                       }                               
-                       text->cursor_timer_on = FALSE;
-               }
-               else {
-                       if (text->cursor_visible) {
-                               gtk_stext_enable_blink(text);
-                       }
-                       text->cursor_timer_on = TRUE;
-               }
+  if (text->cursor_timer_on != blinking_on)
+    {
+      if (text->cursor_timer_on)
+       {
+         /* text widget already created? */
+         if (text->cursor_visible)
+           {
+             gtk_stext_disable_blink (text);
+           }
+           text->cursor_timer_on = FALSE;
        }
+      else
+       {
+         if (text->cursor_visible)
+           {
+             gtk_stext_enable_blink (text);
+           }
+           text->cursor_timer_on = TRUE;
+       }
+    }
 }