]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtktextlayout.c
When in split cursor mode, always add the cursor as both strong and weak
[~andy/gtk] / gtk / gtktextlayout.c
index 2b77c91b3c913762f5d3c0e33775445cac6e7862..b92e85cc8f16abdd9cd88ccb7e09bdf7be8706fd 100644 (file)
@@ -76,7 +76,9 @@
  * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
  */
 
+#define GTK_TEXT_USE_INTERNAL_UNSUPPORTED_API
 #include "gtksignal.h"
+#include "gtkmarshalers.h"
 #include "gtktextlayout.h"
 #include "gtktextbtree.h"
 #include "gtktextiterprivate.h"
@@ -84,9 +86,6 @@
 #include <stdlib.h>
 #include <string.h>
 
-static GtkTextLineData    *gtk_text_line_data_new                 (GtkTextLayout     *layout,
-                                                                   GtkTextLine       *line);
-
 static GtkTextLineData *gtk_text_layout_real_wrap (GtkTextLayout *layout,
                                                    GtkTextLine *line,
                                                    /* may be NULL */
@@ -178,7 +177,7 @@ gtk_text_layout_class_init (GtkTextLayoutClass *klass)
                   G_SIGNAL_RUN_LAST,
                   G_STRUCT_OFFSET (GtkTextLayoutClass, invalidated),
                   NULL, NULL,
-                  gtk_marshal_VOID__VOID,
+                  _gtk_marshal_VOID__VOID,
                   GTK_TYPE_NONE,
                   0);
 
@@ -188,7 +187,7 @@ gtk_text_layout_class_init (GtkTextLayoutClass *klass)
                   G_SIGNAL_RUN_LAST,
                   G_STRUCT_OFFSET (GtkTextLayoutClass, changed),
                   NULL, NULL,
-                  gtk_marshal_VOID__INT_INT_INT,
+                  _gtk_marshal_VOID__INT_INT_INT,
                   GTK_TYPE_NONE,
                   3,
                   GTK_TYPE_INT,
@@ -201,7 +200,7 @@ gtk_text_layout_class_init (GtkTextLayoutClass *klass)
                   G_SIGNAL_RUN_LAST,
                   G_STRUCT_OFFSET (GtkTextLayoutClass, allocate_child),
                   NULL, NULL,
-                  gtk_marshal_VOID__OBJECT_INT_INT,
+                  _gtk_marshal_VOID__OBJECT_INT_INT,
                   GTK_TYPE_NONE,
                   3,
                   GTK_TYPE_OBJECT,
@@ -209,7 +208,7 @@ gtk_text_layout_class_init (GtkTextLayoutClass *klass)
                   GTK_TYPE_INT);
 }
 
-void
+static void
 gtk_text_layout_init (GtkTextLayout *text_layout)
 {
   text_layout->cursor_visible = TRUE;
@@ -294,6 +293,7 @@ gtk_text_layout_default_style_changed (GtkTextLayout *layout)
 {
   g_return_if_fail (GTK_IS_TEXT_LAYOUT (layout));
 
+  DV (g_print ("invalidating all due to default style change (%s)\n", G_STRLOC));
   gtk_text_layout_invalidate_all (layout);
 }
 
@@ -336,6 +336,7 @@ gtk_text_layout_set_contexts (GtkTextLayout *layout,
   layout->rtl_context = rtl_context;
   g_object_ref (G_OBJECT (rtl_context));
 
+  DV (g_print ("invalidating all due to new pango contexts (%s)\n", G_STRLOC));
   gtk_text_layout_invalidate_all (layout);
 }
 
@@ -392,6 +393,7 @@ gtk_text_layout_set_screen_width (GtkTextLayout *layout, gint width)
 
   layout->screen_width = width;
 
+  DV (g_print ("invalidating all due to new screen width (%s)\n", G_STRLOC));
   gtk_text_layout_invalidate_all (layout);
 }
 
@@ -578,13 +580,11 @@ gtk_text_layout_get_lines (GtkTextLayout *layout,
   /* -1 since bottom_y is one past */
   last_btree_line =
     _gtk_text_btree_find_line_by_y (_gtk_text_buffer_get_btree (layout->buffer),
-                                   layout, bottom_y - 1, NULL);
+                                    layout, bottom_y - 1, NULL);
 
   if (!last_btree_line)
     last_btree_line =
-      _gtk_text_btree_get_line (_gtk_text_buffer_get_btree (layout->buffer),
-                               _gtk_text_btree_line_count (_gtk_text_buffer_get_btree (layout->buffer)) - 1,
-                               NULL);
+      _gtk_text_btree_get_end_iter_line (_gtk_text_buffer_get_btree (layout->buffer));
 
   g_assert (last_btree_line != NULL);
 
@@ -596,7 +596,7 @@ gtk_text_layout_get_lines (GtkTextLayout *layout,
       if (line == last_btree_line)
         break;
 
-      line = _gtk_text_line_next (line);
+      line = _gtk_text_line_next_excluding_last (line);
     }
 
   retval = g_slist_reverse (retval);
@@ -722,7 +722,7 @@ gtk_text_layout_real_invalidate (GtkTextLayout *layout,
       if (line == last_line)
         break;
 
-      line = _gtk_text_line_next (line);
+      line = _gtk_text_line_next_excluding_last (line);
     }
 
   gtk_text_layout_invalidated (layout);
@@ -751,7 +751,7 @@ gtk_text_layout_real_free_line_data (GtkTextLayout     *layout,
  *
  * Check if there are any invalid regions in a #GtkTextLayout's buffer
  *
- * Return value: #TRUE if any invalid regions were found
+ * Return value: %TRUE if any invalid regions were found
  **/
 gboolean
 gtk_text_layout_is_valid (GtkTextLayout *layout)
@@ -862,7 +862,7 @@ gtk_text_layout_validate_yrange (GtkTextLayout *layout,
         }
 
       seen += line_data->height;
-      line = _gtk_text_line_next (line);
+      line = _gtk_text_line_next_excluding_last (line);
     }
 
   /* If we found and validated any invalid lines, update size and
@@ -922,10 +922,11 @@ gtk_text_layout_real_wrap (GtkTextLayout   *layout,
   GtkTextLineDisplay *display;
 
   g_return_val_if_fail (GTK_IS_TEXT_LAYOUT (layout), NULL);
-
+  g_return_val_if_fail (line != NULL, NULL);
+  
   if (line_data == NULL)
     {
-      line_data = gtk_text_line_data_new (layout, line);
+      line_data = _gtk_text_line_data_new (layout, line);
       _gtk_text_line_add_data (line, line_data);
     }
 
@@ -1457,7 +1458,7 @@ add_cursor (GtkTextLayout      *layout,
       cursor->y = PANGO_PIXELS (strong_pos.y);
       cursor->height = PANGO_PIXELS (strong_pos.height);
       cursor->is_strong = TRUE;
-      cursor->is_weak = FALSE;
+      cursor->is_weak = (layout->cursor_direction == GTK_TEXT_DIR_NONE) ? FALSE : TRUE;
       display->cursors = g_slist_prepend (display->cursors, cursor);
     }
   
@@ -1472,7 +1473,7 @@ add_cursor (GtkTextLayout      *layout,
          cursor->x = PANGO_PIXELS (weak_pos.x);
          cursor->y = PANGO_PIXELS (weak_pos.y);
          cursor->height = PANGO_PIXELS (weak_pos.height);
-         cursor->is_strong = FALSE;
+         cursor->is_strong = (layout->cursor_direction == GTK_TEXT_DIR_NONE) ? FALSE : TRUE;
          cursor->is_weak = TRUE;
          display->cursors = g_slist_prepend (display->cursors, cursor);
        }
@@ -2005,6 +2006,9 @@ line_display_index_to_iter (GtkTextLayout      *layout,
                            gint                index,
                            gint                trailing)
 {
+  g_return_if_fail (!_gtk_text_line_is_last (display->line,
+                                             _gtk_text_buffer_get_btree (layout->buffer)));
+  
   if (index >= display->insert_index + layout->preedit_len)
     index -= layout->preedit_len;
   else if (index > display->insert_index)
@@ -2033,24 +2037,6 @@ line_display_index_to_iter (GtkTextLayout      *layout,
   gtk_text_iter_forward_chars (iter, trailing);
 }
 
-/* FIXME: This really doesn't belong in this file ... */
-static GtkTextLineData*
-gtk_text_line_data_new (GtkTextLayout *layout,
-                        GtkTextLine   *line)
-{
-  GtkTextLineData *line_data;
-
-  line_data = g_new (GtkTextLineData, 1);
-
-  line_data->view_id = layout;
-  line_data->next = NULL;
-  line_data->width = 0;
-  line_data->height = 0;
-  line_data->valid = FALSE;
-
-  return line_data;
-}
-
 static void
 get_line_at_y (GtkTextLayout *layout,
                gint           y,
@@ -2066,8 +2052,8 @@ get_line_at_y (GtkTextLayout *layout,
                                          layout, y, line_top);
   if (*line == NULL)
     {
-      *line = _gtk_text_btree_get_line (_gtk_text_buffer_get_btree (layout->buffer),
-                                       _gtk_text_btree_line_count (_gtk_text_buffer_get_btree (layout->buffer)) - 1, NULL);
+      *line = _gtk_text_btree_get_end_iter_line (_gtk_text_buffer_get_btree (layout->buffer));
+      
       if (line_top)
         *line_top =
           _gtk_text_btree_find_line_top (_gtk_text_buffer_get_btree (layout->buffer),
@@ -2115,14 +2101,6 @@ gtk_text_layout_get_iter_at_pixel (GtkTextLayout *layout,
   g_return_if_fail (GTK_IS_TEXT_LAYOUT (layout));
   g_return_if_fail (target_iter != NULL);
 
-  /* Adjust pixels to be on-screen. This gives nice
-     behavior if the user is dragging with a pointer grab.
-  */
-  if (x < 0)
-    x = 0;
-  if (x > layout->width)
-    x = layout->width;
-
   get_line_at_y (layout, y, &line, &line_top);
 
   display = gtk_text_layout_get_line_display (layout, line, FALSE);
@@ -2130,17 +2108,23 @@ gtk_text_layout_get_iter_at_pixel (GtkTextLayout *layout,
   x -= display->x_offset;
   y -= line_top + display->top_margin;
 
-  /* We clamp y to the area of the actual layout so that the layouts
-   * hit testing works OK on the space above and below the layout
+  /* If we are below the layout, position the cursor at the last character
+   * of the line.
    */
-  y = CLAMP (y, 0, display->height - display->top_margin - display->bottom_margin - 1);
-
-  if (!pango_layout_xy_to_index (display->layout, x * PANGO_SCALE, y * PANGO_SCALE,
-                                 &byte_index, &trailing))
+  if (y > display->height - display->top_margin - display->bottom_margin)
     {
       byte_index = _gtk_text_line_byte_count (line);
       trailing = 0;
     }
+  else
+    {
+       /* Ignore the "outside" return value from pango. Pango is doing
+        * the right thing even if we are outside the layout in the
+        * x-direction.
+        */
+      pango_layout_xy_to_index (display->layout, x * PANGO_SCALE, y * PANGO_SCALE,
+                                &byte_index, &trailing);
+    }
 
   line_display_index_to_iter (layout, display, target_iter, byte_index, trailing);
 
@@ -2248,6 +2232,45 @@ gtk_text_layout_get_line_yrange (GtkTextLayout     *layout,
     }
 }
 
+/**
+ * _gtk_text_layout_get_line_xrange:
+ * @layout: a #GtkTextLayout
+ * @iter:   a #GtkTextIter
+ * @x:      location to store the top of the paragraph in pixels,
+ *          or %NULL.
+ * @width  location to store the height of the paragraph in pixels,
+ *          or %NULL.
+ *
+ * Find the range of X coordinates for the paragraph containing
+ * the given iter. Private for 2.0 due to API freeze, could
+ * be made public for 2.2.
+ **/
+void
+_gtk_text_layout_get_line_xrange (GtkTextLayout     *layout,
+                                  const GtkTextIter *iter,
+                                  gint              *x,
+                                  gint              *width)
+{
+  GtkTextLine *line;
+
+  g_return_if_fail (GTK_IS_TEXT_LAYOUT (layout));
+  g_return_if_fail (_gtk_text_iter_get_btree (iter) == _gtk_text_buffer_get_btree (layout->buffer));
+
+  line = _gtk_text_iter_get_text_line (iter);
+
+  if (x)
+    *x = 0; /* FIXME This is wrong; should represent the first available cursor position */
+  
+  if (width)
+    {
+      GtkTextLineData *line_data = _gtk_text_line_get_data (line, layout);
+      if (line_data)
+        *width = line_data->width;
+      else
+        *width = 0;
+    }
+}
+
 void
 gtk_text_layout_get_iter_location (GtkTextLayout     *layout,
                                    const GtkTextIter *iter,
@@ -2306,9 +2329,8 @@ find_display_line_below (GtkTextLayout *layout,
   if (!line)
     {
       line =
-        _gtk_text_btree_get_line (_gtk_text_buffer_get_btree (layout->buffer),
-                                 _gtk_text_btree_line_count (_gtk_text_buffer_get_btree (layout->buffer)) - 1,
-                                 NULL);
+        _gtk_text_btree_get_end_iter_line (_gtk_text_buffer_get_btree (layout->buffer));
+
       line_top =
         _gtk_text_btree_find_line_top (_gtk_text_buffer_get_btree (layout->buffer),
                                       line, layout);
@@ -2346,7 +2368,7 @@ find_display_line_below (GtkTextLayout *layout,
       line_top += display->bottom_margin;
       gtk_text_layout_free_line_display (layout, display);
 
-      next = _gtk_text_line_next (line);
+      next = _gtk_text_line_next_excluding_last (line);
       if (!next)
         found_line = line;
 
@@ -2374,8 +2396,8 @@ find_display_line_above (GtkTextLayout *layout,
   line = _gtk_text_btree_find_line_by_y (_gtk_text_buffer_get_btree (layout->buffer), layout, y, &line_top);
   if (!line)
     {
-      line = _gtk_text_btree_get_line (_gtk_text_buffer_get_btree (layout->buffer),
-                                      _gtk_text_btree_line_count (_gtk_text_buffer_get_btree (layout->buffer)) - 1, NULL);
+      line = _gtk_text_btree_get_end_iter_line (_gtk_text_buffer_get_btree (layout->buffer));
+      
       line_top = _gtk_text_btree_find_line_top (_gtk_text_buffer_get_btree (layout->buffer), line, layout);
     }
 
@@ -2408,6 +2430,7 @@ find_display_line_above (GtkTextLayout *layout,
           if (tmp_top < y)
             {
               found_line = line;
+             pango_layout_iter_free (layout_iter);
               goto done;
             }
         }
@@ -2658,7 +2681,7 @@ gtk_text_layout_move_iter_to_next_line (GtkTextLayout *layout,
       
       gtk_text_layout_free_line_display (layout, display);
 
-      line = _gtk_text_line_next (line);
+      line = _gtk_text_line_next_excluding_last (line);
     }
 
   return
@@ -2939,7 +2962,7 @@ gtk_text_layout_move_iter_visually (GtkTextLayout *layout,
         }
       else if (new_index > byte_count)
         {
-          line = _gtk_text_line_next (line);
+          line = _gtk_text_line_next_excluding_last (line);
           if (!line)
             goto done;