mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2024-12-13 09:32:47 +00:00
entered into RCS
This commit is contained in:
parent
cfe158ab34
commit
90ba40fc70
147
src/intervals.c
147
src/intervals.c
@ -345,24 +345,28 @@ rotate_left (interval)
|
||||
return B;
|
||||
}
|
||||
|
||||
/* Split an interval into two. The second (RIGHT) half is returned as
|
||||
the new interval. The size and position of the interval being split are
|
||||
stored within it, having been found by find_interval (). The properties
|
||||
are reset; it is up to the caller to do the right thing.
|
||||
/* Split INTERVAL into two pieces, starting the second piece at character
|
||||
position OFFSET (counting from 1), relative to INTERVAL. The right-hand
|
||||
piece (second, lexicographically) is returned.
|
||||
|
||||
The size and position fields of the two intervals are set based upon
|
||||
those of the original interval. The property list of the new interval
|
||||
is reset, thus it is up to the caller to do the right thing with the
|
||||
result.
|
||||
|
||||
Note that this does not change the position of INTERVAL; if it is a root,
|
||||
it is still a root after this operation. */
|
||||
|
||||
INTERVAL
|
||||
split_interval_right (interval, relative_position)
|
||||
split_interval_right (interval, offset)
|
||||
INTERVAL interval;
|
||||
int relative_position;
|
||||
int offset;
|
||||
{
|
||||
INTERVAL new = make_interval ();
|
||||
int position = interval->position;
|
||||
int new_length = LENGTH (interval) - relative_position + 1;
|
||||
int new_length = LENGTH (interval) - offset + 1;
|
||||
|
||||
new->position = position + relative_position - 1;
|
||||
new->position = position + offset - 1;
|
||||
new->parent = interval;
|
||||
#if 0
|
||||
copy_properties (interval, new);
|
||||
@ -386,22 +390,26 @@ split_interval_right (interval, relative_position)
|
||||
return new;
|
||||
}
|
||||
|
||||
/* Split an interval into two. The first (LEFT) half is returned as
|
||||
the new interval. The size and position of the interval being split
|
||||
are stored within it, having been found by find_interval (). The
|
||||
properties are reset; it is up to the caller to do the right thing.
|
||||
/* Split INTERVAL into two pieces, starting the second piece at character
|
||||
position OFFSET (counting from 1), relative to INTERVAL. The left-hand
|
||||
piece (first, lexicographically) is returned.
|
||||
|
||||
Note that this does not change the position of INTERVAL in the tree; if it
|
||||
is a root, it is still a root after this operation. */
|
||||
The size and position fields of the two intervals are set based upon
|
||||
those of the original interval. The property list of the new interval
|
||||
is reset, thus it is up to the caller to do the right thing with the
|
||||
result.
|
||||
|
||||
Note that this does not change the position of INTERVAL; if it is a root,
|
||||
it is still a root after this operation. */
|
||||
|
||||
INTERVAL
|
||||
split_interval_left (interval, relative_position)
|
||||
split_interval_left (interval, offset)
|
||||
INTERVAL interval;
|
||||
int relative_position;
|
||||
int offset;
|
||||
{
|
||||
INTERVAL new = make_interval ();
|
||||
int position = interval->position;
|
||||
int new_length = relative_position - 1;
|
||||
int new_length = offset - 1;
|
||||
|
||||
#if 0
|
||||
copy_properties (interval, new);
|
||||
@ -409,7 +417,7 @@ split_interval_left (interval, relative_position)
|
||||
|
||||
new->position = interval->position;
|
||||
|
||||
interval->position = interval->position + relative_position - 1;
|
||||
interval->position = interval->position + offset - 1;
|
||||
new->parent = interval;
|
||||
|
||||
if (NULL_LEFT_CHILD (interval))
|
||||
@ -429,10 +437,15 @@ split_interval_left (interval, relative_position)
|
||||
return new;
|
||||
}
|
||||
|
||||
/* Find the interval containing POSITION in TREE. POSITION is relative
|
||||
to the start of TREE. */
|
||||
/* Find the interval containing text position POSITION in the text
|
||||
represented by the interval tree TREE. POSITION is relative to
|
||||
the beginning of that text.
|
||||
|
||||
INTERVAL
|
||||
The `position' field, which is a cache of an interval's position,
|
||||
is updated in the interval found. Other functions (e.g., next_interval)
|
||||
will update this cache based on the result of find_interval. */
|
||||
|
||||
INLINE INTERVAL
|
||||
find_interval (tree, position)
|
||||
register INTERVAL tree;
|
||||
register int position;
|
||||
@ -471,10 +484,8 @@ find_interval (tree, position)
|
||||
}
|
||||
|
||||
/* Find the succeeding interval (lexicographically) to INTERVAL.
|
||||
Sets the `position' field based on that of INTERVAL.
|
||||
|
||||
Note that those values are only correct if they were also correct
|
||||
in INTERVAL. */
|
||||
Sets the `position' field based on that of INTERVAL (see
|
||||
find_interval). */
|
||||
|
||||
INTERVAL
|
||||
next_interval (interval)
|
||||
@ -513,10 +524,8 @@ next_interval (interval)
|
||||
}
|
||||
|
||||
/* Find the preceding interval (lexicographically) to INTERVAL.
|
||||
Sets the `position' field based on that of INTERVAL.
|
||||
|
||||
Note that those values are only correct if they were also correct
|
||||
in INTERVAL. */
|
||||
Sets the `position' field based on that of INTERVAL (see
|
||||
find_interval). */
|
||||
|
||||
INTERVAL
|
||||
previous_interval (interval)
|
||||
@ -554,6 +563,7 @@ previous_interval (interval)
|
||||
return NULL_INTERVAL;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Traverse a path down the interval tree TREE to the interval
|
||||
containing POSITION, adjusting all nodes on the path for
|
||||
an addition of LENGTH characters. Insertion between two intervals
|
||||
@ -610,6 +620,59 @@ adjust_intervals_for_insertion (tree, position, length)
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Effect an adjustment corresponding to the addition of LENGTH characters
|
||||
of text. Do this by finding the interval containing POSITION in the
|
||||
interval tree TREE, and then adjusting all of it's ancestors by adding
|
||||
LENGTH to them.
|
||||
|
||||
If POSITION is the first character of an interval, meaning that point
|
||||
is actually between the two intervals, make the new text belong to
|
||||
the interval which is "sticky".
|
||||
|
||||
If both intervals are "stick", then make them belong to the left-most
|
||||
interval. Another possibility would be to create a new interval for
|
||||
this text, and make it have the merged properties of both ends. */
|
||||
|
||||
static INTERVAL
|
||||
adjust_intervals_for_insertion (tree, position, length)
|
||||
INTERVAL tree;
|
||||
int position, length;
|
||||
{
|
||||
register INTERVAL i;
|
||||
|
||||
if (TOTAL_LENGTH (tree) == 0) /* Paranoia */
|
||||
abort ();
|
||||
|
||||
/* If inserting at point-max of a buffer, that position
|
||||
will be out of range. */
|
||||
if (position > TOTAL_LENGTH (tree))
|
||||
position = TOTAL_LENGTH (tree);
|
||||
|
||||
i = find_interval (tree, position);
|
||||
/* If we are positioned between intervals, check the stickiness of
|
||||
both of them. */
|
||||
if (position == i->position
|
||||
&& position != 1)
|
||||
{
|
||||
register prev = previous_interval (i);
|
||||
|
||||
/* If both intervals are sticky here, then default to the
|
||||
left-most one. But perhaps we should create a new
|
||||
interval here instead... */
|
||||
if (END_STICKY (prev))
|
||||
i = prev;
|
||||
}
|
||||
|
||||
while (! NULL_INTERVAL_P (i))
|
||||
{
|
||||
i->total_length += length;
|
||||
i = i->parent
|
||||
}
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
/* Merge interval I with its lexicographic successor. Note that
|
||||
this does not deal with the properties, or delete I. */
|
||||
@ -697,8 +760,8 @@ merge_interval_left (i)
|
||||
return NULL_INTERVAL;
|
||||
}
|
||||
|
||||
/* Delete an interval node from its btree by merging its subtrees
|
||||
into one subtree which is returned. Caller is responsible for
|
||||
/* Delete an node I from its interval tree by merging its subtrees
|
||||
into one subtree which is then returned. Caller is responsible for
|
||||
storing the resulting subtree into its parent. */
|
||||
|
||||
static INTERVAL
|
||||
@ -1002,7 +1065,7 @@ map_intervals (source, destination, position)
|
||||
|
||||
If the inserted text had no intervals associated, this function
|
||||
simply returns -- offset_intervals should handle placing the
|
||||
text in the correct interval, depending on the hungry bits.
|
||||
text in the correct interval, depending on the sticky bits.
|
||||
|
||||
If the inserted text had properties (intervals), then there are two
|
||||
cases -- either insertion happened in the middle of some interval,
|
||||
@ -1015,12 +1078,12 @@ map_intervals (source, destination, position)
|
||||
of the text into which it was inserted.
|
||||
|
||||
If the text goes between two intervals, then if neither interval
|
||||
had its appropriate hungry property set (front_hungry, rear_hungry),
|
||||
the new text has only its properties. If one of the hungry properties
|
||||
had its appropriate sticky property set (front_sticky, rear_sticky),
|
||||
the new text has only its properties. If one of the sticky properties
|
||||
is set, then the new text "sticks" to that region and its properties
|
||||
depend on merging as above. If both the preceding and succeding
|
||||
intervals to the new text are "hungry", then the new text retains
|
||||
only its properties, as if neither hungry property were set. Perhaps
|
||||
intervals to the new text are "sticky", then the new text retains
|
||||
only its properties, as if neither sticky property were set. Perhaps
|
||||
we should consider merging all three sets of properties onto the new
|
||||
text... */
|
||||
|
||||
@ -1088,7 +1151,7 @@ graft_intervals_into_buffer (new_tree, position, b)
|
||||
/* First interval -- none precede it. */
|
||||
if (position == 1)
|
||||
{
|
||||
if (! under->front_hungry)
|
||||
if (! FRONT_STICKY (under))
|
||||
/* The inserted string keeps its own properties. */
|
||||
while (! NULL_INTERVAL_P (over))
|
||||
{
|
||||
@ -1115,10 +1178,10 @@ graft_intervals_into_buffer (new_tree, position, b)
|
||||
if (NULL_INTERVAL_P (prev))
|
||||
abort ();
|
||||
|
||||
if (prev->rear_hungry)
|
||||
if (END_STICKY (prev))
|
||||
{
|
||||
if (under->front_hungry)
|
||||
/* The intervals go inbetween as the two hungry
|
||||
if (FRONT_STICKY (under))
|
||||
/* The intervals go inbetween as the two sticky
|
||||
properties cancel each other. Should we change
|
||||
this policy? */
|
||||
while (! NULL_INTERVAL_P (over))
|
||||
@ -1142,7 +1205,7 @@ graft_intervals_into_buffer (new_tree, position, b)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (under->front_hungry)
|
||||
if (FRONT_STICKY (under))
|
||||
/* The intervals stick to under */
|
||||
while (! NULL_INTERVAL_P (over))
|
||||
{
|
||||
@ -1334,7 +1397,7 @@ verify_interval_modification (buf, start, end)
|
||||
abort ();
|
||||
|
||||
i = find_interval (intervals, start - 1);
|
||||
if (! END_HUNGRY_P (i))
|
||||
if (! END_STICKY_P (i))
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
214
src/intervals.h
Normal file
214
src/intervals.h
Normal file
@ -0,0 +1,214 @@
|
||||
/* Definitions and global variables for intervals.
|
||||
Copyright (C) 1990, 1992 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Emacs.
|
||||
|
||||
GNU Emacs 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 1, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Emacs is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Emacs; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
#ifdef USE_INTERVALS
|
||||
#include "dispextern.h"
|
||||
|
||||
#define NULL_INTERVAL 0
|
||||
#define INTERVAL_DEFAULT NULL_INTERVAL
|
||||
|
||||
/* These are macros for dealing with the interval tree. */
|
||||
|
||||
/* Size of the structure used to represent an interval */
|
||||
#define INTERVAL_SIZE (sizeof (struct interval))
|
||||
|
||||
/* Size of a pointer to an interval structure */
|
||||
#define INTERVAL_PTR_SIZE (sizeof (struct interval *))
|
||||
|
||||
/* True if an interval pointer is null, or is a Lisp_Buffer or
|
||||
Lisp_String pointer (meaning it points to the owner of this
|
||||
interval tree.) */
|
||||
#define NULL_INTERVAL_P(i) ((i) == NULL_INTERVAL || \
|
||||
XTYPE ((Lisp_Object)(i)) == Lisp_Buffer || \
|
||||
XTYPE ((Lisp_Object)(i)) == Lisp_String)
|
||||
|
||||
/* True if this interval has no right child. */
|
||||
#define NULL_RIGHT_CHILD(i) (NULL_INTERVAL_P((i)->right))
|
||||
|
||||
/* True if this interval has no left child. */
|
||||
#define NULL_LEFT_CHILD(i) (NULL_INTERVAL_P((i)->left))
|
||||
|
||||
/* True if this interval has no parent. */
|
||||
#define NULL_PARENT(i) (NULL_INTERVAL_P((i)->parent))
|
||||
|
||||
/* True if this interval is the left child of some other interval. */
|
||||
#define AM_LEFT_CHILD(i) (! NULL_INTERVAL_P ((i)->parent) \
|
||||
&& (i)->parent->left == (i))
|
||||
|
||||
/* True if this interval is the right ehild of some other interval. */
|
||||
#define AM_RIGHT_CHILD(i) (! NULL_INTERVAL_P ((i)->parent) \
|
||||
&& (i)->parent->right == (i))
|
||||
|
||||
/* True if this interval has no children. */
|
||||
#define LEAF_INTERVAL_P(i) ((i)->left == NULL_INTERVAL \
|
||||
&& (i)->right == NULL_INTERVAL)
|
||||
|
||||
/* True if this interval has no parent and is therefore the root. */
|
||||
#define ROOT_INTERVAL_P(i) (NULL_PARENT (i))
|
||||
|
||||
/* True if this interval is the only interval in the interval tree. */
|
||||
#define ONLY_INTERVAL_P(i) (ROOT_INTERVAL_P((i)) && LEAF_INTERVAL_P ((i)))
|
||||
|
||||
/* True if this interval has both left and right children. */
|
||||
#define BOTH_KIDS_P(i) ((i)->left != NULL_INTERVAL \
|
||||
&& (i)->right != NULL_INTERVAL)
|
||||
|
||||
/* The total size of all text represented by this interval and all its
|
||||
children in the tree. This is zero if the interval is null. */
|
||||
#define TOTAL_LENGTH(i) ((i) == NULL_INTERVAL ? 0 : (i)->total_length)
|
||||
|
||||
/* The size of text represented by this interval alone. */
|
||||
#define LENGTH(i) ((i) == NULL_INTERVAL ? 0 : (TOTAL_LENGTH ((i)) \
|
||||
- TOTAL_LENGTH ((i)->right) \
|
||||
- TOTAL_LENGTH ((i)->left)))
|
||||
|
||||
/* The absolute index of the last character belonging to I. Note that
|
||||
the position cache i->position must be valid for this to work. */
|
||||
#define INTERVAL_LAST_POS(i) ((i)->position + LENGTH ((i)) - 1)
|
||||
|
||||
/* The total size of the left subtree of this interval. */
|
||||
#define LEFT_TOTAL_LENGTH(i) ((i)->left ? (i)->left->total_length : 0)
|
||||
|
||||
/* The total size of the right subtree of this interval. */
|
||||
#define RIGHT_TOTAL_LENGTH(i) ((i)->right ? (i)->right->total_length : 0)
|
||||
|
||||
|
||||
/* These macros are for dealing with the interval properties. */
|
||||
|
||||
/* True if this is a default interval, which is the same as being null
|
||||
or having no properties. */
|
||||
#define DEFAULT_INTERVAL_P(i) (NULL_INTERVAL_P (i) || EQ ((i)->plist, Qnil))
|
||||
|
||||
/* Reset this interval to its vanilla, or no-property state. */
|
||||
#define RESET_INTERVAL(i) { \
|
||||
(i)->total_length = (i)->position = 0; \
|
||||
(i)->left = (i)->right = NULL_INTERVAL; \
|
||||
(i)->parent = NULL_INTERVAL; \
|
||||
(i)->write_protect = 0; \
|
||||
(i)->visible = 0; \
|
||||
(i)->front_sticky = (i)->rear_sticky = 0; \
|
||||
(i)->plist = Qnil; \
|
||||
}
|
||||
|
||||
/* Copy the cached property values of interval FROM to interval TO. */
|
||||
#define COPY_INTERVAL_CACHE(from,to) \
|
||||
{ \
|
||||
(to)->write_protect = (from)->write_protect; \
|
||||
(to)->visible = (from)->visible; \
|
||||
(to)->front_sticky = (from)->front_sticky; \
|
||||
(to)->rear_sticky = (from)->rear_sticky; \
|
||||
}
|
||||
|
||||
/* Copy only the set bits of FROM's cache. */
|
||||
#define MERGE_INTERVAL_CACHE(from,to) \
|
||||
{ \
|
||||
if ((from)->write_protect) (to)->write_protect = 1; \
|
||||
if ((from)->visible) (to)->visible = 1; \
|
||||
if ((from)->front_sticky) (to)->front_sticky = 1; \
|
||||
if ((from)->rear_sticky) (to)->rear_sticky = 1; \
|
||||
}
|
||||
|
||||
/* Macro determining whether the properties of an interval being
|
||||
inserted should be merged with the properties of the text where
|
||||
they are being inserted. */
|
||||
#define MERGE_INSERTIONS(i) 0
|
||||
|
||||
/* Macro determining if an invisible interval should be displayed
|
||||
as a special glyph, or not at all. */
|
||||
#define DISPLAY_INVISIBLE_GLYPH(i) 0
|
||||
|
||||
/* Is this interval visible? Replace later with cache access */
|
||||
#define INTERVAL_VISIBLE_P(i) \
|
||||
(! NULL_INTERVAL_P (i) && ! NILP (Fmemq (Qinvisible, (i)->plist)))
|
||||
|
||||
/* Is this interval writable? Replace later with cache access */
|
||||
#define INTERVAL_WRITABLE_P(i) \
|
||||
(! NULL_INTERVAL_P (i) && NILP (Fmemq (Qread_only, (i)->plist)))
|
||||
|
||||
/* Macros to tell whether insertions before or after this interval
|
||||
should stick to it. */
|
||||
#define FRONT_STICKY_P(i) ((i)->front_sticky != 0)
|
||||
#define END_STICKY_P(i) ((i)->rear_sticky != 0)
|
||||
|
||||
|
||||
/* Declared in alloc.c */
|
||||
|
||||
extern INTERVAL make_interval ();
|
||||
|
||||
/* Declared in intervals.c */
|
||||
|
||||
extern INTERVAL mouse_interval;
|
||||
extern Lisp_Object Vmouse_buffer;
|
||||
extern int mouse_buffer_offset;
|
||||
extern Lisp_Object interval_balance_threshold;
|
||||
|
||||
extern INTERVAL create_root_interval ();
|
||||
extern void copy_properties ();
|
||||
extern int intervals_equal ();
|
||||
extern void traverse_intervals ();
|
||||
extern INTERVAL split_interval_right (), split_interval_left ();
|
||||
extern INTERVAL find_interval (), next_interval (), previous_interval ();
|
||||
extern INTERVAL merge_interval_left (), merge_interval_right ();
|
||||
extern void delete_interval ();
|
||||
extern INLINE void offset_intervals ();
|
||||
extern void map_intervals ();
|
||||
extern void graft_intervals_into_buffer ();
|
||||
extern void set_point ();
|
||||
extern void verify_interval_modification ();
|
||||
extern INTERVAL balance_intervals ();
|
||||
extern void insert_interval_copy();
|
||||
extern void copy_intervals_to_string ();
|
||||
extern INTERVAL make_string_interval ();
|
||||
extern INTERVAL make_buffer_interval ();
|
||||
|
||||
/* Declared in textprop.c */
|
||||
|
||||
/* Types of hooks. */
|
||||
extern Lisp_Object Qmouse_left;
|
||||
extern Lisp_Object Qmouse_entered;
|
||||
extern Lisp_Object Qpoint_left;
|
||||
extern Lisp_Object Qpoint_entered;
|
||||
extern Lisp_Object Qmodification;
|
||||
|
||||
/* Visual properties text (including strings) may have. */
|
||||
extern Lisp_Object Qforeground, Qbackground, Qfont, Qunderline, Qstipple;
|
||||
extern Lisp_Object Qinvisible, Qread_only;
|
||||
|
||||
extern void run_hooks ();
|
||||
|
||||
extern Lisp_Object Ftext_properties_at ();
|
||||
extern Lisp_Object Fnext_property_change (), Fprevious_property_change ();
|
||||
extern Lisp_Object Fadd_text_properties (), Fset_text_properties ();
|
||||
extern Lisp_Object Fremove_text_properties (), Ferase_text_properties ();
|
||||
|
||||
extern void syms_of_textprop ();
|
||||
|
||||
#else /* intervals not used */
|
||||
|
||||
#define NULL_INTERVAL_P(i) 1
|
||||
#define INTERVAL_SIZE 0
|
||||
#define INTERVAL_PTR_SIZE 0
|
||||
|
||||
#define copy_intervals_to_string(string,buffer,position,length)
|
||||
#define verify_interval_modification(buffer,start,end)
|
||||
#define insert_interval_copy(source,position,end,sink,at)
|
||||
#define graft_intervals_into_buffer(tree,position,bufferptr)
|
||||
#define offset_intervals(buffer,position,length)
|
||||
|
||||
#endif /* intervals not used */
|
Loading…
Reference in New Issue
Block a user