]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtktextsegment.c
GtkBubbleWindow: rework how drawing is done
[~andy/gtk] / gtk / gtktextsegment.c
index 38e905865b69f387725a0a66e9b7d0db2a9de9a1..d1493d69a41459207f954e7f84a27acfe2740747 100644 (file)
@@ -12,7 +12,7 @@
  * California, Sun Microsystems, Inc., and other parties.  The
  * following terms apply to all files associated with the software
  * unless explicitly disclaimed in individual files.
- * 
+ *
  * The authors hereby grant permission to use, copy, modify,
  * distribute, and license this software and its documentation for any
  * purpose, provided that existing copyright notices are retained in
  * software may be copyrighted by their authors and need not follow
  * the licensing terms described here, provided that the new terms are
  * clearly indicated on the first page of each file where they apply.
- * 
+ *
  * IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY
  * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
  * DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION,
  * OR ANY DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED
  * OF THE POSSIBILITY OF SUCH DAMAGE.
- * 
+ *
  * THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
  * foregoing, the authors grant the U.S. Government and others acting
  * in its behalf permission to use and distribute the software in
  * accordance with the terms specified in this license.
- * 
+ *
  */
 
+#define GTK_TEXT_USE_INTERNAL_UNSUPPORTED_API
+#include "config.h"
 #include "gtktextbtree.h"
 #include <string.h>
-#include <ctype.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include "gtktexttag.h"
  */
 
 GtkTextLineSegment*
-gtk_text_line_segment_split(const GtkTextIter *iter)
+gtk_text_line_segment_split (const GtkTextIter *iter)
 {
   GtkTextLineSegment *prev, *seg;
   GtkTextBTree *tree;
   GtkTextLine *line;
   int count;
 
-  line = gtk_text_iter_get_line(iter);
-  tree = gtk_text_iter_get_btree(iter);
-  
-  count = gtk_text_iter_get_line_byte(iter);
+  line = _gtk_text_iter_get_text_line (iter);
+  tree = _gtk_text_iter_get_btree (iter);
+
+  count = gtk_text_iter_get_line_index (iter);
+
+  if (gtk_get_debug_flags () & GTK_DEBUG_TEXT)
+    _gtk_text_iter_check (iter);
   
   prev = NULL;
   seg = line->segments;
@@ -115,13 +119,13 @@ gtk_text_line_segment_split(const GtkTextIter *iter)
             }
           else
             {
-              g_assert(count != seg->byte_count);
-              g_assert(seg->byte_count > 0);
-              
-              gtk_text_btree_segments_changed(tree);
-              
+              g_assert (count != seg->byte_count);
+              g_assert (seg->byte_count > 0);
+
+              _gtk_text_btree_segments_changed (tree);
+
               seg = (*seg->type->splitFunc)(seg, count);
-              
+
               if (prev == NULL)
                 line->segments = seg;
               else
@@ -140,7 +144,7 @@ gtk_text_line_segment_split(const GtkTextIter *iter)
       prev = seg;
       seg = seg->next;
     }
-  g_error("split_segment reached end of line!");
+  g_error ("split_segment reached end of line!");
   return NULL;
 }
 
@@ -149,86 +153,88 @@ gtk_text_line_segment_split(const GtkTextIter *iter)
  * Macros that determine how much space to allocate for new segments:
  */
 
-#define CSEG_SIZE(chars) ((unsigned) (G_STRUCT_OFFSET(GtkTextLineSegment, body) \
+#define CSEG_SIZE(chars) ((unsigned) (G_STRUCT_OFFSET (GtkTextLineSegment, body) \
         + 1 + (chars)))
-#define TSEG_SIZE ((unsigned) (G_STRUCT_OFFSET(GtkTextLineSegment, body) \
-        + sizeof(GtkTextToggleBody)))
+#define TSEG_SIZE ((unsigned) (G_STRUCT_OFFSET (GtkTextLineSegment, body) \
+        + sizeof (GtkTextToggleBody)))
 
 /*
  * Type functions
  */
 
 static void
-char_segment_self_check(GtkTextLineSegment *seg)
+char_segment_self_check (GtkTextLineSegment *seg)
 {
   /* This function checks the segment itself, but doesn't
      assume the segment has been validly inserted into
      the btree. */
-  
-  g_assert(seg != NULL);
-  
+
+  g_assert (seg != NULL);
+
   if (seg->byte_count <= 0)
     {
-      g_error("char_segment_check_func: segment has size <= 0");
+      g_error ("segment has size <= 0");
     }
 
-  if (strlen(seg->body.chars) != seg->byte_count)
+  if (strlen (seg->body.chars) != seg->byte_count)
     {
-      g_error("char_segment_check_func: segment has wrong size");
+      g_error ("segment has wrong size");
     }
 
   if (g_utf8_strlen (seg->body.chars, seg->byte_count) != seg->char_count)
     {
-      g_error("char segment has wrong character count");
+      g_error ("char segment has wrong character count");
     }
 }
 
 GtkTextLineSegment*
-char_segment_new(const gchar *text, guint len)
+_gtk_char_segment_new (const gchar *text, guint len)
 {
   GtkTextLineSegment *seg;
 
-  g_assert(gtk_text_byte_begins_utf8_char(text));
-  
-  seg = g_malloc(CSEG_SIZE(len));
-  seg->type = &gtk_text_char_type;
+  g_assert (gtk_text_byte_begins_utf8_char (text));
+
+  seg = g_malloc (CSEG_SIZE (len));
+  seg->type = (GtkTextLineSegmentClass *)&gtk_text_char_type;
   seg->next = NULL;
   seg->byte_count = len;
-  memcpy(seg->body.chars, text, len);
+  memcpy (seg->body.chars, text, len);
   seg->body.chars[len] = '\0';
 
   seg->char_count = g_utf8_strlen (seg->body.chars, seg->byte_count);
 
-  if (gtk_debug_flags & GTK_DEBUG_TEXT)
-    char_segment_self_check(seg);
-  
+  if (gtk_get_debug_flags () & GTK_DEBUG_TEXT)
+    char_segment_self_check (seg);
+
   return seg;
 }
 
 GtkTextLineSegment*
-char_segment_new_from_two_strings(const gchar *text1, guint len1,
-                                  const gchar *text2, guint len2)
+_gtk_char_segment_new_from_two_strings (const gchar *text1, 
+                                       guint        len1, 
+                                       guint        chars1,
+                                        const gchar *text2, 
+                                       guint        len2, 
+                                       guint        chars2)
 {
   GtkTextLineSegment *seg;
 
-  g_assert(gtk_text_byte_begins_utf8_char(text1));
-  g_assert(gtk_text_byte_begins_utf8_char(text2));
-  
-  seg = g_malloc(CSEG_SIZE(len1+len2));
+  g_assert (gtk_text_byte_begins_utf8_char (text1));
+  g_assert (gtk_text_byte_begins_utf8_char (text2));
+
+  seg = g_malloc (CSEG_SIZE (len1+len2));
   seg->type = &gtk_text_char_type;
   seg->next = NULL;
   seg->byte_count = len1 + len2;
-  memcpy(seg->body.chars, text1, len1);
-  memcpy(seg->body.chars + len1, text2, len2);
+  memcpy (seg->body.chars, text1, len1);
+  memcpy (seg->body.chars + len1, text2, len2);
   seg->body.chars[len1+len2] = '\0';
 
-  /* In principle this function could probably take chars1 and chars2
-     as args, since it's typically used to merge two char segments */
-  seg->char_count = g_utf8_strlen (seg->body.chars, seg->byte_count);
+  seg->char_count = chars1 + chars2;
+
+  if (gtk_get_debug_flags () & GTK_DEBUG_TEXT)
+    char_segment_self_check (seg);
 
-  if (gtk_debug_flags & GTK_DEBUG_TEXT)
-    char_segment_self_check(seg);
-  
   return seg;
 }
 
@@ -251,35 +257,35 @@ char_segment_new_from_two_strings(const gchar *text1, guint len1,
  */
 
 static GtkTextLineSegment *
-char_segment_split_func(GtkTextLineSegment *seg, int index)
+char_segment_split_func (GtkTextLineSegment *seg, int index)
 {
   GtkTextLineSegment *new1, *new2;
 
-  g_assert(index < seg->byte_count);
-  
-  if (gtk_debug_flags & GTK_DEBUG_TEXT)
+  g_assert (index < seg->byte_count);
+
+  if (gtk_get_debug_flags () & GTK_DEBUG_TEXT)
     {
-      char_segment_self_check(seg);
+      char_segment_self_check (seg);
     }
-  
-  new1 = char_segment_new(seg->body.chars, index);
-  new2 = char_segment_new(seg->body.chars + index, seg->byte_count - index);
 
-  g_assert(gtk_text_byte_begins_utf8_char(new1->body.chars));
-  g_assert(gtk_text_byte_begins_utf8_char(new2->body.chars));
-  g_assert(new1->byte_count + new2->byte_count == seg->byte_count);
-  g_assert(new1->char_count + new2->char_count == seg->char_count);
-  
+  new1 = _gtk_char_segment_new (seg->body.chars, index);
+  new2 = _gtk_char_segment_new (seg->body.chars + index, seg->byte_count - index);
+
+  g_assert (gtk_text_byte_begins_utf8_char (new1->body.chars));
+  g_assert (gtk_text_byte_begins_utf8_char (new2->body.chars));
+  g_assert (new1->byte_count + new2->byte_count == seg->byte_count);
+  g_assert (new1->char_count + new2->char_count == seg->char_count);
+
   new1->next = new2;
   new2->next = seg->next;
 
-  if (gtk_debug_flags & GTK_DEBUG_TEXT)
+  if (gtk_get_debug_flags () & GTK_DEBUG_TEXT)
     {
-      char_segment_self_check(new1);
-      char_segment_self_check(new2);
+      char_segment_self_check (new1);
+      char_segment_self_check (new2);
     }
-  
-  g_free(seg);
+
+  g_free (seg);
   return new1;
 }
 
@@ -291,6 +297,11 @@ char_segment_split_func(GtkTextLineSegment *seg, int index)
  *      This procedure merges adjacent character segments into
  *      a single character segment, if possible.
  *
+ * Arguments:
+ *      segPtr: Pointer to the first of two adjacent segments to
+ *              join.
+ *      line:   Line containing segments (not used).
+ *
  * Results:
  *      The return value is a pointer to the first segment in
  *      the (new) list of segments that used to start with segPtr.
@@ -303,33 +314,34 @@ char_segment_split_func(GtkTextLineSegment *seg, int index)
 
         /* ARGSUSED */
 static GtkTextLineSegment *
-char_segment_cleanup_func(segPtr, line)
-     GtkTextLineSegment *segPtr;           /* Pointer to first of two adjacent
-                                         * segments to join. */
-     GtkTextLine *line;                /* Line containing segments (not
-                                         * used). */
+char_segment_cleanup_func (GtkTextLineSegment *segPtr, GtkTextLine *line)
 {
   GtkTextLineSegment *segPtr2, *newPtr;
 
-  if (gtk_debug_flags & GTK_DEBUG_TEXT)
-    char_segment_self_check(segPtr);
-  
+  if (gtk_get_debug_flags () & GTK_DEBUG_TEXT)
+    char_segment_self_check (segPtr);
+
   segPtr2 = segPtr->next;
   if ((segPtr2 == NULL) || (segPtr2->type != &gtk_text_char_type))
     {
       return segPtr;
     }
 
-  newPtr = char_segment_new_from_two_strings(segPtr->body.chars, segPtr->byte_count,
-                                             segPtr2->body.chars, segPtr2->byte_count);
+  newPtr =
+    _gtk_char_segment_new_from_two_strings (segPtr->body.chars, 
+                                           segPtr->byte_count,
+                                           segPtr->char_count,
+                                            segPtr2->body.chars, 
+                                           segPtr2->byte_count,
+                                           segPtr2->char_count);
 
   newPtr->next = segPtr2->next;
 
-  if (gtk_debug_flags & GTK_DEBUG_TEXT)
-    char_segment_self_check(newPtr);
-  
-  g_free(segPtr);
-  g_free(segPtr2);
+  if (gtk_get_debug_flags () & GTK_DEBUG_TEXT)
+    char_segment_self_check (newPtr);
+
+  g_free (segPtr);
+  g_free (segPtr2);
   return newPtr;
 }
 
@@ -340,6 +352,12 @@ char_segment_cleanup_func(segPtr, line)
  *
  *      This procedure is invoked to delete a character segment.
  *
+ * Arguments:
+ *      segPtr   : Segment to delete
+ *      line     : Line containing segment
+ *      treeGone : Non-zero means the entire tree is being
+ *                 deleted, so everything must get cleaned up.
+ *
  * Results:
  *      Always returns 0 to indicate that the segment was deleted.
  *
@@ -351,14 +369,9 @@ char_segment_cleanup_func(segPtr, line)
 
         /* ARGSUSED */
 static int
-char_segment_delete_func(segPtr, line, treeGone)
-     GtkTextLineSegment *segPtr;           /* Segment to delete. */
-     GtkTextLine *line;                /* Line containing segment. */
-     int treeGone;                      /* Non-zero means the entire tree is
-                                         * being deleted, so everything must
-                                         * get cleaned up. */
+char_segment_delete_func (GtkTextLineSegment *segPtr, GtkTextLine *line, int treeGone)
 {
-  g_free((char*) segPtr);
+  g_free ((char*) segPtr);
   return 0;
 }
 
@@ -370,6 +383,10 @@ char_segment_delete_func(segPtr, line, treeGone)
  *      This procedure is invoked to perform consistency checks
  *      on character segments.
  *
+ * Arguments:
+ *      segPtr : Segment to check
+ *      line   : Line containing segment
+ *
  * Results:
  *      None.
  *
@@ -382,34 +399,25 @@ char_segment_delete_func(segPtr, line, treeGone)
 
         /* ARGSUSED */
 static void
-char_segment_check_func(segPtr, line)
-     GtkTextLineSegment *segPtr;           /* Segment to check. */
-     GtkTextLine *line;                /* Line containing segment. */
+char_segment_check_func (GtkTextLineSegment *segPtr, GtkTextLine *line)
 {
-  char_segment_self_check(segPtr);
-  
-  if (segPtr->next == NULL)
-    {
-      if (segPtr->body.chars[segPtr->byte_count-1] != '\n')
-        {
-          g_error("char_segment_check_func: line doesn't end with newline");
-        }
-    }
-  else
+  char_segment_self_check (segPtr);
+
+  if (segPtr->next != NULL)
     {
       if (segPtr->next->type == &gtk_text_char_type)
         {
-          g_error("char_segment_check_func: adjacent character segments weren't merged");
+          g_error ("adjacent character segments weren't merged");
         }
     }
 }
 
 GtkTextLineSegment*
-toggle_segment_new(GtkTextTagInfo *info, gboolean on)
+_gtk_toggle_segment_new (GtkTextTagInfo *info, gboolean on)
 {
   GtkTextLineSegment *seg;
 
-  seg = g_malloc(TSEG_SIZE);
+  seg = g_malloc (TSEG_SIZE);
 
   seg->type = on ? &gtk_text_toggle_on_type : &gtk_text_toggle_off_type;
 
@@ -417,7 +425,7 @@ toggle_segment_new(GtkTextTagInfo *info, gboolean on)
 
   seg->byte_count = 0;
   seg->char_count = 0;
-  
+
   seg->body.toggle.info = info;
   seg->body.toggle.inNodeCounts = 0;
 
@@ -431,6 +439,12 @@ toggle_segment_new(GtkTextTagInfo *info, gboolean on)
  *
  *      This procedure is invoked to delete toggle segments.
  *
+ * Arguments:
+ *      segPtr   : Segment to check
+ *      line     : Line containing segment
+ *      treeGone : Non-zero means the entire tree is being
+ *                 deleted so everything must get cleaned up
+ *
  * Results:
  *      Returns 1 to indicate that the segment may not be deleted,
  *      unless the entire B-tree is going away.
@@ -444,16 +458,11 @@ toggle_segment_new(GtkTextTagInfo *info, gboolean on)
  */
 
 static int
-toggle_segment_delete_func(segPtr, line, treeGone)
-     GtkTextLineSegment *segPtr;           /* Segment to check. */
-     GtkTextLine *line;                /* Line containing segment. */
-     int treeGone;                      /* Non-zero means the entire tree is
-                                         * being deleted, so everything must
-                                         * get cleaned up. */
+toggle_segment_delete_func (GtkTextLineSegment *segPtr, GtkTextLine *line, int treeGone)
 {
   if (treeGone)
     {
-      g_free((char *) segPtr);
+      g_free ((char *) segPtr);
       return 0;
     }
 
@@ -467,8 +476,8 @@ toggle_segment_delete_func(segPtr, line, treeGone)
 
   if (segPtr->body.toggle.inNodeCounts)
     {
-      change_node_toggle_count(line->parent,
-                               segPtr->body.toggle.info, -1);
+      _gtk_change_node_toggle_count (line->parent,
+                                     segPtr->body.toggle.info, -1);
       segPtr->body.toggle.inNodeCounts = 0;
     }
   return 1;
@@ -483,6 +492,10 @@ toggle_segment_delete_func(segPtr, line, treeGone)
  *      been modified in some way.  It's invoked after the
  *      modifications are complete.
  *
+ * Arguments:
+ *      segPtr : Segment to check
+ *      line   : Line that now contains segment
+ *
  * Results:
  *      The return value is the head segment in a new list
  *      that is to replace the tail of the line that used to
@@ -498,9 +511,7 @@ toggle_segment_delete_func(segPtr, line, treeGone)
  */
 
 static GtkTextLineSegment *
-toggle_segment_cleanup_func(segPtr, line)
-     GtkTextLineSegment *segPtr;   /* Segment to check. */
-     GtkTextLine *line;        /* Line that now contains segment. */
+toggle_segment_cleanup_func (GtkTextLineSegment *segPtr, GtkTextLine *line)
 {
   GtkTextLineSegment *segPtr2, *prevPtr;
   int counts;
@@ -530,21 +541,21 @@ toggle_segment_cleanup_func(segPtr, line)
             + segPtr2->body.toggle.inNodeCounts;
           if (counts != 0)
             {
-              change_node_toggle_count(line->parent,
-                                       segPtr->body.toggle.info, -counts);
+              _gtk_change_node_toggle_count (line->parent,
+                                             segPtr->body.toggle.info, -counts);
             }
           prevPtr->next = segPtr2->next;
-          g_free((char *) segPtr2);
+          g_free ((char *) segPtr2);
           segPtr2 = segPtr->next;
-          g_free((char *) segPtr);
+          g_free ((char *) segPtr);
           return segPtr2;
         }
     }
 
   if (!segPtr->body.toggle.inNodeCounts)
     {
-      change_node_toggle_count(line->parent,
-                               segPtr->body.toggle.info, 1);
+      _gtk_change_node_toggle_count (line->parent,
+                                     segPtr->body.toggle.info, 1);
       segPtr->body.toggle.inNodeCounts = 1;
     }
   return segPtr;
@@ -558,6 +569,10 @@ toggle_segment_cleanup_func(segPtr, line)
  *      This procedure is invoked when a toggle segment is about
  *      to move from one line to another.
  *
+ * Arguments:
+ *      segPtr : Segment to check
+ *      line   : Line that used to contain segment
+ *
  * Results:
  *      None.
  *
@@ -568,14 +583,12 @@ toggle_segment_cleanup_func(segPtr, line)
  */
 
 static void
-toggle_segment_line_change_func(segPtr, line)
-     GtkTextLineSegment *segPtr;   /* Segment to check. */
-     GtkTextLine *line;        /* Line that used to contain segment. */
+toggle_segment_line_change_func (GtkTextLineSegment *segPtr, GtkTextLine *line)
 {
   if (segPtr->body.toggle.inNodeCounts)
     {
-      change_node_toggle_count(line->parent,
-                               segPtr->body.toggle.info, -1);
+      _gtk_change_node_toggle_count (line->parent,
+                                     segPtr->body.toggle.info, -1);
       segPtr->body.toggle.inNodeCounts = 0;
     }
 }
@@ -585,7 +598,7 @@ toggle_segment_line_change_func(segPtr, line)
  */
 
 
-GtkTextLineSegmentClass gtk_text_char_type = {
+const GtkTextLineSegmentClass gtk_text_char_type = {
   "character",                          /* name */
   0,                                            /* leftGravity */
   char_segment_split_func,                              /* splitFunc */
@@ -600,14 +613,14 @@ GtkTextLineSegmentClass gtk_text_char_type = {
  * range:
  */
 
-GtkTextLineSegmentClass gtk_text_toggle_on_type = {
+const GtkTextLineSegmentClass gtk_text_toggle_on_type = {
   "toggleOn",                                   /* name */
   0,                                            /* leftGravity */
   NULL,                 /* splitFunc */
   toggle_segment_delete_func,                           /* deleteFunc */
-  toggle_segment_cleanup_func,                         /* cleanupFunc */
-  toggle_segment_line_change_func,                     /* lineChangeFunc */
-  toggle_segment_check_func                            /* checkFunc */
+  toggle_segment_cleanup_func,                          /* cleanupFunc */
+  toggle_segment_line_change_func,                      /* lineChangeFunc */
+  _gtk_toggle_segment_check_func                        /* checkFunc */
 };
 
 /*
@@ -615,12 +628,12 @@ GtkTextLineSegmentClass gtk_text_toggle_on_type = {
  * range:
  */
 
-GtkTextLineSegmentClass gtk_text_toggle_off_type = {
-  "toggleOff",                         /* name */
-  1,                                           /* leftGravity */
-  NULL,                        /* splitFunc */
-  toggle_segment_delete_func,                          /* deleteFunc */
-  toggle_segment_cleanup_func,                         /* cleanupFunc */
-  toggle_segment_line_change_func,                     /* lineChangeFunc */
-  toggle_segment_check_func                            /* checkFunc */
+const GtkTextLineSegmentClass gtk_text_toggle_off_type = {
+  "toggleOff",                          /* name */
+  1,                                            /* leftGravity */
+  NULL,                 /* splitFunc */
+  toggle_segment_delete_func,                           /* deleteFunc */
+  toggle_segment_cleanup_func,                          /* cleanupFunc */
+  toggle_segment_line_change_func,                      /* lineChangeFunc */
+  _gtk_toggle_segment_check_func                        /* checkFunc */
 };