2005-12-10 21:17:16 -08:00
|
|
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4; coding: utf-8 -*-
|
|
|
|
*
|
|
|
|
* moofold.c
|
|
|
|
*
|
2006-02-23 06:03:17 -08:00
|
|
|
* Copyright (C) 2004-2006 by Yevgen Muntyan <muntyan@math.tamu.edu>
|
2005-12-10 21:17:16 -08:00
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* See COPYING file that comes with this distribution.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define MOOEDIT_COMPILATION
|
|
|
|
#include "mooedit/mootext-private.h"
|
|
|
|
#include "mooutils/moomarshals.h"
|
|
|
|
|
|
|
|
|
2005-12-13 04:44:02 -08:00
|
|
|
#ifdef MOO_DEBUG
|
2005-12-12 02:58:25 -08:00
|
|
|
#define WANT_CHECKS 1
|
2005-12-13 04:44:02 -08:00
|
|
|
#else
|
|
|
|
#define WANT_CHECKS 0
|
|
|
|
#endif
|
2005-12-12 02:58:25 -08:00
|
|
|
|
|
|
|
static void moo_fold_finalize (GObject *object);
|
|
|
|
static void moo_fold_free_recursively (MooFold *fold);
|
2005-12-10 21:17:16 -08:00
|
|
|
|
|
|
|
|
|
|
|
enum {
|
|
|
|
LAST_SIGNAL
|
|
|
|
};
|
|
|
|
|
|
|
|
// static guint signals[LAST_SIGNAL];
|
|
|
|
|
|
|
|
|
|
|
|
enum {
|
|
|
|
PROP_0
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/* MOO_TYPE_FOLD */
|
|
|
|
G_DEFINE_TYPE (MooFold, moo_fold, G_TYPE_OBJECT)
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
moo_fold_class_init (MooFoldClass *klass)
|
|
|
|
{
|
|
|
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
|
|
|
|
|
|
|
gobject_class->finalize = moo_fold_finalize;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
2005-12-12 02:58:25 -08:00
|
|
|
moo_fold_init (MooFold *fold)
|
2005-12-10 21:17:16 -08:00
|
|
|
{
|
2005-12-12 02:58:25 -08:00
|
|
|
fold->deleted = TRUE;
|
2005-12-10 21:17:16 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
moo_fold_finalize (GObject *object)
|
|
|
|
{
|
|
|
|
MooFold *fold = MOO_FOLD (object);
|
2005-12-12 02:58:25 -08:00
|
|
|
|
|
|
|
if (!fold->deleted)
|
|
|
|
g_critical ("%s: oops, crash pending...", G_STRLOC);
|
|
|
|
|
2005-12-10 21:17:16 -08:00
|
|
|
G_OBJECT_CLASS (moo_fold_parent_class)->finalize (object);
|
|
|
|
}
|
2005-12-12 02:58:25 -08:00
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
moo_fold_free_recursively (MooFold *fold)
|
|
|
|
{
|
|
|
|
MooFold *child;
|
|
|
|
|
|
|
|
g_return_if_fail (MOO_IS_FOLD (fold));
|
|
|
|
|
|
|
|
fold->deleted = TRUE;
|
|
|
|
|
|
|
|
child = fold->children;
|
|
|
|
fold->children = NULL;
|
|
|
|
|
|
|
|
for ( ; child != NULL; child = child->next)
|
|
|
|
moo_fold_free_recursively (child);
|
|
|
|
|
|
|
|
if (fold->start)
|
|
|
|
g_object_unref (fold->start);
|
|
|
|
if (fold->end)
|
|
|
|
g_object_unref (fold->end);
|
|
|
|
g_object_unref (fold);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
moo_fold_get_start (MooFold *fold)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (MOO_IS_FOLD (fold), -1);
|
|
|
|
g_return_val_if_fail (!moo_fold_is_deleted (fold), -1);
|
|
|
|
return moo_line_mark_get_line (fold->start);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
moo_fold_get_end (MooFold *fold)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (MOO_IS_FOLD (fold), -1);
|
|
|
|
g_return_val_if_fail (!moo_fold_is_deleted (fold), -1);
|
|
|
|
return moo_line_mark_get_line (fold->end);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
moo_fold_is_deleted (MooFold *fold)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (MOO_IS_FOLD (fold), TRUE);
|
|
|
|
return fold->deleted != 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#if WANT_CHECKS
|
|
|
|
|
2005-12-13 04:12:31 -08:00
|
|
|
static void
|
2005-12-12 02:58:25 -08:00
|
|
|
CHECK_LIST_MEMBER__ (MooFold *list,
|
|
|
|
MooFold *fold)
|
|
|
|
{
|
|
|
|
while (list)
|
|
|
|
{
|
|
|
|
if (list == fold)
|
2005-12-13 04:12:31 -08:00
|
|
|
return;
|
2005-12-12 02:58:25 -08:00
|
|
|
list = list->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_assert_not_reached ();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
CHECK_FOLD (MooFoldTree *tree,
|
|
|
|
MooFold *fold)
|
|
|
|
{
|
|
|
|
g_assert (tree != NULL);
|
|
|
|
g_assert (MOO_IS_FOLD (fold));
|
|
|
|
g_assert (!fold->deleted);
|
|
|
|
|
|
|
|
while (fold->parent)
|
|
|
|
{
|
|
|
|
CHECK_LIST_MEMBER__ (fold->parent->children, fold);
|
|
|
|
fold = fold->parent;
|
|
|
|
}
|
|
|
|
|
|
|
|
CHECK_LIST_MEMBER__ (tree->folds, fold);
|
|
|
|
}
|
|
|
|
|
|
|
|
#else /* WANT_CHECKS */
|
|
|
|
#define CHECK_FOLD(tree,fold)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
MooFoldTree *
|
|
|
|
moo_fold_tree_new (MooTextBuffer *buffer)
|
|
|
|
{
|
|
|
|
MooFoldTree *tree = g_new0 (MooFoldTree, 1);
|
|
|
|
|
|
|
|
tree->buffer = buffer;
|
|
|
|
tree->consistent = TRUE;
|
|
|
|
|
|
|
|
return tree;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
moo_fold_tree_free (MooFoldTree *tree)
|
|
|
|
{
|
|
|
|
MooFold *child;
|
|
|
|
|
|
|
|
g_return_if_fail (tree != NULL);
|
|
|
|
|
|
|
|
for (child = tree->folds; child != NULL; child = child->next)
|
|
|
|
moo_fold_free_recursively (child);
|
|
|
|
|
|
|
|
g_free (tree);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
get_line_count (MooFoldTree *tree)
|
|
|
|
{
|
|
|
|
return gtk_text_buffer_get_line_count (GTK_TEXT_BUFFER (tree->buffer));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static MooLineMark *
|
|
|
|
fold_mark_new (MooFold *fold)
|
|
|
|
{
|
|
|
|
MooLineMark *mark = g_object_new (MOO_TYPE_LINE_MARK, NULL);
|
|
|
|
_moo_line_mark_set_fold (mark, fold);
|
|
|
|
return mark;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static MooFold *
|
|
|
|
insert_fold (MooFoldTree *tree,
|
|
|
|
MooFold *parent,
|
|
|
|
int first_line,
|
|
|
|
int last_line)
|
|
|
|
{
|
|
|
|
MooFold *fold, *last, *new_fold;
|
|
|
|
|
|
|
|
g_assert (!parent || MOO_IS_FOLD (parent));
|
|
|
|
g_assert (!parent || moo_fold_get_start (parent) < first_line);
|
|
|
|
g_assert (!parent || moo_fold_get_end (parent) >= last_line);
|
|
|
|
|
|
|
|
last = NULL;
|
|
|
|
|
|
|
|
for (fold = (parent ? parent->children : tree->folds); fold != NULL; fold = fold->next)
|
|
|
|
{
|
|
|
|
int start, end;
|
|
|
|
|
|
|
|
start = moo_fold_get_start (fold);
|
|
|
|
end = moo_fold_get_end (fold);
|
|
|
|
|
|
|
|
if (!fold->next)
|
|
|
|
last = fold;
|
|
|
|
|
|
|
|
if (end < first_line)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (start > last_line)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (start == first_line || end == first_line || start == last_line)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (start < first_line)
|
|
|
|
{
|
|
|
|
if (end < last_line)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
/* new fold is inserted into the old one */
|
|
|
|
return insert_fold (tree, fold, first_line, last_line);
|
|
|
|
}
|
|
|
|
else /* start > first_line */
|
|
|
|
{
|
|
|
|
if (end > last_line)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
/* old fold is inserted into the new one */
|
|
|
|
|
|
|
|
new_fold = g_object_new (MOO_TYPE_FOLD, NULL);
|
|
|
|
new_fold->deleted = FALSE;
|
|
|
|
|
|
|
|
if (parent)
|
|
|
|
{
|
|
|
|
if (!parent->children || fold == parent->children)
|
|
|
|
parent->children = new_fold;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!tree->folds || fold == tree->folds)
|
|
|
|
tree->folds = new_fold;
|
|
|
|
}
|
|
|
|
|
|
|
|
new_fold->parent = parent;
|
|
|
|
fold->parent = new_fold;
|
|
|
|
new_fold->children = fold;
|
|
|
|
new_fold->n_children = 1;
|
|
|
|
|
|
|
|
if (fold->next)
|
|
|
|
{
|
|
|
|
fold->next->prev = new_fold;
|
|
|
|
new_fold->next = fold->next;
|
|
|
|
fold->next = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fold->prev)
|
|
|
|
{
|
|
|
|
fold->prev->next = new_fold;
|
|
|
|
new_fold->prev = fold->prev;
|
|
|
|
fold->prev = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
new_fold->start = fold_mark_new (new_fold);
|
|
|
|
new_fold->end = fold_mark_new (new_fold);
|
|
|
|
|
|
|
|
moo_text_buffer_add_line_mark (tree->buffer, new_fold->start, first_line);
|
|
|
|
moo_text_buffer_add_line_mark (tree->buffer, new_fold->end, last_line);
|
|
|
|
|
|
|
|
CHECK_FOLD (tree, new_fold);
|
|
|
|
return new_fold;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* insert new fold before <fold> or in the end if <fold> is NULL */
|
|
|
|
|
|
|
|
new_fold = g_object_new (MOO_TYPE_FOLD, NULL);
|
|
|
|
new_fold->deleted = FALSE;
|
|
|
|
|
|
|
|
new_fold->parent = parent;
|
|
|
|
new_fold->next = fold;
|
|
|
|
|
|
|
|
if (parent)
|
|
|
|
{
|
|
|
|
if (fold == parent->children)
|
|
|
|
parent->children = new_fold;
|
|
|
|
parent->n_children++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (fold == tree->folds)
|
|
|
|
tree->folds = new_fold;
|
|
|
|
tree->n_folds++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fold)
|
|
|
|
{
|
|
|
|
if (fold->prev)
|
|
|
|
new_fold->prev = fold->prev;
|
|
|
|
fold->prev = new_fold;
|
|
|
|
}
|
|
|
|
else if (last)
|
|
|
|
{
|
|
|
|
g_assert (last->next == NULL);
|
|
|
|
last->next = new_fold;
|
|
|
|
new_fold->prev = last;
|
|
|
|
}
|
|
|
|
|
|
|
|
new_fold->start = fold_mark_new (new_fold);
|
|
|
|
new_fold->end = fold_mark_new (new_fold);
|
|
|
|
|
|
|
|
moo_text_buffer_add_line_mark (tree->buffer, new_fold->start, first_line);
|
|
|
|
moo_text_buffer_add_line_mark (tree->buffer, new_fold->end, last_line);
|
|
|
|
|
|
|
|
CHECK_FOLD (tree, new_fold);
|
|
|
|
return new_fold;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
MooFold *
|
|
|
|
moo_fold_tree_add (MooFoldTree *tree,
|
|
|
|
int first_line,
|
|
|
|
int last_line)
|
|
|
|
{
|
|
|
|
g_assert (tree != NULL);
|
|
|
|
g_assert (first_line >= 0 && first_line < get_line_count (tree));
|
|
|
|
g_assert (last_line >= 0 && last_line < get_line_count (tree));
|
|
|
|
g_assert (last_line > first_line);
|
|
|
|
return insert_fold (tree, NULL, first_line, last_line);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
fold_free (MooFold *fold)
|
|
|
|
{
|
|
|
|
fold->deleted = TRUE;
|
|
|
|
|
|
|
|
if (fold->start)
|
|
|
|
{
|
|
|
|
_moo_line_mark_set_fold (fold->start, NULL);
|
|
|
|
|
|
|
|
if (!moo_line_mark_get_deleted (fold->start))
|
|
|
|
moo_text_buffer_delete_line_mark (moo_line_mark_get_buffer (fold->start),
|
|
|
|
fold->start);
|
|
|
|
|
|
|
|
g_object_unref (fold->start);
|
|
|
|
fold->start = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fold->end)
|
|
|
|
{
|
|
|
|
_moo_line_mark_set_fold (fold->end, NULL);
|
|
|
|
|
|
|
|
if (!moo_line_mark_get_deleted (fold->end))
|
|
|
|
moo_text_buffer_delete_line_mark (moo_line_mark_get_buffer (fold->end),
|
|
|
|
fold->end);
|
|
|
|
|
|
|
|
g_object_unref (fold->end);
|
|
|
|
fold->end = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_object_unref (fold);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
moo_fold_tree_remove (MooFoldTree *tree,
|
|
|
|
MooFold *fold)
|
|
|
|
{
|
|
|
|
guint n_children;
|
|
|
|
MooFold *children, *parent, *last;
|
|
|
|
|
|
|
|
CHECK_FOLD (tree, fold);
|
|
|
|
|
|
|
|
moo_fold_tree_expand (tree, fold);
|
|
|
|
|
|
|
|
n_children = fold->n_children;
|
|
|
|
last = children = fold->children;
|
|
|
|
parent = fold->parent;
|
|
|
|
|
|
|
|
if (children)
|
|
|
|
{
|
|
|
|
while (TRUE)
|
|
|
|
{
|
|
|
|
g_assert (last->parent == fold);
|
|
|
|
last->parent = fold->parent;
|
|
|
|
if (!last->next)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
g_assert ((last && children) || (!last && !children));
|
|
|
|
|
|
|
|
if (parent)
|
|
|
|
{
|
|
|
|
if (fold == parent->children)
|
|
|
|
parent->children = children ? children : parent->children->next;
|
|
|
|
parent->n_children = parent->n_children + n_children - 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (fold == tree->folds)
|
|
|
|
tree->folds = children ? children : tree->folds->next;
|
|
|
|
tree->n_folds = tree->n_folds + n_children - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (last)
|
|
|
|
last->next = fold->next;
|
|
|
|
if (fold->next)
|
|
|
|
fold->next->prev = last ? last : fold->prev;
|
|
|
|
if (children)
|
|
|
|
children->prev = fold->prev;
|
|
|
|
if (fold->prev)
|
|
|
|
fold->prev->next = children ? children : fold->next;
|
|
|
|
|
|
|
|
fold_free (fold);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
expand_check_visible (MooFoldTree *tree,
|
|
|
|
MooFold *fold)
|
|
|
|
{
|
|
|
|
GtkTextIter start, end;
|
|
|
|
GtkTextBuffer *buffer;
|
|
|
|
MooFold *child;
|
|
|
|
|
|
|
|
CHECK_FOLD (tree, fold);
|
|
|
|
|
|
|
|
buffer = GTK_TEXT_BUFFER (tree->buffer);
|
|
|
|
gtk_text_buffer_get_iter_at_line (buffer, &start,
|
|
|
|
moo_fold_get_start (fold));
|
|
|
|
end = start;
|
|
|
|
gtk_text_iter_forward_line (&end);
|
|
|
|
gtk_text_buffer_remove_tag_by_name (buffer, MOO_FOLD_TAG, &start, &end);
|
|
|
|
|
|
|
|
if (fold->collapsed)
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (child = fold->children; child != NULL; child = child->next)
|
|
|
|
{
|
|
|
|
int start_line, end_line;
|
|
|
|
|
|
|
|
if (child->prev)
|
|
|
|
start_line = moo_fold_get_end (child->prev) + 1;
|
|
|
|
else
|
|
|
|
start_line = moo_fold_get_start (fold) + 1;
|
|
|
|
|
|
|
|
end_line = moo_fold_get_start (child);
|
|
|
|
|
|
|
|
gtk_text_buffer_get_iter_at_line (buffer, &start, start_line);
|
|
|
|
gtk_text_buffer_get_iter_at_line (buffer, &end, end_line);
|
|
|
|
gtk_text_iter_forward_line (&end);
|
|
|
|
gtk_text_buffer_remove_tag_by_name (buffer, MOO_FOLD_TAG, &start, &end);
|
|
|
|
|
|
|
|
expand_check_visible (tree, child);
|
|
|
|
|
|
|
|
if (!child->next)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (child)
|
|
|
|
{
|
|
|
|
if (moo_fold_get_end (child) < moo_fold_get_end (fold))
|
|
|
|
{
|
|
|
|
gtk_text_buffer_get_iter_at_line (buffer, &start,
|
|
|
|
moo_fold_get_end (child) + 1);
|
|
|
|
gtk_text_buffer_get_iter_at_line (buffer, &end,
|
|
|
|
moo_fold_get_end (fold));
|
|
|
|
gtk_text_iter_forward_line (&end);
|
|
|
|
gtk_text_buffer_remove_tag_by_name (buffer, MOO_FOLD_TAG, &start, &end);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
start = end;
|
|
|
|
gtk_text_buffer_get_iter_at_line (buffer, &end,
|
|
|
|
moo_fold_get_end (fold));
|
|
|
|
gtk_text_iter_forward_line (&end);
|
|
|
|
gtk_text_buffer_remove_tag_by_name (buffer, MOO_FOLD_TAG, &start, &end);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
moo_fold_tree_expand (MooFoldTree *tree,
|
|
|
|
MooFold *fold)
|
|
|
|
{
|
|
|
|
CHECK_FOLD (tree, fold);
|
|
|
|
|
|
|
|
if (!fold->collapsed)
|
|
|
|
return;
|
|
|
|
|
|
|
|
fold->collapsed = FALSE;
|
|
|
|
expand_check_visible (tree, fold);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
moo_fold_tree_collapse (MooFoldTree *tree,
|
|
|
|
MooFold *fold)
|
|
|
|
{
|
|
|
|
GtkTextIter start, end;
|
|
|
|
GtkTextBuffer *buffer;
|
|
|
|
|
|
|
|
CHECK_FOLD (tree, fold);
|
|
|
|
|
|
|
|
if (fold->collapsed)
|
|
|
|
return;
|
|
|
|
|
|
|
|
fold->collapsed = TRUE;
|
|
|
|
|
|
|
|
buffer = GTK_TEXT_BUFFER (tree->buffer);
|
|
|
|
gtk_text_buffer_get_iter_at_line (buffer, &start,
|
|
|
|
moo_fold_get_start (fold) + 1);
|
|
|
|
gtk_text_buffer_get_iter_at_line (buffer, &end,
|
|
|
|
moo_fold_get_end (fold));
|
|
|
|
gtk_text_iter_forward_line (&end);
|
|
|
|
gtk_text_buffer_apply_tag_by_name (buffer, MOO_FOLD_TAG, &start, &end);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static GSList *
|
|
|
|
get_folds_in_range (MooFoldTree *tree,
|
|
|
|
MooFold *parent,
|
|
|
|
int first_line,
|
|
|
|
int last_line,
|
|
|
|
GSList *list)
|
|
|
|
{
|
|
|
|
MooFold *child;
|
|
|
|
|
|
|
|
if (parent && first_line <= moo_fold_get_start (parent) && last_line >= moo_fold_get_start (parent))
|
|
|
|
list = g_slist_prepend (list, parent);
|
|
|
|
|
|
|
|
for (child = parent ? parent->children : tree->folds; child != NULL; child = child->next)
|
|
|
|
{
|
|
|
|
if (last_line < moo_fold_get_start (child))
|
|
|
|
break;
|
|
|
|
if (first_line >= moo_fold_get_end (child))
|
|
|
|
continue;
|
|
|
|
list = get_folds_in_range (tree, child, first_line, last_line, list);
|
|
|
|
}
|
|
|
|
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
GSList *
|
|
|
|
moo_fold_tree_get (MooFoldTree *tree,
|
|
|
|
int first_line,
|
|
|
|
int last_line)
|
|
|
|
{
|
|
|
|
GSList *list;
|
|
|
|
|
|
|
|
g_assert (tree != NULL);
|
|
|
|
g_assert (first_line >= 0 && first_line < get_line_count (tree));
|
|
|
|
g_assert (last_line >= 0 && last_line < get_line_count (tree));
|
|
|
|
g_assert (last_line >= first_line);
|
|
|
|
|
|
|
|
list = get_folds_in_range (tree, NULL, first_line, last_line, NULL);
|
|
|
|
return g_slist_reverse (list);
|
|
|
|
}
|