gtktextmark.c 6.13 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
/* 
 * tkTextMark.c --
 *
 *	This file contains the procedure that implement marks for
 *	text widgets.
 *
 * Copyright (c) 1994 The Regents of the University of California.
 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id$
 */

#include "gtktextbtree.h"

gboolean
gtk_text_mark_is_visible(GtkTextMark *mark)
{
  GtkTextLineSegment *seg;

  seg = (GtkTextLineSegment*)mark;

  return seg->body.mark.visible;
}

Havoc Pennington's avatar
Havoc Pennington committed
28
const char *
29 30 31 32 33 34
gtk_text_mark_get_name (GtkTextMark *mark)
{
  GtkTextLineSegment *seg;

  seg = (GtkTextLineSegment*)mark;

Havoc Pennington's avatar
Havoc Pennington committed
35
  return seg->body.mark.name;
36 37
}

38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61

GtkTextMark *
gtk_text_mark_ref (GtkTextMark *mark)
{
  GtkTextLineSegment *seg;

  seg = (GtkTextLineSegment*)mark;

  mark_segment_ref (seg);

  return mark;
}

void
gtk_text_mark_unref (GtkTextMark *mark)
{
  GtkTextLineSegment *seg;

  seg = (GtkTextLineSegment*)mark;
  
  mark_segment_unref (seg);
}

gboolean
62
gtk_text_mark_get_deleted (GtkTextMark *mark)
63 64 65 66 67 68 69 70 71 72
{
  GtkTextLineSegment *seg;
  
  g_return_val_if_fail (mark != NULL, FALSE);

  seg = (GtkTextLineSegment*)mark;
  
  return seg->body.mark.tree == NULL;
}

73 74 75 76 77 78 79 80 81
/*
 * Macro that determines the size of a mark segment:
 */

#define MSEG_SIZE ((unsigned) (G_STRUCT_OFFSET(GtkTextLineSegment, body) \
	+ sizeof(GtkTextMarkBody)))


GtkTextLineSegment*
82 83 84
mark_segment_new (GtkTextBTree *tree,
                  gboolean left_gravity,
                  const gchar *name)
85 86 87
{
  GtkTextLineSegment *mark;

88 89
  mark = (GtkTextLineSegment *) g_malloc0 (MSEG_SIZE);
  mark->body.mark.name = g_strdup (name);
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105

  if (left_gravity)
    mark->type = &gtk_text_left_mark_type;
  else
    mark->type = &gtk_text_right_mark_type;

  mark->byte_count = 0;
  mark->char_count = 0;

  mark->body.mark.tree = tree;
  mark->body.mark.line = NULL;
  mark->next = NULL;

  mark->body.mark.refcount = 1;

  mark->body.mark.visible = FALSE;
106
  mark->body.mark.not_deleteable = FALSE;
107 108 109 110 111 112 113
  
  return mark;
}

void
mark_segment_ref(GtkTextLineSegment *mark)
{
114 115 116 117
  g_return_if_fail (mark != NULL);
  g_return_if_fail (mark->type == &gtk_text_right_mark_type ||
                    mark->type == &gtk_text_left_mark_type);
  g_return_if_fail (mark->body.mark.refcount > 0);
118 119 120 121 122 123 124
  
  mark->body.mark.refcount += 1;
}

void
mark_segment_unref(GtkTextLineSegment *mark)
{
125 126 127 128
  g_return_if_fail (mark != NULL);
  g_return_if_fail (mark->type == &gtk_text_right_mark_type ||
                    mark->type == &gtk_text_left_mark_type);
  g_return_if_fail (mark->body.mark.refcount > 0);
129 130 131 132 133 134 135 136 137 138 139 140

  mark->body.mark.refcount -= 1;

  if (mark->body.mark.refcount == 0)
    {
      g_free(mark->body.mark.name);
      
      g_free(mark);
    }
}


141 142 143 144 145 146 147 148
static int                 mark_segment_delete_func  (GtkTextLineSegment *segPtr,
                                                      GtkTextLine        *line,
                                                      int                 treeGone);
static GtkTextLineSegment *mark_segment_cleanup_func (GtkTextLineSegment *segPtr,
                                                      GtkTextLine        *line);
static void                mark_segment_check_func   (GtkTextLineSegment *segPtr,
                                                      GtkTextLine        *line);

149 150 151 152 153 154 155 156 157

/*
 * The following structures declare the "mark" segment types.
 * There are actually two types for marks, one with left gravity
 * and one with right gravity.  They are identical except for
 * their gravity property.
 */

GtkTextLineSegmentClass gtk_text_right_mark_type = {
158
    "mark",					        /* name */
159
    FALSE,						/* leftGravity */
160
    NULL,		                        	/* splitFunc */
161 162
    mark_segment_delete_func,				/* deleteFunc */
    mark_segment_cleanup_func,				/* cleanupFunc */
163
    NULL,		                                /* lineChangeFunc */
164 165 166 167
    mark_segment_check_func				/* checkFunc */
};

GtkTextLineSegmentClass gtk_text_left_mark_type = {
168
    "mark",					        /* name */
169
    TRUE,						/* leftGravity */
170
    NULL,			                        /* splitFunc */
171 172
    mark_segment_delete_func,				/* deleteFunc */
    mark_segment_cleanup_func,				/* cleanupFunc */
173
    NULL,		                                /* lineChangeFunc */
174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
    mark_segment_check_func				/* checkFunc */
};

/*
 *--------------------------------------------------------------
 *
 * mark_segment_delete_func --
 *
 *	This procedure is invoked by the text B-tree code whenever
 *	a mark lies in a range of characters being deleted.
 *
 * Results:
 *	Returns 1 to indicate that deletion has been rejected.
 *
 * Side effects:
 *	None (even if the whole tree is being deleted we don't
 *	free up the mark;  it will be done elsewhere).
 *
 *--------------------------------------------------------------
 */

195 196 197 198
static gboolean
mark_segment_delete_func (GtkTextLineSegment *segPtr,
                          GtkTextLine        *line,
                          gboolean            tree_gone)
199
{
200
  return TRUE;
201
}
202

203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
/*
 *--------------------------------------------------------------
 *
 * mark_segment_cleanup_func --
 *
 *	This procedure is invoked by the B-tree code whenever a
 *	mark segment is moved from one line to another.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The line field of the segment gets updated.
 *
 *--------------------------------------------------------------
 */

static GtkTextLineSegment *
221 222
mark_segment_cleanup_func(GtkTextLineSegment *seg,
                          GtkTextLine        *line)
223
{
224 225 226
  /* not sure why Tk did this here and not in LineChangeFunc */
  seg->body.mark.line = line;
  return seg;
227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247
}

/*
 *--------------------------------------------------------------
 *
 * mark_segment_check_func --
 *
 *	This procedure is invoked by the B-tree code to perform
 *	consistency checks on mark segments.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The procedure panics if it detects anything wrong with
 *	the mark.
 *
 *--------------------------------------------------------------
 */

static void
248 249
mark_segment_check_func(GtkTextLineSegment *seg,
                        GtkTextLine        *line)
250
{
251 252
  if (seg->body.mark.line != line)
    g_error("mark_segment_check_func: seg->body.mark.line bogus");
253
}