forked from AuroraMiddleware/gtk
clean up trailing whitespace, add extensive tests for tag toggle
2000-10-03 Havoc Pennington <hp@redhat.com> * gtk/testtextbuffer.c: clean up trailing whitespace, add extensive tests for tag toggle iteration. * gtk/gtktextiter.c (MAX_LINEAR_SCAN): decrease linear scan distance * gtk/gtktextbtree.c (gtk_text_line_next_could_contain_tag): optimize case where the tag root is on level 1 (gtk_text_line_previous_could_contain_tag): attempt to implement (gtk_text_line_next_could_contain_tag): Abstract out node_compare functionality * gtk/gtktextiter.c (gtk_text_iter_backward_to_tag_toggle): Implement this, though not very efficiently. * gtk/gtktextiterprivate.h: reformat * gtk/gtktextiter.c (gtk_text_iter_get_char): return 0 on the end iterator * gtk/gtktextbuffer.c (gtk_text_buffer_delete_interactive): Fix this to properly revalidate the iterators. * gtk/gtktextview.c (gtk_text_view_delete): fix control-K to work properly at the end of the line (and therefore on empty lines) * gtk/gtktextbtree.c (gtk_text_btree_get_selection_bounds): Gee, maybe we should return a value...
This commit is contained in:
parent
69ac9451a6
commit
928c069883
31
ChangeLog
31
ChangeLog
@ -1,3 +1,34 @@
|
||||
2000-10-03 Havoc Pennington <hp@redhat.com>
|
||||
|
||||
* gtk/testtextbuffer.c: clean up trailing whitespace,
|
||||
add extensive tests for tag toggle iteration.
|
||||
|
||||
* gtk/gtktextiter.c (MAX_LINEAR_SCAN): decrease linear scan
|
||||
distance
|
||||
|
||||
* gtk/gtktextbtree.c (gtk_text_line_next_could_contain_tag):
|
||||
optimize case where the tag root is on level 1
|
||||
(gtk_text_line_previous_could_contain_tag): attempt to implement
|
||||
(gtk_text_line_next_could_contain_tag): Abstract out node_compare
|
||||
functionality
|
||||
|
||||
* gtk/gtktextiter.c (gtk_text_iter_backward_to_tag_toggle):
|
||||
Implement this, though not very efficiently.
|
||||
|
||||
* gtk/gtktextiterprivate.h: reformat
|
||||
|
||||
* gtk/gtktextiter.c (gtk_text_iter_get_char): return 0 on the end
|
||||
iterator
|
||||
|
||||
* gtk/gtktextbuffer.c (gtk_text_buffer_delete_interactive): Fix
|
||||
this to properly revalidate the iterators.
|
||||
|
||||
* gtk/gtktextview.c (gtk_text_view_delete): fix control-K to work
|
||||
properly at the end of the line (and therefore on empty lines)
|
||||
|
||||
* gtk/gtktextbtree.c (gtk_text_btree_get_selection_bounds): Gee,
|
||||
maybe we should return a value...
|
||||
|
||||
2000-10-03 Tor Lillqvist <tml@iki.fi>
|
||||
|
||||
* config.h.win32: Guard definition of alloca(). glib.h now handles
|
||||
|
@ -1,3 +1,34 @@
|
||||
2000-10-03 Havoc Pennington <hp@redhat.com>
|
||||
|
||||
* gtk/testtextbuffer.c: clean up trailing whitespace,
|
||||
add extensive tests for tag toggle iteration.
|
||||
|
||||
* gtk/gtktextiter.c (MAX_LINEAR_SCAN): decrease linear scan
|
||||
distance
|
||||
|
||||
* gtk/gtktextbtree.c (gtk_text_line_next_could_contain_tag):
|
||||
optimize case where the tag root is on level 1
|
||||
(gtk_text_line_previous_could_contain_tag): attempt to implement
|
||||
(gtk_text_line_next_could_contain_tag): Abstract out node_compare
|
||||
functionality
|
||||
|
||||
* gtk/gtktextiter.c (gtk_text_iter_backward_to_tag_toggle):
|
||||
Implement this, though not very efficiently.
|
||||
|
||||
* gtk/gtktextiterprivate.h: reformat
|
||||
|
||||
* gtk/gtktextiter.c (gtk_text_iter_get_char): return 0 on the end
|
||||
iterator
|
||||
|
||||
* gtk/gtktextbuffer.c (gtk_text_buffer_delete_interactive): Fix
|
||||
this to properly revalidate the iterators.
|
||||
|
||||
* gtk/gtktextview.c (gtk_text_view_delete): fix control-K to work
|
||||
properly at the end of the line (and therefore on empty lines)
|
||||
|
||||
* gtk/gtktextbtree.c (gtk_text_btree_get_selection_bounds): Gee,
|
||||
maybe we should return a value...
|
||||
|
||||
2000-10-03 Tor Lillqvist <tml@iki.fi>
|
||||
|
||||
* config.h.win32: Guard definition of alloca(). glib.h now handles
|
||||
|
@ -1,3 +1,34 @@
|
||||
2000-10-03 Havoc Pennington <hp@redhat.com>
|
||||
|
||||
* gtk/testtextbuffer.c: clean up trailing whitespace,
|
||||
add extensive tests for tag toggle iteration.
|
||||
|
||||
* gtk/gtktextiter.c (MAX_LINEAR_SCAN): decrease linear scan
|
||||
distance
|
||||
|
||||
* gtk/gtktextbtree.c (gtk_text_line_next_could_contain_tag):
|
||||
optimize case where the tag root is on level 1
|
||||
(gtk_text_line_previous_could_contain_tag): attempt to implement
|
||||
(gtk_text_line_next_could_contain_tag): Abstract out node_compare
|
||||
functionality
|
||||
|
||||
* gtk/gtktextiter.c (gtk_text_iter_backward_to_tag_toggle):
|
||||
Implement this, though not very efficiently.
|
||||
|
||||
* gtk/gtktextiterprivate.h: reformat
|
||||
|
||||
* gtk/gtktextiter.c (gtk_text_iter_get_char): return 0 on the end
|
||||
iterator
|
||||
|
||||
* gtk/gtktextbuffer.c (gtk_text_buffer_delete_interactive): Fix
|
||||
this to properly revalidate the iterators.
|
||||
|
||||
* gtk/gtktextview.c (gtk_text_view_delete): fix control-K to work
|
||||
properly at the end of the line (and therefore on empty lines)
|
||||
|
||||
* gtk/gtktextbtree.c (gtk_text_btree_get_selection_bounds): Gee,
|
||||
maybe we should return a value...
|
||||
|
||||
2000-10-03 Tor Lillqvist <tml@iki.fi>
|
||||
|
||||
* config.h.win32: Guard definition of alloca(). glib.h now handles
|
||||
|
@ -1,3 +1,34 @@
|
||||
2000-10-03 Havoc Pennington <hp@redhat.com>
|
||||
|
||||
* gtk/testtextbuffer.c: clean up trailing whitespace,
|
||||
add extensive tests for tag toggle iteration.
|
||||
|
||||
* gtk/gtktextiter.c (MAX_LINEAR_SCAN): decrease linear scan
|
||||
distance
|
||||
|
||||
* gtk/gtktextbtree.c (gtk_text_line_next_could_contain_tag):
|
||||
optimize case where the tag root is on level 1
|
||||
(gtk_text_line_previous_could_contain_tag): attempt to implement
|
||||
(gtk_text_line_next_could_contain_tag): Abstract out node_compare
|
||||
functionality
|
||||
|
||||
* gtk/gtktextiter.c (gtk_text_iter_backward_to_tag_toggle):
|
||||
Implement this, though not very efficiently.
|
||||
|
||||
* gtk/gtktextiterprivate.h: reformat
|
||||
|
||||
* gtk/gtktextiter.c (gtk_text_iter_get_char): return 0 on the end
|
||||
iterator
|
||||
|
||||
* gtk/gtktextbuffer.c (gtk_text_buffer_delete_interactive): Fix
|
||||
this to properly revalidate the iterators.
|
||||
|
||||
* gtk/gtktextview.c (gtk_text_view_delete): fix control-K to work
|
||||
properly at the end of the line (and therefore on empty lines)
|
||||
|
||||
* gtk/gtktextbtree.c (gtk_text_btree_get_selection_bounds): Gee,
|
||||
maybe we should return a value...
|
||||
|
||||
2000-10-03 Tor Lillqvist <tml@iki.fi>
|
||||
|
||||
* config.h.win32: Guard definition of alloca(). glib.h now handles
|
||||
|
@ -1,3 +1,34 @@
|
||||
2000-10-03 Havoc Pennington <hp@redhat.com>
|
||||
|
||||
* gtk/testtextbuffer.c: clean up trailing whitespace,
|
||||
add extensive tests for tag toggle iteration.
|
||||
|
||||
* gtk/gtktextiter.c (MAX_LINEAR_SCAN): decrease linear scan
|
||||
distance
|
||||
|
||||
* gtk/gtktextbtree.c (gtk_text_line_next_could_contain_tag):
|
||||
optimize case where the tag root is on level 1
|
||||
(gtk_text_line_previous_could_contain_tag): attempt to implement
|
||||
(gtk_text_line_next_could_contain_tag): Abstract out node_compare
|
||||
functionality
|
||||
|
||||
* gtk/gtktextiter.c (gtk_text_iter_backward_to_tag_toggle):
|
||||
Implement this, though not very efficiently.
|
||||
|
||||
* gtk/gtktextiterprivate.h: reformat
|
||||
|
||||
* gtk/gtktextiter.c (gtk_text_iter_get_char): return 0 on the end
|
||||
iterator
|
||||
|
||||
* gtk/gtktextbuffer.c (gtk_text_buffer_delete_interactive): Fix
|
||||
this to properly revalidate the iterators.
|
||||
|
||||
* gtk/gtktextview.c (gtk_text_view_delete): fix control-K to work
|
||||
properly at the end of the line (and therefore on empty lines)
|
||||
|
||||
* gtk/gtktextbtree.c (gtk_text_btree_get_selection_bounds): Gee,
|
||||
maybe we should return a value...
|
||||
|
||||
2000-10-03 Tor Lillqvist <tml@iki.fi>
|
||||
|
||||
* config.h.win32: Guard definition of alloca(). glib.h now handles
|
||||
|
@ -1,3 +1,34 @@
|
||||
2000-10-03 Havoc Pennington <hp@redhat.com>
|
||||
|
||||
* gtk/testtextbuffer.c: clean up trailing whitespace,
|
||||
add extensive tests for tag toggle iteration.
|
||||
|
||||
* gtk/gtktextiter.c (MAX_LINEAR_SCAN): decrease linear scan
|
||||
distance
|
||||
|
||||
* gtk/gtktextbtree.c (gtk_text_line_next_could_contain_tag):
|
||||
optimize case where the tag root is on level 1
|
||||
(gtk_text_line_previous_could_contain_tag): attempt to implement
|
||||
(gtk_text_line_next_could_contain_tag): Abstract out node_compare
|
||||
functionality
|
||||
|
||||
* gtk/gtktextiter.c (gtk_text_iter_backward_to_tag_toggle):
|
||||
Implement this, though not very efficiently.
|
||||
|
||||
* gtk/gtktextiterprivate.h: reformat
|
||||
|
||||
* gtk/gtktextiter.c (gtk_text_iter_get_char): return 0 on the end
|
||||
iterator
|
||||
|
||||
* gtk/gtktextbuffer.c (gtk_text_buffer_delete_interactive): Fix
|
||||
this to properly revalidate the iterators.
|
||||
|
||||
* gtk/gtktextview.c (gtk_text_view_delete): fix control-K to work
|
||||
properly at the end of the line (and therefore on empty lines)
|
||||
|
||||
* gtk/gtktextbtree.c (gtk_text_btree_get_selection_bounds): Gee,
|
||||
maybe we should return a value...
|
||||
|
||||
2000-10-03 Tor Lillqvist <tml@iki.fi>
|
||||
|
||||
* config.h.win32: Guard definition of alloca(). glib.h now handles
|
||||
|
@ -1,3 +1,34 @@
|
||||
2000-10-03 Havoc Pennington <hp@redhat.com>
|
||||
|
||||
* gtk/testtextbuffer.c: clean up trailing whitespace,
|
||||
add extensive tests for tag toggle iteration.
|
||||
|
||||
* gtk/gtktextiter.c (MAX_LINEAR_SCAN): decrease linear scan
|
||||
distance
|
||||
|
||||
* gtk/gtktextbtree.c (gtk_text_line_next_could_contain_tag):
|
||||
optimize case where the tag root is on level 1
|
||||
(gtk_text_line_previous_could_contain_tag): attempt to implement
|
||||
(gtk_text_line_next_could_contain_tag): Abstract out node_compare
|
||||
functionality
|
||||
|
||||
* gtk/gtktextiter.c (gtk_text_iter_backward_to_tag_toggle):
|
||||
Implement this, though not very efficiently.
|
||||
|
||||
* gtk/gtktextiterprivate.h: reformat
|
||||
|
||||
* gtk/gtktextiter.c (gtk_text_iter_get_char): return 0 on the end
|
||||
iterator
|
||||
|
||||
* gtk/gtktextbuffer.c (gtk_text_buffer_delete_interactive): Fix
|
||||
this to properly revalidate the iterators.
|
||||
|
||||
* gtk/gtktextview.c (gtk_text_view_delete): fix control-K to work
|
||||
properly at the end of the line (and therefore on empty lines)
|
||||
|
||||
* gtk/gtktextbtree.c (gtk_text_btree_get_selection_bounds): Gee,
|
||||
maybe we should return a value...
|
||||
|
||||
2000-10-03 Tor Lillqvist <tml@iki.fi>
|
||||
|
||||
* config.h.win32: Guard definition of alloca(). glib.h now handles
|
||||
|
@ -414,9 +414,9 @@ gtk_text_btree_new (GtkTextTagTable *table,
|
||||
tree->mark_table = g_hash_table_new(g_str_hash, g_str_equal);
|
||||
|
||||
/* We don't ref the buffer, since the buffer owns us;
|
||||
we'd have some circularity issues. The buffer always
|
||||
lasts longer than the BTree
|
||||
*/
|
||||
* we'd have some circularity issues. The buffer always
|
||||
* lasts longer than the BTree
|
||||
*/
|
||||
tree->buffer = buffer;
|
||||
|
||||
{
|
||||
@ -434,7 +434,6 @@ gtk_text_btree_new (GtkTextTagTable *table,
|
||||
FALSE);
|
||||
|
||||
tree->insert_mark->body.mark.not_deleteable = TRUE;
|
||||
|
||||
tree->insert_mark->body.mark.visible = TRUE;
|
||||
|
||||
tree->selection_bound_mark =
|
||||
@ -2486,6 +2485,8 @@ gtk_text_btree_get_selection_bounds (GtkTextBTree *tree,
|
||||
|
||||
if (end)
|
||||
*end = tmp_end;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2502,7 +2503,7 @@ gtk_text_btree_get_selection_bounds (GtkTextBTree *tree,
|
||||
}
|
||||
|
||||
void
|
||||
gtk_text_btree_place_cursor(GtkTextBTree *tree,
|
||||
gtk_text_btree_place_cursor(GtkTextBTree *tree,
|
||||
const GtkTextIter *iter)
|
||||
{
|
||||
GtkTextIter start, end;
|
||||
@ -2585,7 +2586,7 @@ gtk_text_btree_get_mark_by_name (GtkTextBTree *tree,
|
||||
|
||||
void
|
||||
gtk_text_mark_set_visible (GtkTextMark *mark,
|
||||
gboolean setting)
|
||||
gboolean setting)
|
||||
{
|
||||
GtkTextLineSegment *seg;
|
||||
|
||||
@ -2599,7 +2600,7 @@ gtk_text_mark_set_visible (GtkTextMark *mark,
|
||||
{
|
||||
seg->body.mark.visible = setting;
|
||||
|
||||
redisplay_mark(seg);
|
||||
redisplay_mark (seg);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3052,12 +3053,12 @@ gtk_text_line_previous (GtkTextLine *line)
|
||||
return prev;
|
||||
}
|
||||
|
||||
g_assert_not_reached();
|
||||
g_assert_not_reached ();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
gtk_text_line_add_data (GtkTextLine *line,
|
||||
gtk_text_line_add_data (GtkTextLine *line,
|
||||
GtkTextLineData *data)
|
||||
{
|
||||
g_return_if_fail(line != NULL);
|
||||
@ -3418,7 +3419,6 @@ gtk_text_line_char_to_byte (GtkTextLine *line,
|
||||
g_warning("FIXME not implemented");
|
||||
}
|
||||
|
||||
|
||||
/* FIXME sync with char_locate (or figure out a clean
|
||||
way to merge the two functions) */
|
||||
void
|
||||
@ -3692,6 +3692,101 @@ gtk_text_line_char_to_byte_offsets(GtkTextLine *line,
|
||||
}
|
||||
}
|
||||
|
||||
static gint
|
||||
node_compare (GtkTextBTreeNode *lhs,
|
||||
GtkTextBTreeNode *rhs)
|
||||
{
|
||||
GtkTextBTreeNode *iter;
|
||||
GtkTextBTreeNode *node;
|
||||
GtkTextBTreeNode *common_parent;
|
||||
GtkTextBTreeNode *parent_of_lower;
|
||||
GtkTextBTreeNode *parent_of_higher;
|
||||
gboolean lhs_is_lower;
|
||||
GtkTextBTreeNode *lower;
|
||||
GtkTextBTreeNode *higher;
|
||||
|
||||
/* This function assumes that lhs and rhs are not underneath each
|
||||
* other.
|
||||
*/
|
||||
|
||||
if (lhs == rhs)
|
||||
return 0;
|
||||
|
||||
if (lhs->level < rhs->level)
|
||||
{
|
||||
lhs_is_lower = TRUE;
|
||||
lower = lhs;
|
||||
higher = rhs;
|
||||
}
|
||||
else
|
||||
{
|
||||
lhs_is_lower = FALSE;
|
||||
lower = rhs;
|
||||
higher = lhs;
|
||||
}
|
||||
|
||||
/* Algorithm: find common parent of lhs/rhs. Save the child nodes
|
||||
* of the common parent we used to reach the common parent; the
|
||||
* ordering of these child nodes in the child list is the ordering
|
||||
* of lhs and rhs.
|
||||
*/
|
||||
|
||||
/* Get on the same level (may be on same level already) */
|
||||
node = lower;
|
||||
while (node->level < higher->level)
|
||||
node = node->parent;
|
||||
|
||||
g_assert (node->level == higher->level);
|
||||
|
||||
g_assert (node != higher); /* Happens if lower is underneath higher */
|
||||
|
||||
/* Go up until we have two children with a common parent.
|
||||
*/
|
||||
parent_of_lower = node;
|
||||
parent_of_higher = higher;
|
||||
|
||||
while (parent_of_lower->parent != parent_of_higher->parent)
|
||||
{
|
||||
parent_of_lower = parent_of_lower->parent;
|
||||
parent_of_higher = parent_of_higher->parent;
|
||||
}
|
||||
|
||||
g_assert (parent_of_lower->parent == parent_of_higher->parent);
|
||||
|
||||
common_parent = parent_of_lower->parent;
|
||||
|
||||
g_assert (common_parent != NULL);
|
||||
|
||||
/* See which is first in the list of common_parent's children */
|
||||
iter = common_parent->children.node;
|
||||
while (iter != NULL)
|
||||
{
|
||||
if (iter == parent_of_higher)
|
||||
{
|
||||
/* higher is less than lower */
|
||||
|
||||
if (lhs_is_lower)
|
||||
return 1; /* lhs > rhs */
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
else if (iter == parent_of_lower)
|
||||
{
|
||||
/* lower is less than higher */
|
||||
|
||||
if (lhs_is_lower)
|
||||
return -1; /* lhs < rhs */
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
iter = iter->next;
|
||||
}
|
||||
|
||||
g_assert_not_reached ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* remember that tag == NULL means "any tag" */
|
||||
GtkTextLine*
|
||||
gtk_text_line_next_could_contain_tag(GtkTextLine *line,
|
||||
@ -3710,7 +3805,8 @@ gtk_text_line_next_could_contain_tag(GtkTextLine *line,
|
||||
if (tag == NULL)
|
||||
{
|
||||
/* Right now we can only offer linear-search if the user wants
|
||||
to know about any tag toggle at all. */
|
||||
* to know about any tag toggle at all.
|
||||
*/
|
||||
return gtk_text_line_next (line);
|
||||
}
|
||||
|
||||
@ -3733,6 +3829,9 @@ gtk_text_line_next_could_contain_tag(GtkTextLine *line,
|
||||
|
||||
if (info->tag_root == NULL)
|
||||
return NULL;
|
||||
|
||||
if (info->tag_root == line->parent)
|
||||
return NULL; /* we were at the last line under the tag root */
|
||||
|
||||
/* We need to go up out of this node, and on to the next one with
|
||||
toggles for the target tag. If we're below the tag root, we need to
|
||||
@ -3773,57 +3872,25 @@ gtk_text_line_next_could_contain_tag(GtkTextLine *line,
|
||||
}
|
||||
else
|
||||
{
|
||||
GtkTextBTreeNode * iter;
|
||||
GtkTextBTreeNode * common_parent;
|
||||
GtkTextBTreeNode * parent_of_tag_root;
|
||||
GtkTextBTreeNode * parent_of_node;
|
||||
gint ordering;
|
||||
|
||||
/* Find common parent between our current line, and the tag
|
||||
root. Save the child nodes of the common parent we used to get
|
||||
to the common parent; we then use these two child nodes to
|
||||
determine whether the ordering of the tag root and the current
|
||||
line in the tree. (Nice code cleanup: write
|
||||
gtk_btree_node_compare() to compute node ordering.)
|
||||
*/
|
||||
ordering = node_compare (line->parent, info->tag_root);
|
||||
|
||||
/* Get on the same level */
|
||||
node = line->parent;
|
||||
while (node->level < info->tag_root->level)
|
||||
node = node->parent;
|
||||
|
||||
common_parent = info->tag_root->parent;
|
||||
|
||||
/* Find common parent, and children of that parent above
|
||||
tag root and our current node */
|
||||
parent_of_node = node;
|
||||
parent_of_tag_root = info->tag_root;
|
||||
|
||||
while (node->parent != common_parent)
|
||||
if (ordering < 0)
|
||||
{
|
||||
parent_of_node = node;
|
||||
parent_of_tag_root = common_parent;
|
||||
node = node->parent;
|
||||
common_parent = common_parent->parent;
|
||||
/* Tag root is ahead of us, so search there. */
|
||||
node = info->tag_root;
|
||||
goto found;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Tag root is after us, so no more lines that
|
||||
* could contain the tag.
|
||||
*/
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* See which is first in the list of common_parent's children */
|
||||
iter = common_parent->children.node;
|
||||
while (iter != NULL)
|
||||
{
|
||||
if (iter == parent_of_tag_root)
|
||||
return NULL; /* Tag root was before us in the tree */
|
||||
else if (iter == parent_of_node)
|
||||
{
|
||||
/* We want the first inside-tag-root node,
|
||||
since we're before the tag root */
|
||||
node = info->tag_root;
|
||||
goto found;
|
||||
}
|
||||
|
||||
iter = iter->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
found:
|
||||
@ -3831,42 +3898,261 @@ gtk_text_line_next_could_contain_tag(GtkTextLine *line,
|
||||
g_assert(node != NULL);
|
||||
|
||||
/* We have to find the first sub-node of this node that contains
|
||||
the target tag. */
|
||||
* the target tag.
|
||||
*/
|
||||
|
||||
continue_outer_loop:
|
||||
while (node->level > 0)
|
||||
{
|
||||
g_assert(node != NULL); /* If this fails, it likely means an
|
||||
incorrect tag summary led us on a
|
||||
wild goose chase down this branch of
|
||||
the tree. */
|
||||
g_assert (node != NULL); /* If this fails, it likely means an
|
||||
incorrect tag summary led us on a
|
||||
wild goose chase down this branch of
|
||||
the tree. */
|
||||
node = node->children.node;
|
||||
while (node != NULL)
|
||||
{
|
||||
if (gtk_text_btree_node_has_tag(node, tag))
|
||||
goto continue_outer_loop;
|
||||
if (gtk_text_btree_node_has_tag (node, tag))
|
||||
break;
|
||||
node = node->next;
|
||||
}
|
||||
g_assert(node != NULL);
|
||||
}
|
||||
|
||||
g_assert(node != NULL);
|
||||
g_assert(node->level == 0);
|
||||
g_assert (node != NULL);
|
||||
g_assert (node->level == 0);
|
||||
|
||||
return node->children.line;
|
||||
}
|
||||
|
||||
GtkTextLine*
|
||||
gtk_text_line_previous_could_contain_tag(GtkTextLine *line,
|
||||
GtkTextBTree *tree,
|
||||
GtkTextTag *tag)
|
||||
{
|
||||
g_warning("FIXME");
|
||||
|
||||
static GtkTextLine*
|
||||
prev_line_under_node (GtkTextBTreeNode *node,
|
||||
GtkTextLine *line)
|
||||
{
|
||||
GtkTextLine *prev;
|
||||
|
||||
prev = node->children.line;
|
||||
|
||||
g_assert (prev);
|
||||
|
||||
if (prev != line)
|
||||
{
|
||||
while (prev->next != line)
|
||||
prev = prev->next;
|
||||
|
||||
return prev;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GtkTextLine*
|
||||
gtk_text_line_previous_could_contain_tag (GtkTextLine *line,
|
||||
GtkTextBTree *tree,
|
||||
GtkTextTag *tag)
|
||||
{
|
||||
GtkTextBTreeNode *node;
|
||||
GtkTextBTreeNode *found_node = NULL;
|
||||
GtkTextTagInfo *info;
|
||||
gboolean below_tag_root;
|
||||
GtkTextLine *prev;
|
||||
GtkTextBTreeNode *line_ancestor;
|
||||
GtkTextBTreeNode *line_ancestor_parent;
|
||||
|
||||
/* See next_could_contain_tag() for more extensive comments
|
||||
* on what's going on here.
|
||||
*/
|
||||
|
||||
g_return_val_if_fail(line != NULL, NULL);
|
||||
|
||||
if (gtk_debug_flags & GTK_DEBUG_TEXT)
|
||||
gtk_text_btree_check (tree);
|
||||
|
||||
if (tag == NULL)
|
||||
{
|
||||
/* Right now we can only offer linear-search if the user wants
|
||||
* to know about any tag toggle at all.
|
||||
*/
|
||||
return gtk_text_line_previous (line);
|
||||
}
|
||||
|
||||
/* Return same-node line, if any. */
|
||||
prev = prev_line_under_node (line->parent, line);
|
||||
if (prev)
|
||||
return prev;
|
||||
|
||||
info = gtk_text_btree_get_existing_tag_info (tree, tag);
|
||||
if (info == NULL)
|
||||
return NULL;
|
||||
|
||||
if (info->tag_root == NULL)
|
||||
return NULL;
|
||||
|
||||
if (info->tag_root == line->parent)
|
||||
return NULL; /* we were at the first line under the tag root */
|
||||
|
||||
/* Are we below the tag root */
|
||||
node = line->parent;
|
||||
below_tag_root = FALSE;
|
||||
while (node != NULL)
|
||||
{
|
||||
if (node == info->tag_root)
|
||||
{
|
||||
below_tag_root = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
node = node->parent;
|
||||
}
|
||||
|
||||
if (below_tag_root)
|
||||
{
|
||||
/* Look for a previous node under this tag root that has our
|
||||
* tag.
|
||||
*/
|
||||
|
||||
/* this assertion holds because line->parent is not the
|
||||
* tag root, we are below the tag root, and the tag
|
||||
* root exists.
|
||||
*/
|
||||
g_assert (line->parent->parent != NULL);
|
||||
|
||||
line_ancestor = line->parent;
|
||||
line_ancestor_parent = line->parent->parent;
|
||||
|
||||
node = line_ancestor_parent->children.node;
|
||||
while (node != line_ancestor &&
|
||||
line_ancestor != info->tag_root)
|
||||
{
|
||||
GSList *child_nodes = NULL;
|
||||
GSList *tmp;
|
||||
|
||||
/* Create reverse-order list of nodes before
|
||||
* line_ancestor
|
||||
*/
|
||||
while (node != line_ancestor
|
||||
&& node != NULL)
|
||||
{
|
||||
child_nodes = g_slist_prepend (child_nodes, node);
|
||||
|
||||
node = node->next;
|
||||
}
|
||||
|
||||
/* Try to find a node with our tag on it in the list */
|
||||
tmp = child_nodes;
|
||||
while (tmp != NULL)
|
||||
{
|
||||
GtkTextBTreeNode *this_node = tmp->data;
|
||||
|
||||
g_assert (this_node != line_ancestor);
|
||||
|
||||
if (gtk_text_btree_node_has_tag (this_node, tag))
|
||||
{
|
||||
found_node = this_node;
|
||||
g_slist_free (child_nodes);
|
||||
goto found;
|
||||
}
|
||||
|
||||
tmp = g_slist_next (tmp);
|
||||
}
|
||||
|
||||
g_slist_free (child_nodes);
|
||||
|
||||
/* Didn't find anything on this level; go up one level. */
|
||||
line_ancestor = line_ancestor_parent;
|
||||
line_ancestor_parent = line_ancestor->parent;
|
||||
|
||||
node = line_ancestor_parent->children.node;
|
||||
}
|
||||
|
||||
/* No dice. */
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
gint ordering;
|
||||
|
||||
ordering = node_compare (line->parent, info->tag_root);
|
||||
|
||||
if (ordering < 0)
|
||||
{
|
||||
/* Tag root is ahead of us, so no more lines
|
||||
* with this tag.
|
||||
*/
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Tag root is after us, so grab last tagged
|
||||
* line underneath the tag root.
|
||||
*/
|
||||
found_node = info->tag_root;
|
||||
goto found;
|
||||
}
|
||||
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
found:
|
||||
|
||||
g_assert (found_node != NULL);
|
||||
|
||||
/* We have to find the last sub-node of this node that contains
|
||||
* the target tag.
|
||||
*/
|
||||
node = found_node;
|
||||
|
||||
while (node->level > 0)
|
||||
{
|
||||
GSList *child_nodes = NULL;
|
||||
GSList *iter;
|
||||
g_assert (node != NULL); /* If this fails, it likely means an
|
||||
incorrect tag summary led us on a
|
||||
wild goose chase down this branch of
|
||||
the tree. */
|
||||
|
||||
node = node->children.node;
|
||||
while (node != NULL)
|
||||
{
|
||||
child_nodes = g_slist_prepend (child_nodes, node);
|
||||
node = node->next;
|
||||
}
|
||||
|
||||
node = NULL; /* detect failure to find a child node. */
|
||||
|
||||
iter = child_nodes;
|
||||
while (iter != NULL)
|
||||
{
|
||||
if (gtk_text_btree_node_has_tag (iter->data, tag))
|
||||
{
|
||||
/* recurse into this node. */
|
||||
node = iter->data;
|
||||
break;
|
||||
}
|
||||
|
||||
iter = g_slist_next (iter);
|
||||
}
|
||||
|
||||
g_slist_free (child_nodes);
|
||||
|
||||
g_assert (node != NULL);
|
||||
}
|
||||
|
||||
g_assert (node != NULL);
|
||||
g_assert (node->level == 0);
|
||||
|
||||
/* this assertion is correct, but slow. */
|
||||
/* g_assert (node_compare (node, line->parent) < 0); */
|
||||
|
||||
/* Return last line in this node. */
|
||||
|
||||
prev = node->children.line;
|
||||
while (prev->next)
|
||||
prev = prev->next;
|
||||
|
||||
return prev;
|
||||
}
|
||||
|
||||
/*
|
||||
* Non-public function implementations */
|
||||
* Non-public function implementations
|
||||
*/
|
||||
|
||||
static void
|
||||
summary_list_destroy(Summary *summary)
|
||||
@ -6260,6 +6546,11 @@ gtk_text_btree_spew (GtkTextBTree *tree)
|
||||
|
||||
list = g_slist_next (list);
|
||||
}
|
||||
|
||||
if (tree->tag_infos == NULL)
|
||||
{
|
||||
printf (" (no tags in the tree)\n");
|
||||
}
|
||||
}
|
||||
|
||||
printf("=================== Tree nodes\n");
|
||||
@ -6301,11 +6592,17 @@ gtk_text_btree_spew_line_short (GtkTextLine *line, int indent)
|
||||
}
|
||||
else if (seg->type == >k_text_right_mark_type)
|
||||
{
|
||||
printf("%s right mark `%s'\n", spaces, seg->body.mark.name);
|
||||
printf("%s right mark `%s' visible: %d\n",
|
||||
spaces,
|
||||
seg->body.mark.name,
|
||||
seg->body.mark.visible);
|
||||
}
|
||||
else if (seg->type == >k_text_left_mark_type)
|
||||
{
|
||||
printf("%s left mark `%s'\n", spaces, seg->body.mark.name);
|
||||
printf("%s left mark `%s' visible: %d\n",
|
||||
spaces,
|
||||
seg->body.mark.name,
|
||||
seg->body.mark.visible);
|
||||
}
|
||||
else if (seg->type == >k_text_toggle_on_type ||
|
||||
seg->type == >k_text_toggle_off_type)
|
||||
@ -6397,11 +6694,17 @@ gtk_text_btree_spew_segment(GtkTextBTree* tree, GtkTextLineSegment * seg)
|
||||
}
|
||||
else if (seg->type == >k_text_right_mark_type)
|
||||
{
|
||||
printf(" right mark `%s'\n", seg->body.mark.name);
|
||||
printf(" right mark `%s' visible: %d not_deleteable: %d\n",
|
||||
seg->body.mark.name,
|
||||
seg->body.mark.visible,
|
||||
seg->body.mark.not_deleteable);
|
||||
}
|
||||
else if (seg->type == >k_text_left_mark_type)
|
||||
{
|
||||
printf(" left mark `%s'\n", seg->body.mark.name);
|
||||
printf(" left mark `%s' visible: %d not_deleteable: %d\n",
|
||||
seg->body.mark.name,
|
||||
seg->body.mark.visible,
|
||||
seg->body.mark.not_deleteable);
|
||||
}
|
||||
else if (seg->type == >k_text_toggle_on_type ||
|
||||
seg->type == >k_text_toggle_off_type)
|
||||
|
@ -821,8 +821,8 @@ gtk_text_buffer_emit_delete (GtkTextBuffer *buffer,
|
||||
**/
|
||||
void
|
||||
gtk_text_buffer_delete (GtkTextBuffer *buffer,
|
||||
GtkTextIter *start,
|
||||
GtkTextIter *end)
|
||||
GtkTextIter *start,
|
||||
GtkTextIter *end)
|
||||
{
|
||||
g_return_if_fail(GTK_IS_TEXT_BUFFER(buffer));
|
||||
g_return_if_fail(start != NULL);
|
||||
@ -840,7 +840,9 @@ gtk_text_buffer_delete (GtkTextBuffer *buffer,
|
||||
*
|
||||
* Deletes all <emphasis>editable</emphasis> text in the given range.
|
||||
* Calls gtk_text_buffer_delete() for each editable sub-range of
|
||||
* [@start,@end).
|
||||
* [@start,@end). @start and @end are revalidated to point to
|
||||
* the location of the last deleted range, or left untouched if
|
||||
* no text was deleted.
|
||||
*
|
||||
* Return value: whether some text was actually deleted
|
||||
**/
|
||||
@ -904,6 +906,10 @@ gtk_text_buffer_delete_interactive (GtkTextBuffer *buffer,
|
||||
gtk_text_buffer_emit_delete (buffer, &start, &iter, TRUE);
|
||||
|
||||
deleted_stuff = TRUE;
|
||||
|
||||
/* revalidate user's iterators. */
|
||||
*start_iter = start;
|
||||
*end_iter = iter;
|
||||
}
|
||||
|
||||
break;
|
||||
@ -923,6 +929,10 @@ gtk_text_buffer_delete_interactive (GtkTextBuffer *buffer,
|
||||
|
||||
current_state = FALSE;
|
||||
deleted_stuff = TRUE;
|
||||
|
||||
/* revalidate user's iterators. */
|
||||
*start_iter = start;
|
||||
*end_iter = iter;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1478,7 +1488,7 @@ gtk_text_buffer_real_apply_tag (GtkTextBuffer *buffer,
|
||||
const GtkTextIter *start,
|
||||
const GtkTextIter *end)
|
||||
{
|
||||
gtk_text_btree_tag(start, end, tag, TRUE);
|
||||
gtk_text_btree_tag (start, end, tag, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1487,7 +1497,7 @@ gtk_text_buffer_real_remove_tag (GtkTextBuffer *buffer,
|
||||
const GtkTextIter *start,
|
||||
const GtkTextIter *end)
|
||||
{
|
||||
gtk_text_btree_tag(start, end, tag, FALSE);
|
||||
gtk_text_btree_tag (start, end, tag, FALSE);
|
||||
}
|
||||
|
||||
|
||||
@ -1500,12 +1510,14 @@ gtk_text_buffer_emit_tag(GtkTextBuffer *buffer,
|
||||
{
|
||||
g_return_if_fail(tag != NULL);
|
||||
|
||||
gtk_text_iter_reorder (start, end);
|
||||
|
||||
if (apply)
|
||||
gtk_signal_emit(GTK_OBJECT(buffer), signals[APPLY_TAG],
|
||||
tag, start, end);
|
||||
gtk_signal_emit (GTK_OBJECT(buffer), signals[APPLY_TAG],
|
||||
tag, start, end);
|
||||
else
|
||||
gtk_signal_emit(GTK_OBJECT(buffer), signals[REMOVE_TAG],
|
||||
tag, start, end);
|
||||
gtk_signal_emit (GTK_OBJECT(buffer), signals[REMOVE_TAG],
|
||||
tag, start, end);
|
||||
}
|
||||
|
||||
|
||||
|
@ -33,7 +33,8 @@
|
||||
|
||||
typedef struct _GtkTextRealIter GtkTextRealIter;
|
||||
|
||||
struct _GtkTextRealIter {
|
||||
struct _GtkTextRealIter
|
||||
{
|
||||
/* Always-valid information */
|
||||
GtkTextBTree *tree;
|
||||
GtkTextLine *line;
|
||||
@ -53,7 +54,7 @@ struct _GtkTextRealIter {
|
||||
/* Valid if the segments_changed_stamp is up-to-date */
|
||||
GtkTextLineSegment *segment; /* indexable segment we index */
|
||||
GtkTextLineSegment *any_segment; /* first segment in our location,
|
||||
maybe same as "segment" */
|
||||
maybe same as "segment" */
|
||||
/* One of these will always be valid if segments_changed_stamp is
|
||||
up-to-date. If invalid, they are -1.
|
||||
|
||||
@ -94,7 +95,7 @@ iter_set_from_byte_offset(GtkTextRealIter *iter,
|
||||
{
|
||||
iter_set_common(iter, line);
|
||||
|
||||
gtk_text_line_byte_locate(iter->line,
|
||||
gtk_text_line_byte_locate (iter->line,
|
||||
byte_offset,
|
||||
&iter->segment,
|
||||
&iter->any_segment,
|
||||
@ -110,7 +111,7 @@ iter_set_from_char_offset(GtkTextRealIter *iter,
|
||||
{
|
||||
iter_set_common(iter, line);
|
||||
|
||||
gtk_text_line_char_locate(iter->line,
|
||||
gtk_text_line_char_locate (iter->line,
|
||||
char_offset,
|
||||
&iter->segment,
|
||||
&iter->any_segment,
|
||||
@ -362,6 +363,12 @@ ensure_byte_offsets(GtkTextRealIter *iter)
|
||||
}
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
is_segment_start (GtkTextRealIter *real)
|
||||
{
|
||||
return real->segment_byte_offset == 0 || real->segment_char_offset == 0;
|
||||
}
|
||||
|
||||
#if 1
|
||||
static void
|
||||
check_invariants(const GtkTextIter *iter)
|
||||
@ -689,12 +696,15 @@ gtk_text_iter_get_line_index(const GtkTextIter *iter)
|
||||
* Returns the Unicode character at this iterator. (Equivalent to
|
||||
* operator* on a C++ iterator.) If the iterator points at a
|
||||
* non-character element, such as an image embedded in the buffer, the
|
||||
* Unicode "unknown" character 0xFFFD is returned.
|
||||
* Unicode "unknown" character 0xFFFD is returned. If invoked on
|
||||
* the end iterator, zero is returned; zero is not a valid Unicode character.
|
||||
* So you can write a loop which ends when gtk_text_iter_get_char()
|
||||
* returns 0.
|
||||
*
|
||||
* Return value: a Unicode character
|
||||
* Return value: a Unicode character, or 0 if @iter is not dereferenceable
|
||||
**/
|
||||
gunichar
|
||||
gtk_text_iter_get_char(const GtkTextIter *iter)
|
||||
gtk_text_iter_get_char (const GtkTextIter *iter)
|
||||
{
|
||||
GtkTextRealIter *real;
|
||||
|
||||
@ -705,12 +715,11 @@ gtk_text_iter_get_char(const GtkTextIter *iter)
|
||||
if (real == NULL)
|
||||
return 0;
|
||||
|
||||
check_invariants(iter);
|
||||
|
||||
/* FIXME probably want to special-case the end iterator
|
||||
and either have an error or return 0 */
|
||||
|
||||
if (real->segment->type == >k_text_char_type)
|
||||
check_invariants(iter);
|
||||
|
||||
if (gtk_text_iter_is_last (iter))
|
||||
return 0;
|
||||
else if (real->segment->type == >k_text_char_type)
|
||||
{
|
||||
ensure_byte_offsets(real);
|
||||
|
||||
@ -1392,13 +1401,13 @@ gtk_text_iter_get_attributes (const GtkTextIter *iter,
|
||||
* (MOVEMENT OCCURRED && NEW ITER IS DEREFERENCEABLE)
|
||||
*/
|
||||
static gboolean
|
||||
forward_line_leaving_caches_unmodified(GtkTextRealIter *real)
|
||||
forward_line_leaving_caches_unmodified (GtkTextRealIter *real)
|
||||
{
|
||||
GtkTextLine *new_line;
|
||||
|
||||
new_line = gtk_text_line_next(real->line);
|
||||
new_line = gtk_text_line_next (real->line);
|
||||
|
||||
g_assert(new_line != real->line);
|
||||
g_assert (new_line != real->line);
|
||||
|
||||
if (new_line != NULL)
|
||||
{
|
||||
@ -1442,11 +1451,56 @@ forward_line_leaving_caches_unmodified(GtkTextRealIter *real)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* The return value of this indicates WHETHER WE MOVED.
|
||||
* The return value of public functions indicates
|
||||
* (MOVEMENT OCCURRED && NEW ITER IS DEREFERENCEABLE)
|
||||
*/
|
||||
static gboolean
|
||||
backward_line_leaving_caches_unmodified (GtkTextRealIter *real)
|
||||
{
|
||||
GtkTextLine *new_line;
|
||||
|
||||
new_line = gtk_text_line_previous (real->line);
|
||||
|
||||
g_assert (new_line != real->line);
|
||||
|
||||
if (new_line != NULL)
|
||||
{
|
||||
real->line = new_line;
|
||||
|
||||
real->line_byte_offset = 0;
|
||||
real->line_char_offset = 0;
|
||||
|
||||
real->segment_byte_offset = 0;
|
||||
real->segment_char_offset = 0;
|
||||
|
||||
/* Find first segments in new line */
|
||||
real->any_segment = real->line->segments;
|
||||
real->segment = real->any_segment;
|
||||
while (real->segment->char_count == 0)
|
||||
real->segment = real->segment->next;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* There is no way to move backward; we were already
|
||||
at the first line. */
|
||||
|
||||
/* We leave real->line as-is */
|
||||
|
||||
/* Note that we didn't clamp to the start of the first line. */
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* The return value indicates (MOVEMENT OCCURRED && NEW ITER IS
|
||||
* DEREFERENCEABLE)
|
||||
*/
|
||||
static gboolean
|
||||
forward_char(GtkTextRealIter *real)
|
||||
forward_char (GtkTextRealIter *real)
|
||||
{
|
||||
GtkTextIter *iter = (GtkTextIter*)real;
|
||||
|
||||
@ -1465,7 +1519,7 @@ forward_char(GtkTextRealIter *real)
|
||||
/* Just moving within a segment. Keep byte count
|
||||
up-to-date, if it was already up-to-date. */
|
||||
|
||||
g_assert(real->segment->type == >k_text_char_type);
|
||||
g_assert (real->segment->type == >k_text_char_type);
|
||||
|
||||
if (real->line_byte_offset >= 0)
|
||||
{
|
||||
@ -1502,7 +1556,7 @@ forward_char(GtkTextRealIter *real)
|
||||
}
|
||||
|
||||
gboolean
|
||||
gtk_text_iter_forward_indexable_segment(GtkTextIter *iter)
|
||||
gtk_text_iter_forward_indexable_segment (GtkTextIter *iter)
|
||||
{
|
||||
/* Need to move to the next segment; if no next segment,
|
||||
need to move to next line. */
|
||||
@ -1524,7 +1578,7 @@ gtk_text_iter_forward_indexable_segment(GtkTextIter *iter)
|
||||
if (real->line_char_offset >= 0)
|
||||
{
|
||||
chars_skipped = real->segment->char_count - real->segment_char_offset;
|
||||
g_assert(chars_skipped > 0);
|
||||
g_assert (chars_skipped > 0);
|
||||
}
|
||||
else
|
||||
chars_skipped = 0;
|
||||
@ -1532,7 +1586,7 @@ gtk_text_iter_forward_indexable_segment(GtkTextIter *iter)
|
||||
if (real->line_byte_offset >= 0)
|
||||
{
|
||||
bytes_skipped = real->segment->byte_count - real->segment_byte_offset;
|
||||
g_assert(bytes_skipped > 0);
|
||||
g_assert (bytes_skipped > 0);
|
||||
}
|
||||
else
|
||||
bytes_skipped = 0;
|
||||
@ -1551,17 +1605,17 @@ gtk_text_iter_forward_indexable_segment(GtkTextIter *iter)
|
||||
|
||||
if (real->line_byte_offset >= 0)
|
||||
{
|
||||
g_assert(bytes_skipped > 0);
|
||||
g_assert (bytes_skipped > 0);
|
||||
real->segment_byte_offset = 0;
|
||||
real->line_byte_offset += bytes_skipped;
|
||||
}
|
||||
|
||||
if (real->line_char_offset >= 0)
|
||||
{
|
||||
g_assert(chars_skipped > 0);
|
||||
g_assert (chars_skipped > 0);
|
||||
real->segment_char_offset = 0;
|
||||
real->line_char_offset += chars_skipped;
|
||||
adjust_char_index(real, chars_skipped);
|
||||
adjust_char_index (real, chars_skipped);
|
||||
}
|
||||
|
||||
check_invariants(iter);
|
||||
@ -1571,21 +1625,19 @@ gtk_text_iter_forward_indexable_segment(GtkTextIter *iter)
|
||||
else
|
||||
{
|
||||
/* End of the line */
|
||||
if (forward_line_leaving_caches_unmodified(real))
|
||||
if (forward_line_leaving_caches_unmodified (real))
|
||||
{
|
||||
adjust_line_number(real, 1);
|
||||
adjust_line_number (real, 1);
|
||||
if (real->line_char_offset >= 0)
|
||||
adjust_char_index(real, chars_skipped);
|
||||
adjust_char_index (real, chars_skipped);
|
||||
|
||||
check_invariants(iter);
|
||||
g_assert (real->line_byte_offset == 0);
|
||||
g_assert (real->line_char_offset == 0);
|
||||
g_assert (real->segment_byte_offset == 0);
|
||||
g_assert (real->segment_char_offset == 0);
|
||||
g_assert (gtk_text_iter_starts_line(iter));
|
||||
|
||||
g_assert(real->line_byte_offset == 0);
|
||||
g_assert(real->line_char_offset == 0);
|
||||
g_assert(real->segment_byte_offset == 0);
|
||||
g_assert(real->segment_char_offset == 0);
|
||||
g_assert(gtk_text_iter_starts_line(iter));
|
||||
|
||||
check_invariants(iter);
|
||||
check_invariants (iter);
|
||||
|
||||
if (gtk_text_iter_is_last (iter))
|
||||
return FALSE;
|
||||
@ -1603,13 +1655,156 @@ gtk_text_iter_forward_indexable_segment(GtkTextIter *iter)
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
gtk_text_iter_backward_indexable_segment(GtkTextIter *iter)
|
||||
static gboolean
|
||||
at_last_indexable_segment (GtkTextRealIter *real)
|
||||
{
|
||||
g_warning("FIXME");
|
||||
GtkTextLineSegment *seg;
|
||||
|
||||
/* Return TRUE if there are no indexable segments after
|
||||
* this iterator.
|
||||
*/
|
||||
|
||||
seg = real->segment->next;
|
||||
while (seg)
|
||||
{
|
||||
if (seg->char_count > 0)
|
||||
return FALSE;
|
||||
seg = seg->next;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
/* Goes back to the start of the next segment, even if
|
||||
* we're not at the start of the current segment (always
|
||||
* ends up on a different segment if it returns TRUE)
|
||||
*/
|
||||
gboolean
|
||||
gtk_text_iter_backward_indexable_segment (GtkTextIter *iter)
|
||||
{
|
||||
/* Move to the start of the previous segment; if no previous
|
||||
* segment, to the last segment in the previous line. This is
|
||||
* inherently a bit inefficient due to the singly-linked list and
|
||||
* tree nodes, but we can't afford the RAM for doubly-linked.
|
||||
*/
|
||||
GtkTextRealIter *real;
|
||||
GtkTextLineSegment *seg;
|
||||
GtkTextLineSegment *any_seg;
|
||||
GtkTextLineSegment *prev_seg;
|
||||
GtkTextLineSegment *prev_any_seg;
|
||||
gint bytes_skipped;
|
||||
gint chars_skipped;
|
||||
|
||||
g_return_val_if_fail (iter != NULL, FALSE);
|
||||
|
||||
real = gtk_text_iter_make_real(iter);
|
||||
|
||||
if (real == NULL)
|
||||
return FALSE;
|
||||
|
||||
check_invariants (iter);
|
||||
|
||||
/* Find first segments in line */
|
||||
any_seg = real->line->segments;
|
||||
seg = any_seg;
|
||||
while (seg->char_count == 0)
|
||||
seg = seg->next;
|
||||
|
||||
if (seg == real->segment)
|
||||
{
|
||||
/* Could probably do this case faster by hand-coding the
|
||||
* iteration.
|
||||
*/
|
||||
|
||||
/* We were already at the start of a line;
|
||||
* go back to the previous line.
|
||||
*/
|
||||
if (gtk_text_iter_backward_line (iter))
|
||||
{
|
||||
/* Go forward to last indexable segment in line. */
|
||||
while (!at_last_indexable_segment (real))
|
||||
gtk_text_iter_forward_indexable_segment (iter);
|
||||
|
||||
check_invariants (iter);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE; /* We were at the start of the first line. */
|
||||
}
|
||||
|
||||
/* We must be in the middle of a line; so find the indexable
|
||||
* segment just before our current segment.
|
||||
*/
|
||||
g_assert (seg != real->segment);
|
||||
while (seg != real->segment)
|
||||
{
|
||||
prev_seg = seg;
|
||||
prev_any_seg = any_seg;
|
||||
|
||||
any_seg = seg->next;
|
||||
seg = any_seg;
|
||||
while (seg->char_count == 0)
|
||||
seg = seg->next;
|
||||
}
|
||||
|
||||
g_assert (prev_seg != NULL);
|
||||
g_assert (prev_any_seg != NULL);
|
||||
g_assert (prev_seg->char_count > 0);
|
||||
|
||||
/* We skipped the entire previous segment, plus any
|
||||
* chars we were into the current segment.
|
||||
*/
|
||||
if (real->segment_byte_offset >= 0)
|
||||
bytes_skipped = prev_seg->byte_count + real->segment_byte_offset;
|
||||
else
|
||||
bytes_skipped = -1;
|
||||
|
||||
if (real->segment_char_offset >= 0)
|
||||
chars_skipped = prev_seg->char_count + real->segment_char_offset;
|
||||
else
|
||||
chars_skipped = -1;
|
||||
|
||||
real->segment = prev_seg;
|
||||
real->any_segment = prev_any_seg;
|
||||
real->segment_byte_offset = 0;
|
||||
real->segment_char_offset = 0;
|
||||
|
||||
if (bytes_skipped >= 0)
|
||||
{
|
||||
if (real->line_byte_offset >= 0)
|
||||
{
|
||||
real->line_byte_offset -= bytes_skipped;
|
||||
g_assert (real->line_byte_offset >= 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
real->line_byte_offset = -1;
|
||||
|
||||
if (chars_skipped >= 0)
|
||||
{
|
||||
if (real->line_char_offset >= 0)
|
||||
{
|
||||
real->line_char_offset -= chars_skipped;
|
||||
g_assert (real->line_char_offset >= 0);
|
||||
}
|
||||
|
||||
if (real->cached_char_index >= 0)
|
||||
{
|
||||
real->cached_char_index -= chars_skipped;
|
||||
g_assert (real->cached_char_index >= 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
real->line_char_offset = -1;
|
||||
real->cached_char_index = -1;
|
||||
}
|
||||
|
||||
/* line number is unchanged. */
|
||||
|
||||
check_invariants (iter);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1677,7 +1872,7 @@ gtk_text_iter_prev_char(GtkTextIter *iter)
|
||||
|
||||
I guess you'd have to profile the various approaches.
|
||||
*/
|
||||
#define MAX_LINEAR_SCAN 300
|
||||
#define MAX_LINEAR_SCAN 150
|
||||
|
||||
|
||||
/**
|
||||
@ -1822,23 +2017,34 @@ gtk_text_iter_backward_chars(GtkTextIter *iter, gint count)
|
||||
else
|
||||
{
|
||||
/* We need to go back into previous segments. For now,
|
||||
just keep this really simple. */
|
||||
gint current_char_index;
|
||||
gint new_char_index;
|
||||
* just keep this really simple. FIXME
|
||||
* use backward_indexable_segment.
|
||||
*/
|
||||
if (TRUE || count > MAX_LINEAR_SCAN)
|
||||
{
|
||||
gint current_char_index;
|
||||
gint new_char_index;
|
||||
|
||||
current_char_index = gtk_text_iter_get_offset(iter);
|
||||
current_char_index = gtk_text_iter_get_offset (iter);
|
||||
|
||||
if (current_char_index == 0)
|
||||
return FALSE; /* can't move backward */
|
||||
if (current_char_index == 0)
|
||||
return FALSE; /* can't move backward */
|
||||
|
||||
new_char_index = current_char_index - count;
|
||||
if (new_char_index < 0)
|
||||
new_char_index = 0;
|
||||
gtk_text_iter_set_offset(iter, new_char_index);
|
||||
new_char_index = current_char_index - count;
|
||||
if (new_char_index < 0)
|
||||
new_char_index = 0;
|
||||
gtk_text_iter_set_offset (iter, new_char_index);
|
||||
|
||||
check_invariants(iter);
|
||||
check_invariants(iter);
|
||||
|
||||
return TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* FIXME backward_indexable_segment here */
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1935,7 +2141,7 @@ gtk_text_iter_backward_line(GtkTextIter *iter)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
invalidate_char_index(real);
|
||||
invalidate_char_index (real);
|
||||
|
||||
real->line_byte_offset = 0;
|
||||
real->line_char_offset = 0;
|
||||
@ -1946,7 +2152,7 @@ gtk_text_iter_backward_line(GtkTextIter *iter)
|
||||
/* Find first segment in line */
|
||||
real->any_segment = real->line->segments;
|
||||
real->segment = gtk_text_line_byte_to_segment(real->line,
|
||||
0, &offset);
|
||||
0, &offset);
|
||||
|
||||
g_assert(offset == 0);
|
||||
|
||||
@ -2207,18 +2413,18 @@ gtk_text_iter_set_line_offset(GtkTextIter *iter,
|
||||
{
|
||||
GtkTextRealIter *real;
|
||||
|
||||
g_return_if_fail(iter != NULL);
|
||||
g_return_if_fail (iter != NULL);
|
||||
|
||||
real = gtk_text_iter_make_surreal(iter);
|
||||
real = gtk_text_iter_make_surreal (iter);
|
||||
|
||||
if (real == NULL)
|
||||
return;
|
||||
|
||||
check_invariants(iter);
|
||||
check_invariants (iter);
|
||||
|
||||
iter_set_from_char_offset(real, real->line, char_on_line);
|
||||
iter_set_from_char_offset (real, real->line, char_on_line);
|
||||
|
||||
check_invariants(iter);
|
||||
check_invariants (iter);
|
||||
}
|
||||
|
||||
void
|
||||
@ -2228,23 +2434,23 @@ gtk_text_iter_set_line(GtkTextIter *iter, gint line_number)
|
||||
gint real_line;
|
||||
GtkTextRealIter *real;
|
||||
|
||||
g_return_if_fail(iter != NULL);
|
||||
g_return_if_fail (iter != NULL);
|
||||
|
||||
real = gtk_text_iter_make_surreal(iter);
|
||||
real = gtk_text_iter_make_surreal (iter);
|
||||
|
||||
if (real == NULL)
|
||||
return;
|
||||
|
||||
check_invariants(iter);
|
||||
check_invariants (iter);
|
||||
|
||||
line = gtk_text_btree_get_line(real->tree, line_number, &real_line);
|
||||
line = gtk_text_btree_get_line (real->tree, line_number, &real_line);
|
||||
|
||||
iter_set_from_char_offset(real, line, 0);
|
||||
iter_set_from_char_offset (real, line, 0);
|
||||
|
||||
/* We might as well cache this, since we know it. */
|
||||
real->cached_line_number = real_line;
|
||||
|
||||
check_invariants(iter);
|
||||
check_invariants (iter);
|
||||
}
|
||||
|
||||
void
|
||||
@ -2360,10 +2566,10 @@ gtk_text_iter_forward_to_tag_toggle (GtkTextIter *iter,
|
||||
check_invariants(iter);
|
||||
|
||||
current_line = real->line;
|
||||
next_line = gtk_text_line_next_could_contain_tag(current_line,
|
||||
real->tree, tag);
|
||||
next_line = gtk_text_line_next_could_contain_tag (current_line,
|
||||
real->tree, tag);
|
||||
|
||||
while (gtk_text_iter_forward_indexable_segment(iter))
|
||||
while (gtk_text_iter_forward_indexable_segment (iter))
|
||||
{
|
||||
/* If we went forward to a line that couldn't contain a toggle
|
||||
for the tag, then skip forward to a line that could contain
|
||||
@ -2374,15 +2580,15 @@ gtk_text_iter_forward_to_tag_toggle (GtkTextIter *iter,
|
||||
if (next_line == NULL)
|
||||
{
|
||||
/* End of search. Set to end of buffer. */
|
||||
gtk_text_btree_get_last_iter(real->tree, iter);
|
||||
gtk_text_btree_get_last_iter (real->tree, iter);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (real->line != next_line)
|
||||
iter_set_from_byte_offset(real, next_line, 0);
|
||||
iter_set_from_byte_offset (real, next_line, 0);
|
||||
|
||||
current_line = real->line;
|
||||
next_line = gtk_text_line_next_could_contain_tag(current_line,
|
||||
next_line = gtk_text_line_next_could_contain_tag (current_line,
|
||||
real->tree,
|
||||
tag);
|
||||
}
|
||||
@ -2397,7 +2603,7 @@ gtk_text_iter_forward_to_tag_toggle (GtkTextIter *iter,
|
||||
}
|
||||
|
||||
/* Check end iterator for tags */
|
||||
if (gtk_text_iter_toggles_tag(iter, tag))
|
||||
if (gtk_text_iter_toggles_tag (iter, tag))
|
||||
{
|
||||
/* If there's a toggle here, it isn't indexable so
|
||||
any_segment can't be the indexable segment. */
|
||||
@ -2409,12 +2615,103 @@ gtk_text_iter_forward_to_tag_toggle (GtkTextIter *iter,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_text_iter_backward_to_tag_toggle:
|
||||
* @iter: a #GtkTextIter
|
||||
* @tag: a #GtkTextTag, or NULL
|
||||
*
|
||||
* Moves backward to the next toggle (on or off) of the
|
||||
* #GtkTextTag @tag, or to the next toggle of any tag if
|
||||
* @tag is NULL. If no matching tag toggles are found,
|
||||
* returns FALSE, otherwise TRUE. Does not return toggles
|
||||
* located at @iter, only toggles before @iter.
|
||||
*
|
||||
* Return value: whether we found a tag toggle before @iter
|
||||
**/
|
||||
gboolean
|
||||
gtk_text_iter_backward_to_tag_toggle (GtkTextIter *iter,
|
||||
GtkTextTag *tag)
|
||||
{
|
||||
GtkTextLine *prev_line;
|
||||
GtkTextLine *current_line;
|
||||
GtkTextRealIter *real;
|
||||
|
||||
g_warning("FIXME");
|
||||
g_return_val_if_fail(iter != NULL, FALSE);
|
||||
|
||||
real = gtk_text_iter_make_real(iter);
|
||||
|
||||
if (real == NULL)
|
||||
return FALSE;
|
||||
|
||||
check_invariants(iter);
|
||||
|
||||
current_line = real->line;
|
||||
prev_line = gtk_text_line_previous_could_contain_tag (current_line,
|
||||
real->tree, tag);
|
||||
|
||||
|
||||
/* If we're at segment start, go to the previous segment;
|
||||
* if mid-segment, snap to start of current segment.
|
||||
*/
|
||||
if (is_segment_start (real))
|
||||
{
|
||||
if (!gtk_text_iter_backward_indexable_segment (iter))
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
ensure_char_offsets (real);
|
||||
|
||||
if (!gtk_text_iter_backward_chars (iter, real->segment_char_offset))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
/* If we went backward to a line that couldn't contain a toggle
|
||||
* for the tag, then skip backward further to a line that
|
||||
* could contain it. This potentially skips huge hunks of the
|
||||
* tree, so we aren't a purely linear search.
|
||||
*/
|
||||
if (real->line != current_line)
|
||||
{
|
||||
if (prev_line == NULL)
|
||||
{
|
||||
/* End of search. Set to start of buffer. */
|
||||
gtk_text_btree_get_iter_at_char (real->tree, iter, 0);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (real->line != prev_line)
|
||||
{
|
||||
/* Set to last segment in prev_line (could do this
|
||||
* more quickly)
|
||||
*/
|
||||
iter_set_from_byte_offset (real, prev_line, 0);
|
||||
|
||||
while (!at_last_indexable_segment (real))
|
||||
gtk_text_iter_forward_indexable_segment (iter);
|
||||
}
|
||||
|
||||
current_line = real->line;
|
||||
prev_line = gtk_text_line_previous_could_contain_tag (current_line,
|
||||
real->tree,
|
||||
tag);
|
||||
}
|
||||
|
||||
if (gtk_text_iter_toggles_tag (iter, tag))
|
||||
{
|
||||
/* If there's a toggle here, it isn't indexable so
|
||||
* any_segment can't be the indexable segment.
|
||||
*/
|
||||
g_assert (real->any_segment != real->segment);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
while (gtk_text_iter_backward_indexable_segment (iter));
|
||||
|
||||
/* Reached front of buffer */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -2437,9 +2734,9 @@ gtk_text_iter_forward_find_char (GtkTextIter *iter,
|
||||
g_return_val_if_fail(iter != NULL, FALSE);
|
||||
g_return_val_if_fail(pred != NULL, FALSE);
|
||||
|
||||
while (gtk_text_iter_next_char(iter))
|
||||
while (gtk_text_iter_next_char (iter))
|
||||
{
|
||||
if (matches_pred(iter, pred, user_data))
|
||||
if (matches_pred (iter, pred, user_data))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -2454,9 +2751,9 @@ gtk_text_iter_backward_find_char (GtkTextIter *iter,
|
||||
g_return_val_if_fail(iter != NULL, FALSE);
|
||||
g_return_val_if_fail(pred != NULL, FALSE);
|
||||
|
||||
while (gtk_text_iter_prev_char(iter))
|
||||
while (gtk_text_iter_prev_char (iter))
|
||||
{
|
||||
if (matches_pred(iter, pred, user_data))
|
||||
if (matches_pred (iter, pred, user_data))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -2640,7 +2937,8 @@ gtk_text_iter_forward_search (GtkTextIter *iter,
|
||||
* gtk_text_iter_get_text() is called repeatedly on
|
||||
* a single line.
|
||||
*/
|
||||
if (lines_match (&search, (const gchar**)lines, visible_only, slice, &match))
|
||||
if (lines_match (&search, (const gchar**)lines,
|
||||
visible_only, slice, &match))
|
||||
{
|
||||
retval = TRUE;
|
||||
|
||||
@ -3062,8 +3360,8 @@ gtk_text_iter_check (const GtkTextIter *iter)
|
||||
if (real->line_byte_offset >= 0)
|
||||
{
|
||||
gtk_text_line_byte_locate(real->line, real->line_byte_offset,
|
||||
&byte_segment, &byte_any_segment,
|
||||
&seg_byte_offset, &line_byte_offset);
|
||||
&byte_segment, &byte_any_segment,
|
||||
&seg_byte_offset, &line_byte_offset);
|
||||
|
||||
if (line_byte_offset != real->line_byte_offset)
|
||||
g_error("wrong byte offset was stored in iterator");
|
||||
@ -3084,8 +3382,8 @@ gtk_text_iter_check (const GtkTextIter *iter)
|
||||
if (real->line_char_offset >= 0)
|
||||
{
|
||||
gtk_text_line_char_locate(real->line, real->line_char_offset,
|
||||
&char_segment, &char_any_segment,
|
||||
&seg_char_offset, &line_char_offset);
|
||||
&char_segment, &char_any_segment,
|
||||
&seg_char_offset, &line_char_offset);
|
||||
|
||||
if (line_char_offset != real->line_char_offset)
|
||||
g_error("wrong char offset was stored in iterator");
|
||||
|
@ -10,18 +10,15 @@ extern "C" {
|
||||
#include <gtk/gtktextiter.h>
|
||||
#include <gtk/gtktextbtree.h>
|
||||
|
||||
GtkTextLineSegment *gtk_text_iter_get_indexable_segment(const GtkTextIter *iter);
|
||||
GtkTextLineSegment *gtk_text_iter_get_any_segment(const GtkTextIter *iter);
|
||||
GtkTextLineSegment *gtk_text_iter_get_indexable_segment (const GtkTextIter *iter);
|
||||
GtkTextLineSegment *gtk_text_iter_get_any_segment (const GtkTextIter *iter);
|
||||
GtkTextLine * gtk_text_iter_get_text_line (const GtkTextIter *iter);
|
||||
GtkTextBTree * gtk_text_iter_get_btree (const GtkTextIter *iter);
|
||||
gboolean gtk_text_iter_forward_indexable_segment (GtkTextIter *iter);
|
||||
gboolean gtk_text_iter_backward_indexable_segment (GtkTextIter *iter);
|
||||
gint gtk_text_iter_get_segment_byte (const GtkTextIter *iter);
|
||||
gint gtk_text_iter_get_segment_char (const GtkTextIter *iter);
|
||||
|
||||
GtkTextLine *gtk_text_iter_get_text_line(const GtkTextIter *iter);
|
||||
|
||||
GtkTextBTree *gtk_text_iter_get_btree(const GtkTextIter *iter);
|
||||
|
||||
gboolean gtk_text_iter_forward_indexable_segment(GtkTextIter *iter);
|
||||
gboolean gtk_text_iter_backward_indexable_segment(GtkTextIter *iter);
|
||||
|
||||
gint gtk_text_iter_get_segment_byte(const GtkTextIter *iter);
|
||||
gint gtk_text_iter_get_segment_char(const GtkTextIter *iter);
|
||||
|
||||
/* debug */
|
||||
void gtk_text_iter_check(const GtkTextIter *iter);
|
||||
|
@ -1204,8 +1204,6 @@ add_cursor (GtkTextLayout *layout,
|
||||
GtkTextLineSegment *seg,
|
||||
gint start)
|
||||
{
|
||||
GtkTextIter selection_start, selection_end;
|
||||
|
||||
PangoRectangle strong_pos, weak_pos;
|
||||
GtkTextCursorDisplay *cursor;
|
||||
|
||||
@ -1214,7 +1212,8 @@ add_cursor (GtkTextLayout *layout,
|
||||
*/
|
||||
if (gtk_text_btree_mark_is_insert (_gtk_text_buffer_get_btree (layout->buffer),
|
||||
(GtkTextMark*)seg) &&
|
||||
(!layout->cursor_visible || gtk_text_buffer_get_selection_bounds (layout->buffer, &selection_start, &selection_end)))
|
||||
(!layout->cursor_visible ||
|
||||
gtk_text_buffer_get_selection_bounds (layout->buffer, NULL, NULL)))
|
||||
return;
|
||||
|
||||
pango_layout_get_cursor_pos (display->layout, start, &strong_pos, &weak_pos);
|
||||
@ -1429,7 +1428,8 @@ gtk_text_layout_get_line_display (GtkTextLayout *layout,
|
||||
tmp_list2 = cursor_segs;
|
||||
while (tmp_list1)
|
||||
{
|
||||
add_cursor (layout, display, tmp_list2->data, GPOINTER_TO_INT (tmp_list1->data));
|
||||
add_cursor (layout, display, tmp_list2->data,
|
||||
GPOINTER_TO_INT (tmp_list1->data));
|
||||
tmp_list1 = tmp_list1->next;
|
||||
tmp_list2 = tmp_list2->next;
|
||||
}
|
||||
|
@ -146,7 +146,7 @@ struct _GtkTextLineDisplay
|
||||
gint bottom_margin;
|
||||
|
||||
gboolean size_only;
|
||||
GtkTextLine *line;
|
||||
GtkTextLine *line;
|
||||
};
|
||||
|
||||
extern PangoAttrType gtk_text_attr_appearance_type;
|
||||
|
@ -530,7 +530,7 @@ gtk_text_view_class_init (GtkTextViewClass *klass)
|
||||
"delete", 2,
|
||||
GTK_TYPE_ENUM, GTK_DELETE_CHARS,
|
||||
GTK_TYPE_INT, 1);
|
||||
|
||||
|
||||
gtk_binding_entry_add_signal (binding_set, GDK_d, GDK_CONTROL_MASK,
|
||||
"delete", 2,
|
||||
GTK_TYPE_ENUM, GTK_DELETE_CHARS,
|
||||
@ -2590,6 +2590,16 @@ gtk_text_view_delete (GtkTextView *text_view,
|
||||
break;
|
||||
|
||||
case GTK_DELETE_PARAGRAPH_ENDS:
|
||||
/* If we're already at a newline, we need to
|
||||
* simply delete that newline, instead of
|
||||
* moving to the next one.
|
||||
*/
|
||||
if (gtk_text_iter_get_char (&end) == '\n')
|
||||
{
|
||||
gtk_text_iter_next_char (&end);
|
||||
--count;
|
||||
}
|
||||
|
||||
while (count > 0)
|
||||
{
|
||||
if (!gtk_text_iter_forward_to_newline (&end))
|
||||
@ -3058,9 +3068,9 @@ gtk_text_view_destroy_layout (GtkTextView *text_view)
|
||||
*/
|
||||
|
||||
static void
|
||||
gtk_text_view_start_selection_dnd (GtkTextView *text_view,
|
||||
gtk_text_view_start_selection_dnd (GtkTextView *text_view,
|
||||
const GtkTextIter *iter,
|
||||
GdkEventMotion *event)
|
||||
GdkEventMotion *event)
|
||||
{
|
||||
GdkDragContext *context;
|
||||
GtkTargetList *target_list;
|
||||
@ -3079,7 +3089,8 @@ gtk_text_view_start_selection_dnd (GtkTextView *text_view,
|
||||
gtk_drag_set_icon_default (context);
|
||||
|
||||
/* We're inside the selection, so start without being able
|
||||
to accept the drag. */
|
||||
* to accept the drag.
|
||||
*/
|
||||
gdk_drag_status (context, 0, event->time);
|
||||
gtk_text_mark_set_visible (text_view->dnd_mark, FALSE);
|
||||
}
|
||||
@ -3201,7 +3212,8 @@ gtk_text_view_drag_motion (GtkWidget *widget,
|
||||
{
|
||||
if (gtk_text_iter_editable (&newplace, text_view->editable))
|
||||
{
|
||||
gtk_text_mark_set_visible (text_view->dnd_mark, text_view->cursor_visible);
|
||||
gtk_text_mark_set_visible (text_view->dnd_mark,
|
||||
text_view->cursor_visible);
|
||||
|
||||
gdk_drag_status (context, context->suggested_action, time);
|
||||
}
|
||||
|
@ -16,14 +16,14 @@ main (int argc, char** argv)
|
||||
int n;
|
||||
gunichar ch;
|
||||
GtkTextIter start, end;
|
||||
|
||||
|
||||
gtk_init (&argc, &argv);
|
||||
|
||||
/* Check UTF8 unknown char thing */
|
||||
g_assert (g_utf8_strlen (gtk_text_unknown_char_utf8, 3) == 1);
|
||||
ch = g_utf8_get_char (gtk_text_unknown_char_utf8);
|
||||
g_assert (ch == gtk_text_unknown_char);
|
||||
|
||||
|
||||
/* First, we turn on btree debugging. */
|
||||
gtk_debug_flags |= GTK_DEBUG_TEXT;
|
||||
|
||||
@ -31,18 +31,18 @@ main (int argc, char** argv)
|
||||
buffer = gtk_text_buffer_new (NULL);
|
||||
|
||||
/* Check that buffer starts with one empty line and zero chars */
|
||||
|
||||
|
||||
n = gtk_text_buffer_get_line_count (buffer);
|
||||
if (n != 1)
|
||||
g_error ("%d lines, expected 1", n);
|
||||
|
||||
|
||||
n = gtk_text_buffer_get_char_count (buffer);
|
||||
if (n != 1)
|
||||
g_error ("%d chars, expected 1", n);
|
||||
|
||||
|
||||
/* Run gruesome alien test suite on buffer */
|
||||
run_tests (buffer);
|
||||
|
||||
|
||||
/* Put stuff in the buffer */
|
||||
|
||||
fill_buffer (buffer);
|
||||
@ -59,7 +59,7 @@ main (int argc, char** argv)
|
||||
n = gtk_text_buffer_get_line_count (buffer);
|
||||
if (n != 1)
|
||||
g_error ("%d lines, expected 1", n);
|
||||
|
||||
|
||||
n = gtk_text_buffer_get_char_count (buffer);
|
||||
if (n != 1)
|
||||
g_error ("%d chars, expected 1", n);
|
||||
@ -67,10 +67,165 @@ main (int argc, char** argv)
|
||||
run_tests (buffer);
|
||||
|
||||
g_print ("All tests passed.\n");
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static gint
|
||||
count_toggles_at_iter (GtkTextIter *iter,
|
||||
GtkTextTag *of_tag)
|
||||
{
|
||||
GSList *tags;
|
||||
GSList *tmp;
|
||||
gint count = 0;
|
||||
|
||||
/* get toggle-ons and toggle-offs */
|
||||
tags = gtk_text_iter_get_toggled_tags (iter, TRUE);
|
||||
tags = g_slist_concat (tags,
|
||||
gtk_text_iter_get_toggled_tags (iter, FALSE));
|
||||
|
||||
tmp = tags;
|
||||
while (tmp != NULL)
|
||||
{
|
||||
if (of_tag == NULL)
|
||||
++count;
|
||||
else if (of_tag == tmp->data)
|
||||
++count;
|
||||
|
||||
tmp = g_slist_next (tmp);
|
||||
}
|
||||
|
||||
g_slist_free (tags);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static gint
|
||||
count_toggles_in_buffer (GtkTextBuffer *buffer,
|
||||
GtkTextTag *of_tag)
|
||||
{
|
||||
GtkTextIter iter;
|
||||
gint count = 0;
|
||||
|
||||
gtk_text_buffer_get_iter_at_offset (buffer, &iter, 0);
|
||||
do
|
||||
{
|
||||
count += count_toggles_at_iter (&iter, of_tag);
|
||||
}
|
||||
while (gtk_text_iter_next_char (&iter));
|
||||
|
||||
/* Do the end iterator, because forward_char won't return TRUE
|
||||
* on it.
|
||||
*/
|
||||
count += count_toggles_at_iter (&iter, of_tag);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static void
|
||||
check_specific_tag (GtkTextBuffer *buffer,
|
||||
const gchar *tag_name)
|
||||
{
|
||||
GtkTextIter iter;
|
||||
GtkTextTag *tag;
|
||||
gboolean state;
|
||||
gint count;
|
||||
gint buffer_count;
|
||||
gint last_offset;
|
||||
|
||||
tag = gtk_text_tag_table_lookup (gtk_text_buffer_get_tag_table (buffer),
|
||||
tag_name);
|
||||
|
||||
buffer_count = count_toggles_in_buffer (buffer, tag);
|
||||
|
||||
state = FALSE;
|
||||
count = 0;
|
||||
|
||||
last_offset = -1;
|
||||
gtk_text_buffer_get_iter_at_offset (buffer, &iter, 0);
|
||||
if (gtk_text_iter_toggles_tag (&iter, tag) ||
|
||||
gtk_text_iter_forward_to_tag_toggle (&iter, tag))
|
||||
{
|
||||
do
|
||||
{
|
||||
gint this_offset;
|
||||
|
||||
++count;
|
||||
|
||||
this_offset = gtk_text_iter_get_offset (&iter);
|
||||
|
||||
if (this_offset <= last_offset)
|
||||
g_error ("forward_to_tag_toggle moved in wrong direction");
|
||||
|
||||
last_offset = this_offset;
|
||||
|
||||
if (gtk_text_iter_begins_tag (&iter, tag))
|
||||
{
|
||||
if (state)
|
||||
g_error ("Tag %p is already on, and was toggled on?", tag);
|
||||
state = TRUE;
|
||||
}
|
||||
else if (gtk_text_iter_ends_tag (&iter, tag))
|
||||
{
|
||||
if (!state)
|
||||
g_error ("Tag %p toggled off, but wasn't toggled on?", tag);
|
||||
state = FALSE;
|
||||
}
|
||||
else
|
||||
g_error ("forward_to_tag_toggle went to a location without a toggle");
|
||||
}
|
||||
while (gtk_text_iter_forward_to_tag_toggle (&iter, tag));
|
||||
}
|
||||
|
||||
if (count != buffer_count)
|
||||
g_error ("Counted %d tags iterating by char, %d iterating by tag toggle\n",
|
||||
buffer_count, count);
|
||||
|
||||
state = FALSE;
|
||||
count = 0;
|
||||
|
||||
gtk_text_buffer_get_last_iter (buffer, &iter);
|
||||
last_offset = gtk_text_iter_get_offset (&iter);
|
||||
if (gtk_text_iter_toggles_tag (&iter, tag) ||
|
||||
gtk_text_iter_backward_to_tag_toggle (&iter, tag))
|
||||
{
|
||||
do
|
||||
{
|
||||
gint this_offset;
|
||||
|
||||
++count;
|
||||
|
||||
this_offset = gtk_text_iter_get_offset (&iter);
|
||||
|
||||
if (this_offset >= last_offset)
|
||||
g_error ("backward_to_tag_toggle moved in wrong direction");
|
||||
|
||||
last_offset = this_offset;
|
||||
|
||||
if (gtk_text_iter_begins_tag (&iter, tag))
|
||||
{
|
||||
if (!state)
|
||||
g_error ("Tag %p wasn't on when we got to the on toggle going backward?", tag);
|
||||
state = FALSE;
|
||||
}
|
||||
else if (gtk_text_iter_ends_tag (&iter, tag))
|
||||
{
|
||||
if (state)
|
||||
g_error ("Tag %p off toggle, but we were already inside a tag?", tag);
|
||||
state = TRUE;
|
||||
}
|
||||
else
|
||||
g_error ("backward_to_tag_toggle went to a location without a toggle");
|
||||
}
|
||||
while (gtk_text_iter_backward_to_tag_toggle (&iter, tag));
|
||||
}
|
||||
|
||||
if (count != buffer_count)
|
||||
g_error ("Counted %d tags iterating by char, %d iterating by tag toggle\n",
|
||||
buffer_count, count);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
run_tests (GtkTextBuffer *buffer)
|
||||
{
|
||||
@ -81,9 +236,13 @@ run_tests (GtkTextBuffer *buffer)
|
||||
gint i, j;
|
||||
gint num_chars;
|
||||
GtkTextMark *bar_mark;
|
||||
GtkTextTag *tag;
|
||||
GHashTable *tag_states;
|
||||
gint count;
|
||||
gint buffer_count;
|
||||
|
||||
gtk_text_buffer_get_bounds (buffer, &start, &end);
|
||||
|
||||
|
||||
/* Check that walking the tree via chars and via iterators produces
|
||||
* the same number of indexable locations.
|
||||
*/
|
||||
@ -95,7 +254,7 @@ run_tests (GtkTextBuffer *buffer)
|
||||
{
|
||||
GtkTextIter current;
|
||||
GtkTextMark *foo_mark;
|
||||
|
||||
|
||||
gtk_text_buffer_get_iter_at_offset (buffer, ¤t, i);
|
||||
|
||||
if (!gtk_text_iter_equal (&iter, ¤t))
|
||||
@ -119,11 +278,11 @@ run_tests (GtkTextBuffer *buffer)
|
||||
gtk_text_iter_spew (&mark, "mark");
|
||||
g_error ("Mark not moved to the right place.");
|
||||
}
|
||||
|
||||
|
||||
foo_mark = gtk_text_buffer_create_mark (buffer, "foo", &iter, FALSE);
|
||||
gtk_text_buffer_get_iter_at_mark (buffer, &mark, foo_mark);
|
||||
gtk_text_buffer_delete_mark (buffer, foo_mark);
|
||||
|
||||
|
||||
if (!gtk_text_iter_equal (&iter, &mark))
|
||||
{
|
||||
gtk_text_iter_spew (&iter, "iter");
|
||||
@ -134,34 +293,34 @@ run_tests (GtkTextBuffer *buffer)
|
||||
if (gtk_text_iter_is_last (&iter))
|
||||
g_error ("iterators ran out before chars (offset %d of %d)",
|
||||
i, num_chars);
|
||||
|
||||
|
||||
gtk_text_iter_next_char (&iter);
|
||||
|
||||
gtk_text_buffer_move_mark (buffer, bar_mark, &iter);
|
||||
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
if (!gtk_text_iter_equal (&iter, &end))
|
||||
g_error ("Iterating over all chars didn't end with the end iter");
|
||||
|
||||
/* Do the tree-walk backward
|
||||
/* Do the tree-walk backward
|
||||
*/
|
||||
num_chars = gtk_text_buffer_get_char_count (buffer);
|
||||
gtk_text_buffer_get_iter_at_offset (buffer, &iter, -1);
|
||||
|
||||
gtk_text_buffer_move_mark (buffer, bar_mark, &iter);
|
||||
|
||||
|
||||
i = num_chars;
|
||||
|
||||
if (!gtk_text_iter_equal (&iter, &end))
|
||||
g_error ("iter at char -1 is not equal to the end iterator");
|
||||
|
||||
|
||||
while (i >= 0)
|
||||
{
|
||||
GtkTextIter current;
|
||||
GtkTextMark *foo_mark;
|
||||
|
||||
|
||||
gtk_text_buffer_get_iter_at_offset (buffer, ¤t, i);
|
||||
|
||||
if (!gtk_text_iter_equal (&iter, ¤t))
|
||||
@ -184,18 +343,18 @@ run_tests (GtkTextBuffer *buffer)
|
||||
gtk_text_iter_spew (&mark, "mark");
|
||||
g_error ("Mark not moved to the right place.");
|
||||
}
|
||||
|
||||
|
||||
foo_mark = gtk_text_buffer_create_mark (buffer, "foo", &iter, FALSE);
|
||||
gtk_text_buffer_get_iter_at_mark (buffer, &mark, foo_mark);
|
||||
gtk_text_buffer_delete_mark (buffer, foo_mark);
|
||||
|
||||
|
||||
if (!gtk_text_iter_equal (&iter, &mark))
|
||||
{
|
||||
gtk_text_iter_spew (&iter, "iter");
|
||||
gtk_text_iter_spew (&mark, "mark");
|
||||
g_error ("Mark not created in the right place.");
|
||||
}
|
||||
|
||||
|
||||
if (i > 0)
|
||||
{
|
||||
if (!gtk_text_iter_prev_char (&iter))
|
||||
@ -208,10 +367,10 @@ run_tests (GtkTextBuffer *buffer)
|
||||
if (gtk_text_iter_prev_char (&iter))
|
||||
g_error ("went backward from 0?");
|
||||
}
|
||||
|
||||
|
||||
--i;
|
||||
}
|
||||
|
||||
|
||||
if (!gtk_text_iter_equal (&iter, &start))
|
||||
g_error ("Iterating backward over all chars didn't end with the start iter");
|
||||
|
||||
@ -223,10 +382,169 @@ run_tests (GtkTextBuffer *buffer)
|
||||
gtk_text_buffer_get_iter_at_line (buffer, &iter, 0);
|
||||
while (gtk_text_iter_forward_line (&iter))
|
||||
++i;
|
||||
|
||||
|
||||
if (i != gtk_text_buffer_get_line_count (buffer))
|
||||
g_error ("Counted %d lines, buffer has %d", i,
|
||||
gtk_text_buffer_get_line_count (buffer));
|
||||
|
||||
/*
|
||||
* Check that moving over tag toggles thinks about working.
|
||||
*/
|
||||
|
||||
buffer_count = count_toggles_in_buffer (buffer, NULL);
|
||||
|
||||
tag_states = g_hash_table_new (NULL, NULL);
|
||||
count = 0;
|
||||
|
||||
gtk_text_buffer_get_iter_at_offset (buffer, &iter, 0);
|
||||
if (gtk_text_iter_toggles_tag (&iter, NULL) ||
|
||||
gtk_text_iter_forward_to_tag_toggle (&iter, NULL))
|
||||
{
|
||||
do
|
||||
{
|
||||
GSList *tags;
|
||||
GSList *tmp;
|
||||
gboolean found_some = FALSE;
|
||||
|
||||
/* get toggled-on tags */
|
||||
tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
|
||||
|
||||
if (tags)
|
||||
found_some = TRUE;
|
||||
|
||||
tmp = tags;
|
||||
while (tmp != NULL)
|
||||
{
|
||||
++count;
|
||||
|
||||
tag = tmp->data;
|
||||
|
||||
if (g_hash_table_lookup (tag_states, tag))
|
||||
g_error ("Tag %p is already on, and was toggled on?", tag);
|
||||
|
||||
g_hash_table_insert (tag_states, tag, GINT_TO_POINTER (TRUE));
|
||||
|
||||
tmp = g_slist_next (tmp);
|
||||
}
|
||||
|
||||
g_slist_free (tags);
|
||||
|
||||
/* get toggled-off tags */
|
||||
tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
|
||||
|
||||
if (tags)
|
||||
found_some = TRUE;
|
||||
|
||||
tmp = tags;
|
||||
while (tmp != NULL)
|
||||
{
|
||||
++count;
|
||||
|
||||
tag = tmp->data;
|
||||
|
||||
if (!g_hash_table_lookup (tag_states, tag))
|
||||
g_error ("Tag %p is already off, and was toggled off?", tag);
|
||||
|
||||
g_hash_table_remove (tag_states, tag);
|
||||
|
||||
tmp = g_slist_next (tmp);
|
||||
}
|
||||
|
||||
g_slist_free (tags);
|
||||
|
||||
if (!found_some)
|
||||
g_error ("No tags found going forward to tag toggle.");
|
||||
|
||||
}
|
||||
while (gtk_text_iter_forward_to_tag_toggle (&iter, NULL));
|
||||
}
|
||||
|
||||
g_hash_table_destroy (tag_states);
|
||||
|
||||
if (count != buffer_count)
|
||||
g_error ("Counted %d tags iterating by char, %d iterating by tag toggle\n",
|
||||
buffer_count, count);
|
||||
|
||||
/* Go backward; here TRUE in the hash means we saw
|
||||
* an off toggle last.
|
||||
*/
|
||||
|
||||
tag_states = g_hash_table_new (NULL, NULL);
|
||||
count = 0;
|
||||
|
||||
gtk_text_buffer_get_last_iter (buffer, &iter);
|
||||
if (gtk_text_iter_toggles_tag (&iter, NULL) ||
|
||||
gtk_text_iter_backward_to_tag_toggle (&iter, NULL))
|
||||
{
|
||||
do
|
||||
{
|
||||
GSList *tags;
|
||||
GSList *tmp;
|
||||
gboolean found_some = FALSE;
|
||||
|
||||
/* get toggled-off tags */
|
||||
tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
|
||||
|
||||
if (tags)
|
||||
found_some = TRUE;
|
||||
|
||||
tmp = tags;
|
||||
while (tmp != NULL)
|
||||
{
|
||||
++count;
|
||||
|
||||
tag = tmp->data;
|
||||
|
||||
if (g_hash_table_lookup (tag_states, tag))
|
||||
g_error ("Tag %p has two off-toggles in a row?", tag);
|
||||
|
||||
g_hash_table_insert (tag_states, tag, GINT_TO_POINTER (TRUE));
|
||||
|
||||
tmp = g_slist_next (tmp);
|
||||
}
|
||||
|
||||
g_slist_free (tags);
|
||||
|
||||
/* get toggled-on tags */
|
||||
tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
|
||||
|
||||
if (tags)
|
||||
found_some = TRUE;
|
||||
|
||||
tmp = tags;
|
||||
while (tmp != NULL)
|
||||
{
|
||||
++count;
|
||||
|
||||
tag = tmp->data;
|
||||
|
||||
if (!g_hash_table_lookup (tag_states, tag))
|
||||
g_error ("Tag %p was toggled on, but saw no off-toggle?", tag);
|
||||
|
||||
g_hash_table_remove (tag_states, tag);
|
||||
|
||||
tmp = g_slist_next (tmp);
|
||||
}
|
||||
|
||||
g_slist_free (tags);
|
||||
|
||||
if (!found_some)
|
||||
g_error ("No tags found going backward to tag toggle.");
|
||||
}
|
||||
while (gtk_text_iter_backward_to_tag_toggle (&iter, NULL));
|
||||
}
|
||||
|
||||
g_hash_table_destroy (tag_states);
|
||||
|
||||
if (count != buffer_count)
|
||||
g_error ("Counted %d tags iterating by char, %d iterating by tag toggle\n",
|
||||
buffer_count, count);
|
||||
|
||||
check_specific_tag (buffer, "fg_red");
|
||||
check_specific_tag (buffer, "bg_green");
|
||||
check_specific_tag (buffer, "front_tag");
|
||||
check_specific_tag (buffer, "center_tag");
|
||||
check_specific_tag (buffer, "end_tag");
|
||||
}
|
||||
|
||||
|
||||
@ -264,7 +582,7 @@ fill_buffer (GtkTextBuffer *buffer)
|
||||
GtkTextIter iter2;
|
||||
GdkPixbuf *pixbuf;
|
||||
int i;
|
||||
|
||||
|
||||
tag = gtk_text_buffer_create_tag (buffer, "fg_blue");
|
||||
|
||||
color.red = color.green = 0;
|
||||
@ -297,49 +615,49 @@ fill_buffer (GtkTextBuffer *buffer)
|
||||
NULL);
|
||||
|
||||
pixbuf = gdk_pixbuf_new_from_xpm_data (book_closed_xpm);
|
||||
|
||||
|
||||
g_assert (pixbuf != NULL);
|
||||
|
||||
|
||||
i = 0;
|
||||
while (i < 10)
|
||||
{
|
||||
gchar *str;
|
||||
|
||||
gtk_text_buffer_get_iter_at_offset (buffer, &iter, 0);
|
||||
|
||||
|
||||
gtk_text_buffer_insert_pixbuf (buffer, &iter, pixbuf);
|
||||
|
||||
gtk_text_buffer_get_iter_at_offset (buffer, &iter, 1);
|
||||
|
||||
|
||||
gtk_text_buffer_insert_pixbuf (buffer, &iter, pixbuf);
|
||||
|
||||
|
||||
str = g_strdup_printf ("%d Hello World!\nwoo woo woo woo woo woo woo woo\n",
|
||||
i);
|
||||
|
||||
|
||||
gtk_text_buffer_insert (buffer, &iter, str, -1);
|
||||
|
||||
g_free (str);
|
||||
|
||||
|
||||
gtk_text_buffer_insert (buffer, &iter,
|
||||
"(Hello World!)\nfoo foo Hello this is some text we are using to text word wrap. It has punctuation! gee; blah - hmm, great.\nnew line\n\n"
|
||||
/* This is UTF8 stuff, Emacs doesn't
|
||||
really know how to display it */
|
||||
"Spanish (Español) ¡Hola! / French (Français) Bonjour, Salut / German (Deutsch Süd) Grüß Gott (testing Latin-1 chars encoded in UTF8)\nThai (we can't display this, just making sure we don't crash) (ภาษาไทย) สวัสดีครับ, สวัสดีค่ะ\n",
|
||||
-1);
|
||||
|
||||
-1);
|
||||
|
||||
gtk_text_buffer_insert_pixbuf (buffer, &iter, pixbuf);
|
||||
gtk_text_buffer_insert_pixbuf (buffer, &iter, pixbuf);
|
||||
|
||||
|
||||
gtk_text_buffer_get_iter_at_offset (buffer, &iter, 4);
|
||||
|
||||
|
||||
gtk_text_buffer_insert_pixbuf (buffer, &iter, pixbuf);
|
||||
|
||||
gtk_text_buffer_get_iter_at_offset (buffer, &iter, 7);
|
||||
|
||||
|
||||
gtk_text_buffer_insert_pixbuf (buffer, &iter, pixbuf);
|
||||
|
||||
gtk_text_buffer_get_iter_at_offset (buffer, &iter, 8);
|
||||
|
||||
|
||||
gtk_text_buffer_insert_pixbuf (buffer, &iter, pixbuf);
|
||||
|
||||
gtk_text_buffer_get_iter_at_line_offset (buffer, &iter, 0, 8);
|
||||
@ -350,40 +668,66 @@ fill_buffer (GtkTextBuffer *buffer)
|
||||
|
||||
gtk_text_iter_forward_chars (&iter, 7);
|
||||
gtk_text_iter_forward_chars (&iter2, 10);
|
||||
|
||||
|
||||
gtk_text_buffer_apply_tag_by_name (buffer, "bg_green", &iter, &iter2);
|
||||
|
||||
gtk_text_iter_forward_chars (&iter, 12);
|
||||
gtk_text_iter_forward_chars (&iter2, 10);
|
||||
|
||||
|
||||
gtk_text_buffer_apply_tag_by_name (buffer, "bg_green", &iter, &iter2);
|
||||
|
||||
gtk_text_iter_forward_chars (&iter, 10);
|
||||
gtk_text_iter_forward_chars (&iter2, 15);
|
||||
|
||||
|
||||
gtk_text_buffer_apply_tag_by_name (buffer, "fg_red", &iter, &iter2);
|
||||
gtk_text_buffer_apply_tag_by_name (buffer, "fg_blue", &iter, &iter2);
|
||||
gtk_text_buffer_apply_tag_by_name (buffer, "fg_blue", &iter, &iter2);
|
||||
|
||||
gtk_text_iter_forward_chars (&iter, 20);
|
||||
gtk_text_iter_forward_chars (&iter2, 20);
|
||||
|
||||
|
||||
gtk_text_buffer_apply_tag_by_name (buffer, "fg_red", &iter, &iter2);
|
||||
gtk_text_buffer_apply_tag_by_name (buffer, "fg_blue", &iter, &iter2);
|
||||
gtk_text_buffer_apply_tag_by_name (buffer, "fg_blue", &iter, &iter2);
|
||||
|
||||
gtk_text_iter_backward_chars (&iter, 25);
|
||||
gtk_text_iter_forward_chars (&iter2, 5);
|
||||
|
||||
|
||||
gtk_text_buffer_apply_tag_by_name (buffer, "fg_red", &iter, &iter2);
|
||||
gtk_text_buffer_apply_tag_by_name (buffer, "fg_blue", &iter, &iter2);
|
||||
gtk_text_buffer_apply_tag_by_name (buffer, "fg_blue", &iter, &iter2);
|
||||
|
||||
gtk_text_iter_forward_chars (&iter, 15);
|
||||
gtk_text_iter_backward_chars (&iter2, 10);
|
||||
|
||||
gtk_text_buffer_remove_tag_by_name (buffer, "fg_red", &iter, &iter2);
|
||||
gtk_text_buffer_remove_tag_by_name (buffer, "fg_blue", &iter, &iter2);
|
||||
|
||||
gtk_text_buffer_remove_tag_by_name (buffer, "fg_blue", &iter, &iter2);
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
/* Put in tags that are just at the beginning, and just near the end,
|
||||
* and just near the middle.
|
||||
*/
|
||||
tag = gtk_text_buffer_create_tag (buffer, "front_tag");
|
||||
gtk_text_buffer_get_iter_at_offset (buffer, &iter, 3);
|
||||
gtk_text_buffer_get_iter_at_offset (buffer, &iter2, 300);
|
||||
|
||||
gtk_text_buffer_apply_tag (buffer, tag, &iter, &iter2);
|
||||
|
||||
tag = gtk_text_buffer_create_tag (buffer, "end_tag");
|
||||
gtk_text_buffer_get_last_iter (buffer, &iter2);
|
||||
gtk_text_iter_backward_chars (&iter2, 12);
|
||||
iter = iter2;
|
||||
gtk_text_iter_backward_chars (&iter, 157);
|
||||
|
||||
gtk_text_buffer_apply_tag (buffer, tag, &iter, &iter2);
|
||||
|
||||
tag = gtk_text_buffer_create_tag (buffer, "center_tag");
|
||||
gtk_text_buffer_get_iter_at_offset (buffer, &iter,
|
||||
gtk_text_buffer_get_char_count (buffer)/2);
|
||||
gtk_text_iter_backward_chars (&iter, 37);
|
||||
iter2 = iter;
|
||||
gtk_text_iter_forward_chars (&iter2, 57);
|
||||
|
||||
gtk_text_buffer_apply_tag (buffer, tag, &iter, &iter2);
|
||||
|
||||
gdk_pixbuf_unref (pixbuf);
|
||||
}
|
||||
|
@ -16,14 +16,14 @@ main (int argc, char** argv)
|
||||
int n;
|
||||
gunichar ch;
|
||||
GtkTextIter start, end;
|
||||
|
||||
|
||||
gtk_init (&argc, &argv);
|
||||
|
||||
/* Check UTF8 unknown char thing */
|
||||
g_assert (g_utf8_strlen (gtk_text_unknown_char_utf8, 3) == 1);
|
||||
ch = g_utf8_get_char (gtk_text_unknown_char_utf8);
|
||||
g_assert (ch == gtk_text_unknown_char);
|
||||
|
||||
|
||||
/* First, we turn on btree debugging. */
|
||||
gtk_debug_flags |= GTK_DEBUG_TEXT;
|
||||
|
||||
@ -31,18 +31,18 @@ main (int argc, char** argv)
|
||||
buffer = gtk_text_buffer_new (NULL);
|
||||
|
||||
/* Check that buffer starts with one empty line and zero chars */
|
||||
|
||||
|
||||
n = gtk_text_buffer_get_line_count (buffer);
|
||||
if (n != 1)
|
||||
g_error ("%d lines, expected 1", n);
|
||||
|
||||
|
||||
n = gtk_text_buffer_get_char_count (buffer);
|
||||
if (n != 1)
|
||||
g_error ("%d chars, expected 1", n);
|
||||
|
||||
|
||||
/* Run gruesome alien test suite on buffer */
|
||||
run_tests (buffer);
|
||||
|
||||
|
||||
/* Put stuff in the buffer */
|
||||
|
||||
fill_buffer (buffer);
|
||||
@ -59,7 +59,7 @@ main (int argc, char** argv)
|
||||
n = gtk_text_buffer_get_line_count (buffer);
|
||||
if (n != 1)
|
||||
g_error ("%d lines, expected 1", n);
|
||||
|
||||
|
||||
n = gtk_text_buffer_get_char_count (buffer);
|
||||
if (n != 1)
|
||||
g_error ("%d chars, expected 1", n);
|
||||
@ -67,10 +67,165 @@ main (int argc, char** argv)
|
||||
run_tests (buffer);
|
||||
|
||||
g_print ("All tests passed.\n");
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static gint
|
||||
count_toggles_at_iter (GtkTextIter *iter,
|
||||
GtkTextTag *of_tag)
|
||||
{
|
||||
GSList *tags;
|
||||
GSList *tmp;
|
||||
gint count = 0;
|
||||
|
||||
/* get toggle-ons and toggle-offs */
|
||||
tags = gtk_text_iter_get_toggled_tags (iter, TRUE);
|
||||
tags = g_slist_concat (tags,
|
||||
gtk_text_iter_get_toggled_tags (iter, FALSE));
|
||||
|
||||
tmp = tags;
|
||||
while (tmp != NULL)
|
||||
{
|
||||
if (of_tag == NULL)
|
||||
++count;
|
||||
else if (of_tag == tmp->data)
|
||||
++count;
|
||||
|
||||
tmp = g_slist_next (tmp);
|
||||
}
|
||||
|
||||
g_slist_free (tags);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static gint
|
||||
count_toggles_in_buffer (GtkTextBuffer *buffer,
|
||||
GtkTextTag *of_tag)
|
||||
{
|
||||
GtkTextIter iter;
|
||||
gint count = 0;
|
||||
|
||||
gtk_text_buffer_get_iter_at_offset (buffer, &iter, 0);
|
||||
do
|
||||
{
|
||||
count += count_toggles_at_iter (&iter, of_tag);
|
||||
}
|
||||
while (gtk_text_iter_next_char (&iter));
|
||||
|
||||
/* Do the end iterator, because forward_char won't return TRUE
|
||||
* on it.
|
||||
*/
|
||||
count += count_toggles_at_iter (&iter, of_tag);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static void
|
||||
check_specific_tag (GtkTextBuffer *buffer,
|
||||
const gchar *tag_name)
|
||||
{
|
||||
GtkTextIter iter;
|
||||
GtkTextTag *tag;
|
||||
gboolean state;
|
||||
gint count;
|
||||
gint buffer_count;
|
||||
gint last_offset;
|
||||
|
||||
tag = gtk_text_tag_table_lookup (gtk_text_buffer_get_tag_table (buffer),
|
||||
tag_name);
|
||||
|
||||
buffer_count = count_toggles_in_buffer (buffer, tag);
|
||||
|
||||
state = FALSE;
|
||||
count = 0;
|
||||
|
||||
last_offset = -1;
|
||||
gtk_text_buffer_get_iter_at_offset (buffer, &iter, 0);
|
||||
if (gtk_text_iter_toggles_tag (&iter, tag) ||
|
||||
gtk_text_iter_forward_to_tag_toggle (&iter, tag))
|
||||
{
|
||||
do
|
||||
{
|
||||
gint this_offset;
|
||||
|
||||
++count;
|
||||
|
||||
this_offset = gtk_text_iter_get_offset (&iter);
|
||||
|
||||
if (this_offset <= last_offset)
|
||||
g_error ("forward_to_tag_toggle moved in wrong direction");
|
||||
|
||||
last_offset = this_offset;
|
||||
|
||||
if (gtk_text_iter_begins_tag (&iter, tag))
|
||||
{
|
||||
if (state)
|
||||
g_error ("Tag %p is already on, and was toggled on?", tag);
|
||||
state = TRUE;
|
||||
}
|
||||
else if (gtk_text_iter_ends_tag (&iter, tag))
|
||||
{
|
||||
if (!state)
|
||||
g_error ("Tag %p toggled off, but wasn't toggled on?", tag);
|
||||
state = FALSE;
|
||||
}
|
||||
else
|
||||
g_error ("forward_to_tag_toggle went to a location without a toggle");
|
||||
}
|
||||
while (gtk_text_iter_forward_to_tag_toggle (&iter, tag));
|
||||
}
|
||||
|
||||
if (count != buffer_count)
|
||||
g_error ("Counted %d tags iterating by char, %d iterating by tag toggle\n",
|
||||
buffer_count, count);
|
||||
|
||||
state = FALSE;
|
||||
count = 0;
|
||||
|
||||
gtk_text_buffer_get_last_iter (buffer, &iter);
|
||||
last_offset = gtk_text_iter_get_offset (&iter);
|
||||
if (gtk_text_iter_toggles_tag (&iter, tag) ||
|
||||
gtk_text_iter_backward_to_tag_toggle (&iter, tag))
|
||||
{
|
||||
do
|
||||
{
|
||||
gint this_offset;
|
||||
|
||||
++count;
|
||||
|
||||
this_offset = gtk_text_iter_get_offset (&iter);
|
||||
|
||||
if (this_offset >= last_offset)
|
||||
g_error ("backward_to_tag_toggle moved in wrong direction");
|
||||
|
||||
last_offset = this_offset;
|
||||
|
||||
if (gtk_text_iter_begins_tag (&iter, tag))
|
||||
{
|
||||
if (!state)
|
||||
g_error ("Tag %p wasn't on when we got to the on toggle going backward?", tag);
|
||||
state = FALSE;
|
||||
}
|
||||
else if (gtk_text_iter_ends_tag (&iter, tag))
|
||||
{
|
||||
if (state)
|
||||
g_error ("Tag %p off toggle, but we were already inside a tag?", tag);
|
||||
state = TRUE;
|
||||
}
|
||||
else
|
||||
g_error ("backward_to_tag_toggle went to a location without a toggle");
|
||||
}
|
||||
while (gtk_text_iter_backward_to_tag_toggle (&iter, tag));
|
||||
}
|
||||
|
||||
if (count != buffer_count)
|
||||
g_error ("Counted %d tags iterating by char, %d iterating by tag toggle\n",
|
||||
buffer_count, count);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
run_tests (GtkTextBuffer *buffer)
|
||||
{
|
||||
@ -81,9 +236,13 @@ run_tests (GtkTextBuffer *buffer)
|
||||
gint i, j;
|
||||
gint num_chars;
|
||||
GtkTextMark *bar_mark;
|
||||
GtkTextTag *tag;
|
||||
GHashTable *tag_states;
|
||||
gint count;
|
||||
gint buffer_count;
|
||||
|
||||
gtk_text_buffer_get_bounds (buffer, &start, &end);
|
||||
|
||||
|
||||
/* Check that walking the tree via chars and via iterators produces
|
||||
* the same number of indexable locations.
|
||||
*/
|
||||
@ -95,7 +254,7 @@ run_tests (GtkTextBuffer *buffer)
|
||||
{
|
||||
GtkTextIter current;
|
||||
GtkTextMark *foo_mark;
|
||||
|
||||
|
||||
gtk_text_buffer_get_iter_at_offset (buffer, ¤t, i);
|
||||
|
||||
if (!gtk_text_iter_equal (&iter, ¤t))
|
||||
@ -119,11 +278,11 @@ run_tests (GtkTextBuffer *buffer)
|
||||
gtk_text_iter_spew (&mark, "mark");
|
||||
g_error ("Mark not moved to the right place.");
|
||||
}
|
||||
|
||||
|
||||
foo_mark = gtk_text_buffer_create_mark (buffer, "foo", &iter, FALSE);
|
||||
gtk_text_buffer_get_iter_at_mark (buffer, &mark, foo_mark);
|
||||
gtk_text_buffer_delete_mark (buffer, foo_mark);
|
||||
|
||||
|
||||
if (!gtk_text_iter_equal (&iter, &mark))
|
||||
{
|
||||
gtk_text_iter_spew (&iter, "iter");
|
||||
@ -134,34 +293,34 @@ run_tests (GtkTextBuffer *buffer)
|
||||
if (gtk_text_iter_is_last (&iter))
|
||||
g_error ("iterators ran out before chars (offset %d of %d)",
|
||||
i, num_chars);
|
||||
|
||||
|
||||
gtk_text_iter_next_char (&iter);
|
||||
|
||||
gtk_text_buffer_move_mark (buffer, bar_mark, &iter);
|
||||
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
if (!gtk_text_iter_equal (&iter, &end))
|
||||
g_error ("Iterating over all chars didn't end with the end iter");
|
||||
|
||||
/* Do the tree-walk backward
|
||||
/* Do the tree-walk backward
|
||||
*/
|
||||
num_chars = gtk_text_buffer_get_char_count (buffer);
|
||||
gtk_text_buffer_get_iter_at_offset (buffer, &iter, -1);
|
||||
|
||||
gtk_text_buffer_move_mark (buffer, bar_mark, &iter);
|
||||
|
||||
|
||||
i = num_chars;
|
||||
|
||||
if (!gtk_text_iter_equal (&iter, &end))
|
||||
g_error ("iter at char -1 is not equal to the end iterator");
|
||||
|
||||
|
||||
while (i >= 0)
|
||||
{
|
||||
GtkTextIter current;
|
||||
GtkTextMark *foo_mark;
|
||||
|
||||
|
||||
gtk_text_buffer_get_iter_at_offset (buffer, ¤t, i);
|
||||
|
||||
if (!gtk_text_iter_equal (&iter, ¤t))
|
||||
@ -184,18 +343,18 @@ run_tests (GtkTextBuffer *buffer)
|
||||
gtk_text_iter_spew (&mark, "mark");
|
||||
g_error ("Mark not moved to the right place.");
|
||||
}
|
||||
|
||||
|
||||
foo_mark = gtk_text_buffer_create_mark (buffer, "foo", &iter, FALSE);
|
||||
gtk_text_buffer_get_iter_at_mark (buffer, &mark, foo_mark);
|
||||
gtk_text_buffer_delete_mark (buffer, foo_mark);
|
||||
|
||||
|
||||
if (!gtk_text_iter_equal (&iter, &mark))
|
||||
{
|
||||
gtk_text_iter_spew (&iter, "iter");
|
||||
gtk_text_iter_spew (&mark, "mark");
|
||||
g_error ("Mark not created in the right place.");
|
||||
}
|
||||
|
||||
|
||||
if (i > 0)
|
||||
{
|
||||
if (!gtk_text_iter_prev_char (&iter))
|
||||
@ -208,10 +367,10 @@ run_tests (GtkTextBuffer *buffer)
|
||||
if (gtk_text_iter_prev_char (&iter))
|
||||
g_error ("went backward from 0?");
|
||||
}
|
||||
|
||||
|
||||
--i;
|
||||
}
|
||||
|
||||
|
||||
if (!gtk_text_iter_equal (&iter, &start))
|
||||
g_error ("Iterating backward over all chars didn't end with the start iter");
|
||||
|
||||
@ -223,10 +382,169 @@ run_tests (GtkTextBuffer *buffer)
|
||||
gtk_text_buffer_get_iter_at_line (buffer, &iter, 0);
|
||||
while (gtk_text_iter_forward_line (&iter))
|
||||
++i;
|
||||
|
||||
|
||||
if (i != gtk_text_buffer_get_line_count (buffer))
|
||||
g_error ("Counted %d lines, buffer has %d", i,
|
||||
gtk_text_buffer_get_line_count (buffer));
|
||||
|
||||
/*
|
||||
* Check that moving over tag toggles thinks about working.
|
||||
*/
|
||||
|
||||
buffer_count = count_toggles_in_buffer (buffer, NULL);
|
||||
|
||||
tag_states = g_hash_table_new (NULL, NULL);
|
||||
count = 0;
|
||||
|
||||
gtk_text_buffer_get_iter_at_offset (buffer, &iter, 0);
|
||||
if (gtk_text_iter_toggles_tag (&iter, NULL) ||
|
||||
gtk_text_iter_forward_to_tag_toggle (&iter, NULL))
|
||||
{
|
||||
do
|
||||
{
|
||||
GSList *tags;
|
||||
GSList *tmp;
|
||||
gboolean found_some = FALSE;
|
||||
|
||||
/* get toggled-on tags */
|
||||
tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
|
||||
|
||||
if (tags)
|
||||
found_some = TRUE;
|
||||
|
||||
tmp = tags;
|
||||
while (tmp != NULL)
|
||||
{
|
||||
++count;
|
||||
|
||||
tag = tmp->data;
|
||||
|
||||
if (g_hash_table_lookup (tag_states, tag))
|
||||
g_error ("Tag %p is already on, and was toggled on?", tag);
|
||||
|
||||
g_hash_table_insert (tag_states, tag, GINT_TO_POINTER (TRUE));
|
||||
|
||||
tmp = g_slist_next (tmp);
|
||||
}
|
||||
|
||||
g_slist_free (tags);
|
||||
|
||||
/* get toggled-off tags */
|
||||
tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
|
||||
|
||||
if (tags)
|
||||
found_some = TRUE;
|
||||
|
||||
tmp = tags;
|
||||
while (tmp != NULL)
|
||||
{
|
||||
++count;
|
||||
|
||||
tag = tmp->data;
|
||||
|
||||
if (!g_hash_table_lookup (tag_states, tag))
|
||||
g_error ("Tag %p is already off, and was toggled off?", tag);
|
||||
|
||||
g_hash_table_remove (tag_states, tag);
|
||||
|
||||
tmp = g_slist_next (tmp);
|
||||
}
|
||||
|
||||
g_slist_free (tags);
|
||||
|
||||
if (!found_some)
|
||||
g_error ("No tags found going forward to tag toggle.");
|
||||
|
||||
}
|
||||
while (gtk_text_iter_forward_to_tag_toggle (&iter, NULL));
|
||||
}
|
||||
|
||||
g_hash_table_destroy (tag_states);
|
||||
|
||||
if (count != buffer_count)
|
||||
g_error ("Counted %d tags iterating by char, %d iterating by tag toggle\n",
|
||||
buffer_count, count);
|
||||
|
||||
/* Go backward; here TRUE in the hash means we saw
|
||||
* an off toggle last.
|
||||
*/
|
||||
|
||||
tag_states = g_hash_table_new (NULL, NULL);
|
||||
count = 0;
|
||||
|
||||
gtk_text_buffer_get_last_iter (buffer, &iter);
|
||||
if (gtk_text_iter_toggles_tag (&iter, NULL) ||
|
||||
gtk_text_iter_backward_to_tag_toggle (&iter, NULL))
|
||||
{
|
||||
do
|
||||
{
|
||||
GSList *tags;
|
||||
GSList *tmp;
|
||||
gboolean found_some = FALSE;
|
||||
|
||||
/* get toggled-off tags */
|
||||
tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
|
||||
|
||||
if (tags)
|
||||
found_some = TRUE;
|
||||
|
||||
tmp = tags;
|
||||
while (tmp != NULL)
|
||||
{
|
||||
++count;
|
||||
|
||||
tag = tmp->data;
|
||||
|
||||
if (g_hash_table_lookup (tag_states, tag))
|
||||
g_error ("Tag %p has two off-toggles in a row?", tag);
|
||||
|
||||
g_hash_table_insert (tag_states, tag, GINT_TO_POINTER (TRUE));
|
||||
|
||||
tmp = g_slist_next (tmp);
|
||||
}
|
||||
|
||||
g_slist_free (tags);
|
||||
|
||||
/* get toggled-on tags */
|
||||
tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
|
||||
|
||||
if (tags)
|
||||
found_some = TRUE;
|
||||
|
||||
tmp = tags;
|
||||
while (tmp != NULL)
|
||||
{
|
||||
++count;
|
||||
|
||||
tag = tmp->data;
|
||||
|
||||
if (!g_hash_table_lookup (tag_states, tag))
|
||||
g_error ("Tag %p was toggled on, but saw no off-toggle?", tag);
|
||||
|
||||
g_hash_table_remove (tag_states, tag);
|
||||
|
||||
tmp = g_slist_next (tmp);
|
||||
}
|
||||
|
||||
g_slist_free (tags);
|
||||
|
||||
if (!found_some)
|
||||
g_error ("No tags found going backward to tag toggle.");
|
||||
}
|
||||
while (gtk_text_iter_backward_to_tag_toggle (&iter, NULL));
|
||||
}
|
||||
|
||||
g_hash_table_destroy (tag_states);
|
||||
|
||||
if (count != buffer_count)
|
||||
g_error ("Counted %d tags iterating by char, %d iterating by tag toggle\n",
|
||||
buffer_count, count);
|
||||
|
||||
check_specific_tag (buffer, "fg_red");
|
||||
check_specific_tag (buffer, "bg_green");
|
||||
check_specific_tag (buffer, "front_tag");
|
||||
check_specific_tag (buffer, "center_tag");
|
||||
check_specific_tag (buffer, "end_tag");
|
||||
}
|
||||
|
||||
|
||||
@ -264,7 +582,7 @@ fill_buffer (GtkTextBuffer *buffer)
|
||||
GtkTextIter iter2;
|
||||
GdkPixbuf *pixbuf;
|
||||
int i;
|
||||
|
||||
|
||||
tag = gtk_text_buffer_create_tag (buffer, "fg_blue");
|
||||
|
||||
color.red = color.green = 0;
|
||||
@ -297,49 +615,49 @@ fill_buffer (GtkTextBuffer *buffer)
|
||||
NULL);
|
||||
|
||||
pixbuf = gdk_pixbuf_new_from_xpm_data (book_closed_xpm);
|
||||
|
||||
|
||||
g_assert (pixbuf != NULL);
|
||||
|
||||
|
||||
i = 0;
|
||||
while (i < 10)
|
||||
{
|
||||
gchar *str;
|
||||
|
||||
gtk_text_buffer_get_iter_at_offset (buffer, &iter, 0);
|
||||
|
||||
|
||||
gtk_text_buffer_insert_pixbuf (buffer, &iter, pixbuf);
|
||||
|
||||
gtk_text_buffer_get_iter_at_offset (buffer, &iter, 1);
|
||||
|
||||
|
||||
gtk_text_buffer_insert_pixbuf (buffer, &iter, pixbuf);
|
||||
|
||||
|
||||
str = g_strdup_printf ("%d Hello World!\nwoo woo woo woo woo woo woo woo\n",
|
||||
i);
|
||||
|
||||
|
||||
gtk_text_buffer_insert (buffer, &iter, str, -1);
|
||||
|
||||
g_free (str);
|
||||
|
||||
|
||||
gtk_text_buffer_insert (buffer, &iter,
|
||||
"(Hello World!)\nfoo foo Hello this is some text we are using to text word wrap. It has punctuation! gee; blah - hmm, great.\nnew line\n\n"
|
||||
/* This is UTF8 stuff, Emacs doesn't
|
||||
really know how to display it */
|
||||
"Spanish (Español) ¡Hola! / French (Français) Bonjour, Salut / German (Deutsch Süd) Grüß Gott (testing Latin-1 chars encoded in UTF8)\nThai (we can't display this, just making sure we don't crash) (ภาษาไทย) สวัสดีครับ, สวัสดีค่ะ\n",
|
||||
-1);
|
||||
|
||||
-1);
|
||||
|
||||
gtk_text_buffer_insert_pixbuf (buffer, &iter, pixbuf);
|
||||
gtk_text_buffer_insert_pixbuf (buffer, &iter, pixbuf);
|
||||
|
||||
|
||||
gtk_text_buffer_get_iter_at_offset (buffer, &iter, 4);
|
||||
|
||||
|
||||
gtk_text_buffer_insert_pixbuf (buffer, &iter, pixbuf);
|
||||
|
||||
gtk_text_buffer_get_iter_at_offset (buffer, &iter, 7);
|
||||
|
||||
|
||||
gtk_text_buffer_insert_pixbuf (buffer, &iter, pixbuf);
|
||||
|
||||
gtk_text_buffer_get_iter_at_offset (buffer, &iter, 8);
|
||||
|
||||
|
||||
gtk_text_buffer_insert_pixbuf (buffer, &iter, pixbuf);
|
||||
|
||||
gtk_text_buffer_get_iter_at_line_offset (buffer, &iter, 0, 8);
|
||||
@ -350,40 +668,66 @@ fill_buffer (GtkTextBuffer *buffer)
|
||||
|
||||
gtk_text_iter_forward_chars (&iter, 7);
|
||||
gtk_text_iter_forward_chars (&iter2, 10);
|
||||
|
||||
|
||||
gtk_text_buffer_apply_tag_by_name (buffer, "bg_green", &iter, &iter2);
|
||||
|
||||
gtk_text_iter_forward_chars (&iter, 12);
|
||||
gtk_text_iter_forward_chars (&iter2, 10);
|
||||
|
||||
|
||||
gtk_text_buffer_apply_tag_by_name (buffer, "bg_green", &iter, &iter2);
|
||||
|
||||
gtk_text_iter_forward_chars (&iter, 10);
|
||||
gtk_text_iter_forward_chars (&iter2, 15);
|
||||
|
||||
|
||||
gtk_text_buffer_apply_tag_by_name (buffer, "fg_red", &iter, &iter2);
|
||||
gtk_text_buffer_apply_tag_by_name (buffer, "fg_blue", &iter, &iter2);
|
||||
gtk_text_buffer_apply_tag_by_name (buffer, "fg_blue", &iter, &iter2);
|
||||
|
||||
gtk_text_iter_forward_chars (&iter, 20);
|
||||
gtk_text_iter_forward_chars (&iter2, 20);
|
||||
|
||||
|
||||
gtk_text_buffer_apply_tag_by_name (buffer, "fg_red", &iter, &iter2);
|
||||
gtk_text_buffer_apply_tag_by_name (buffer, "fg_blue", &iter, &iter2);
|
||||
gtk_text_buffer_apply_tag_by_name (buffer, "fg_blue", &iter, &iter2);
|
||||
|
||||
gtk_text_iter_backward_chars (&iter, 25);
|
||||
gtk_text_iter_forward_chars (&iter2, 5);
|
||||
|
||||
|
||||
gtk_text_buffer_apply_tag_by_name (buffer, "fg_red", &iter, &iter2);
|
||||
gtk_text_buffer_apply_tag_by_name (buffer, "fg_blue", &iter, &iter2);
|
||||
gtk_text_buffer_apply_tag_by_name (buffer, "fg_blue", &iter, &iter2);
|
||||
|
||||
gtk_text_iter_forward_chars (&iter, 15);
|
||||
gtk_text_iter_backward_chars (&iter2, 10);
|
||||
|
||||
gtk_text_buffer_remove_tag_by_name (buffer, "fg_red", &iter, &iter2);
|
||||
gtk_text_buffer_remove_tag_by_name (buffer, "fg_blue", &iter, &iter2);
|
||||
|
||||
gtk_text_buffer_remove_tag_by_name (buffer, "fg_blue", &iter, &iter2);
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
/* Put in tags that are just at the beginning, and just near the end,
|
||||
* and just near the middle.
|
||||
*/
|
||||
tag = gtk_text_buffer_create_tag (buffer, "front_tag");
|
||||
gtk_text_buffer_get_iter_at_offset (buffer, &iter, 3);
|
||||
gtk_text_buffer_get_iter_at_offset (buffer, &iter2, 300);
|
||||
|
||||
gtk_text_buffer_apply_tag (buffer, tag, &iter, &iter2);
|
||||
|
||||
tag = gtk_text_buffer_create_tag (buffer, "end_tag");
|
||||
gtk_text_buffer_get_last_iter (buffer, &iter2);
|
||||
gtk_text_iter_backward_chars (&iter2, 12);
|
||||
iter = iter2;
|
||||
gtk_text_iter_backward_chars (&iter, 157);
|
||||
|
||||
gtk_text_buffer_apply_tag (buffer, tag, &iter, &iter2);
|
||||
|
||||
tag = gtk_text_buffer_create_tag (buffer, "center_tag");
|
||||
gtk_text_buffer_get_iter_at_offset (buffer, &iter,
|
||||
gtk_text_buffer_get_char_count (buffer)/2);
|
||||
gtk_text_iter_backward_chars (&iter, 37);
|
||||
iter2 = iter;
|
||||
gtk_text_iter_forward_chars (&iter2, 57);
|
||||
|
||||
gtk_text_buffer_apply_tag (buffer, tag, &iter, &iter2);
|
||||
|
||||
gdk_pixbuf_unref (pixbuf);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user