GtkTextView: use GSlice to allocate GtkTextLineSegment's
Use GSlice to allocate all types of segments: - char - toggle - mark - pixbuf - child widget Char segments are a bit more complicated because the length of the text is determined at run time and stored in the 'byte_count' field. If the text is long, GSlice will call the system malloc() anyway, so it's better to always use GSlice for GtkTextLineSegment. Toggle segments are also freed in gtktextbtree.c, hence the function _gtk_toggle_segment_free() (for a later commit it would be nice to rename those functions with the _gtk_text prefix). https://bugzilla.gnome.org/show_bug.cgi?id=727908
This commit is contained in:
		
				
					committed by
					
						
						Matthias Clasen
					
				
			
			
				
	
			
			
			
						parent
						
							d69d57afa7
						
					
				
				
					commit
					983a03d5f8
				
			@ -65,6 +65,7 @@
 | 
			
		||||
#include "gtktextiterprivate.h"
 | 
			
		||||
#include "gtkdebug.h"
 | 
			
		||||
#include "gtktextmarkprivate.h"
 | 
			
		||||
#include "gtktextsegment.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Types
 | 
			
		||||
@ -901,9 +902,9 @@ _gtk_text_btree_delete (GtkTextIter *start,
 | 
			
		||||
	       * cleanup_line() below. See bug 317125.
 | 
			
		||||
	       */
 | 
			
		||||
	      next2 = prev_seg->next->next;
 | 
			
		||||
	      g_free ((char *)prev_seg->next);
 | 
			
		||||
              _gtk_toggle_segment_free (prev_seg->next);
 | 
			
		||||
	      prev_seg->next = next2;
 | 
			
		||||
	      g_free ((char *)seg);
 | 
			
		||||
              _gtk_toggle_segment_free (seg);
 | 
			
		||||
	      seg = NULL;
 | 
			
		||||
	    }
 | 
			
		||||
	  else
 | 
			
		||||
@ -1952,7 +1953,7 @@ _gtk_text_btree_tag (const GtkTextIter *start_orig,
 | 
			
		||||
          seg->body.toggle.inNodeCounts = FALSE;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      g_free (seg);
 | 
			
		||||
      _gtk_toggle_segment_free (seg);
 | 
			
		||||
 | 
			
		||||
      /* We only clean up lines when we're done with them, saves some
 | 
			
		||||
         gratuitous line-segment-traversals */
 | 
			
		||||
 | 
			
		||||
@ -73,6 +73,12 @@
 | 
			
		||||
      }                                                                 \
 | 
			
		||||
  } G_STMT_END
 | 
			
		||||
 | 
			
		||||
#define PIXBUF_SEG_SIZE ((unsigned) (G_STRUCT_OFFSET (GtkTextLineSegment, body) \
 | 
			
		||||
        + sizeof (GtkTextPixbuf)))
 | 
			
		||||
 | 
			
		||||
#define WIDGET_SEG_SIZE ((unsigned) (G_STRUCT_OFFSET (GtkTextLineSegment, body) \
 | 
			
		||||
        + sizeof (GtkTextChildBody)))
 | 
			
		||||
 | 
			
		||||
static GtkTextLineSegment *
 | 
			
		||||
pixbuf_segment_cleanup_func (GtkTextLineSegment *seg,
 | 
			
		||||
                             GtkTextLine        *line)
 | 
			
		||||
@ -89,7 +95,7 @@ pixbuf_segment_delete_func (GtkTextLineSegment *seg,
 | 
			
		||||
  if (seg->body.pixbuf.pixbuf)
 | 
			
		||||
    g_object_unref (seg->body.pixbuf.pixbuf);
 | 
			
		||||
 | 
			
		||||
  g_free (seg);
 | 
			
		||||
  g_slice_free1 (PIXBUF_SEG_SIZE, seg);
 | 
			
		||||
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
@ -120,15 +126,12 @@ const GtkTextLineSegmentClass gtk_text_pixbuf_type = {
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define PIXBUF_SEG_SIZE ((unsigned) (G_STRUCT_OFFSET (GtkTextLineSegment, body) \
 | 
			
		||||
        + sizeof (GtkTextPixbuf)))
 | 
			
		||||
 | 
			
		||||
GtkTextLineSegment *
 | 
			
		||||
_gtk_pixbuf_segment_new (GdkPixbuf *pixbuf)
 | 
			
		||||
{
 | 
			
		||||
  GtkTextLineSegment *seg;
 | 
			
		||||
 | 
			
		||||
  seg = g_malloc (PIXBUF_SEG_SIZE);
 | 
			
		||||
  seg = g_slice_alloc (PIXBUF_SEG_SIZE);
 | 
			
		||||
 | 
			
		||||
  seg->type = >k_text_pixbuf_type;
 | 
			
		||||
 | 
			
		||||
@ -218,15 +221,12 @@ const GtkTextLineSegmentClass gtk_text_child_type = {
 | 
			
		||||
  child_segment_check_func                               /* checkFunc */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define WIDGET_SEG_SIZE ((unsigned) (G_STRUCT_OFFSET (GtkTextLineSegment, body) \
 | 
			
		||||
        + sizeof (GtkTextChildBody)))
 | 
			
		||||
 | 
			
		||||
GtkTextLineSegment *
 | 
			
		||||
_gtk_widget_segment_new (GtkTextChildAnchor *anchor)
 | 
			
		||||
{
 | 
			
		||||
  GtkTextLineSegment *seg;
 | 
			
		||||
 | 
			
		||||
  seg = g_malloc (WIDGET_SEG_SIZE);
 | 
			
		||||
  seg = g_slice_alloc (WIDGET_SEG_SIZE);
 | 
			
		||||
 | 
			
		||||
  seg->type = >k_text_child_type;
 | 
			
		||||
 | 
			
		||||
@ -370,8 +370,8 @@ gtk_text_child_anchor_finalize (GObject *obj)
 | 
			
		||||
        }
 | 
			
		||||
  
 | 
			
		||||
      g_slist_free (seg->body.child.widgets);
 | 
			
		||||
  
 | 
			
		||||
      g_free (seg);
 | 
			
		||||
 | 
			
		||||
      g_slice_free1 (WIDGET_SEG_SIZE, seg);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  anchor->segment = NULL;
 | 
			
		||||
 | 
			
		||||
@ -90,6 +90,11 @@
 | 
			
		||||
 * Marks are typically created using the gtk_text_buffer_create_mark() function.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Macro that determines the size of a mark segment:
 | 
			
		||||
 */
 | 
			
		||||
#define MSEG_SIZE ((unsigned) (G_STRUCT_OFFSET (GtkTextLineSegment, body) \
 | 
			
		||||
        + sizeof (GtkTextMarkBody)))
 | 
			
		||||
 | 
			
		||||
static void gtk_text_mark_set_property (GObject         *object,
 | 
			
		||||
				        guint            prop_id,
 | 
			
		||||
@ -161,7 +166,7 @@ gtk_text_mark_finalize (GObject *obj)
 | 
			
		||||
                   "impending");
 | 
			
		||||
 | 
			
		||||
      g_free (seg->body.mark.name);
 | 
			
		||||
      g_free (seg);
 | 
			
		||||
      g_slice_free1 (MSEG_SIZE, seg);
 | 
			
		||||
 | 
			
		||||
      mark->segment = NULL;
 | 
			
		||||
    }
 | 
			
		||||
@ -358,20 +363,12 @@ gtk_text_mark_get_left_gravity (GtkTextMark *mark)
 | 
			
		||||
  return seg->type == >k_text_left_mark_type;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Macro that determines the size of a mark segment:
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#define MSEG_SIZE ((unsigned) (G_STRUCT_OFFSET (GtkTextLineSegment, body) \
 | 
			
		||||
        + sizeof (GtkTextMarkBody)))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static GtkTextLineSegment *
 | 
			
		||||
gtk_mark_segment_new (GtkTextMark *mark_obj)
 | 
			
		||||
{
 | 
			
		||||
  GtkTextLineSegment *mark;
 | 
			
		||||
 | 
			
		||||
  mark = (GtkTextLineSegment *) g_malloc0 (MSEG_SIZE);
 | 
			
		||||
  mark = g_slice_alloc0 (MSEG_SIZE);
 | 
			
		||||
  mark->body.mark.name = NULL;
 | 
			
		||||
  mark->type = >k_text_right_mark_type;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -194,7 +194,7 @@ _gtk_char_segment_new (const gchar *text, guint len)
 | 
			
		||||
 | 
			
		||||
  g_assert (gtk_text_byte_begins_utf8_char (text));
 | 
			
		||||
 | 
			
		||||
  seg = g_malloc (CSEG_SIZE (len));
 | 
			
		||||
  seg = g_slice_alloc (CSEG_SIZE (len));
 | 
			
		||||
  seg->type = (GtkTextLineSegmentClass *)>k_text_char_type;
 | 
			
		||||
  seg->next = NULL;
 | 
			
		||||
  seg->byte_count = len;
 | 
			
		||||
@ -222,7 +222,7 @@ _gtk_char_segment_new_from_two_strings (const gchar *text1,
 | 
			
		||||
  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 = g_slice_alloc (CSEG_SIZE (len1+len2));
 | 
			
		||||
  seg->type = >k_text_char_type;
 | 
			
		||||
  seg->next = NULL;
 | 
			
		||||
  seg->byte_count = len1 + len2;
 | 
			
		||||
@ -238,6 +238,17 @@ _gtk_char_segment_new_from_two_strings (const gchar *text1,
 | 
			
		||||
  return seg;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
_gtk_char_segment_free (GtkTextLineSegment *seg)
 | 
			
		||||
{
 | 
			
		||||
  if (seg == NULL)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  g_assert (seg->type == >k_text_char_type);
 | 
			
		||||
 | 
			
		||||
  g_slice_free1 (CSEG_SIZE (seg->byte_count), seg);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 *--------------------------------------------------------------
 | 
			
		||||
 *
 | 
			
		||||
@ -285,7 +296,7 @@ char_segment_split_func (GtkTextLineSegment *seg, int index)
 | 
			
		||||
      char_segment_self_check (new2);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  g_free (seg);
 | 
			
		||||
  _gtk_char_segment_free (seg);
 | 
			
		||||
  return new1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -340,8 +351,8 @@ char_segment_cleanup_func (GtkTextLineSegment *segPtr, GtkTextLine *line)
 | 
			
		||||
  if (gtk_get_debug_flags () & GTK_DEBUG_TEXT)
 | 
			
		||||
    char_segment_self_check (newPtr);
 | 
			
		||||
 | 
			
		||||
  g_free (segPtr);
 | 
			
		||||
  g_free (segPtr2);
 | 
			
		||||
  _gtk_char_segment_free (segPtr);
 | 
			
		||||
  _gtk_char_segment_free (segPtr2);
 | 
			
		||||
  return newPtr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -371,7 +382,7 @@ char_segment_cleanup_func (GtkTextLineSegment *segPtr, GtkTextLine *line)
 | 
			
		||||
static int
 | 
			
		||||
char_segment_delete_func (GtkTextLineSegment *segPtr, GtkTextLine *line, int treeGone)
 | 
			
		||||
{
 | 
			
		||||
  g_free ((char*) segPtr);
 | 
			
		||||
  _gtk_char_segment_free (segPtr);
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -417,7 +428,7 @@ _gtk_toggle_segment_new (GtkTextTagInfo *info, gboolean on)
 | 
			
		||||
{
 | 
			
		||||
  GtkTextLineSegment *seg;
 | 
			
		||||
 | 
			
		||||
  seg = g_malloc (TSEG_SIZE);
 | 
			
		||||
  seg = g_slice_alloc (TSEG_SIZE);
 | 
			
		||||
 | 
			
		||||
  seg->type = on ? >k_text_toggle_on_type : >k_text_toggle_off_type;
 | 
			
		||||
 | 
			
		||||
@ -432,6 +443,18 @@ _gtk_toggle_segment_new (GtkTextTagInfo *info, gboolean on)
 | 
			
		||||
  return seg;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
_gtk_toggle_segment_free (GtkTextLineSegment *seg)
 | 
			
		||||
{
 | 
			
		||||
  if (seg == NULL)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  g_assert (seg->type == >k_text_toggle_on_type ||
 | 
			
		||||
            seg->type == >k_text_toggle_off_type);
 | 
			
		||||
 | 
			
		||||
  g_slice_free1 (TSEG_SIZE, seg);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 *--------------------------------------------------------------
 | 
			
		||||
 *
 | 
			
		||||
@ -462,7 +485,7 @@ toggle_segment_delete_func (GtkTextLineSegment *segPtr, GtkTextLine *line, int t
 | 
			
		||||
{
 | 
			
		||||
  if (treeGone)
 | 
			
		||||
    {
 | 
			
		||||
      g_free ((char *) segPtr);
 | 
			
		||||
      _gtk_toggle_segment_free (segPtr);
 | 
			
		||||
      return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -545,9 +568,9 @@ toggle_segment_cleanup_func (GtkTextLineSegment *segPtr, GtkTextLine *line)
 | 
			
		||||
                                             segPtr->body.toggle.info, -counts);
 | 
			
		||||
            }
 | 
			
		||||
          prevPtr->next = segPtr2->next;
 | 
			
		||||
          g_free ((char *) segPtr2);
 | 
			
		||||
          _gtk_toggle_segment_free (segPtr2);
 | 
			
		||||
          segPtr2 = segPtr->next;
 | 
			
		||||
          g_free ((char *) segPtr);
 | 
			
		||||
          _gtk_toggle_segment_free (segPtr);
 | 
			
		||||
          return segPtr2;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -164,6 +164,7 @@ GtkTextLineSegment *_gtk_char_segment_new_from_two_strings (const gchar    *text
 | 
			
		||||
GtkTextLineSegment *_gtk_toggle_segment_new                (GtkTextTagInfo *info,
 | 
			
		||||
                                                            gboolean        on);
 | 
			
		||||
 | 
			
		||||
void                _gtk_toggle_segment_free               (GtkTextLineSegment *seg);
 | 
			
		||||
 | 
			
		||||
G_END_DECLS
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user