/* Copyright (c) 1994, 1995 Free Software Foundation.
   Copyright (c) 1995, 1996, 2002, 2010 Ben Wing.

This file is part of XEmacs.

XEmacs 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 3 of the License, or (at your
option) any later version.

XEmacs 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 XEmacs.  If not, see <http://www.gnu.org/licenses/>. */

/* Synched up with: Not in FSF. */

#ifndef INCLUDED_extents_h_
#define INCLUDED_extents_h_

#include "lstream.h"
#include "buffer.h"

DECLARE_LISP_OBJECT (extent, struct extent);
#define XEXTENT(x) XRECORD (x, extent, struct extent)
#define wrap_extent(p) wrap_record (p, extent)
#define EXTENTP(x) RECORDP (x, extent)
#define CHECK_EXTENT(x) CHECK_RECORD (x, extent)
#define CONCHECK_EXTENT(x) CONCHECK_RECORD (x, extent)

struct extent_auxiliary;

DECLARE_LISP_OBJECT (extent_auxiliary, struct extent_auxiliary);
#define XEXTENT_AUXILIARY(x) \
  XRECORD (x, extent_auxiliary, struct extent_auxiliary)
#define wrap_extent_auxiliary(p) wrap_record (p, extent_auxiliary)
#define EXTENT_AUXILIARYP(x) RECORDP (x, extent_auxiliary)
#define CHECK_EXTENT_AUXILIARY(x) CHECK_RECORD (x, extent_auxiliary)
#define CONCHECK_EXTENT_AUXILIARY(x) CONCHECK_RECORD (x, extent_auxiliary)

struct extent_info;

DECLARE_LISP_OBJECT (extent_info, struct extent_info);
#define XEXTENT_INFO(x) XRECORD (x, extent_info, struct extent_info)
#define wrap_extent_info(p) wrap_record (p, extent_info)
#define EXTENT_INFOP(x) RECORDP (x, extent_info)
#define CHECK_EXTENT_INFO(x) CHECK_RECORD (x, extent_info)
#define CONCHECK_EXTENT_INFO(x) CONCHECK_RECORD (x, extent_info)


/* the layouts for glyphs (extent->flags.glyph_layout).  Must fit in 2 bits. */
typedef enum glyph_layout
{
  GL_TEXT,
  GL_OUTSIDE_MARGIN,
  GL_INSIDE_MARGIN,
  GL_WHITESPACE
} glyph_layout;

struct extent;

void set_extent_endpoints (EXTENT extent, Bytexpos s, Bytexpos e,
			   Lisp_Object object);

void set_extent_glyph (EXTENT extent, Lisp_Object glyph, int endp,
		       glyph_layout layout);

Lisp_Object allocate_extent_info (void);

/* flags for map_extents() and friends */
#define ME_END_CLOSED (1 << 0)
#define ME_START_OPEN (1 << 1)
#define ME_ALL_EXTENTS_CLOSED (1 << 2)
#define ME_ALL_EXTENTS_OPEN (2 << 2)
#define ME_ALL_EXTENTS_CLOSED_OPEN (3 << 2)
#define ME_ALL_EXTENTS_OPEN_CLOSED (4 << 2)
#define ME_ALL_EXTENTS_MASK (7 << 2)
#define ME_START_IN_REGION (1 << 5)
#define ME_END_IN_REGION (2 << 5)
#define ME_START_AND_END_IN_REGION (3 << 5)
#define ME_START_OR_END_IN_REGION (4 << 5)
#define ME_IN_REGION_MASK (7 << 5)
#define ME_NEGATE_IN_REGION (1 << 8)
/* the following flags are internal-only */
#define ME_INCLUDE_INTERNAL (1 << 9)
#define ME_MIGHT_THROW (1 << 10)
#define ME_MIGHT_MODIFY_TEXT (1 << 11)
#define ME_MIGHT_MODIFY_EXTENTS (1 << 12)
#define ME_MIGHT_MOVE_SOE (1 << 13)
#define ME_MIGHT_CALL_ELISP (ME_MIGHT_THROW | ME_MIGHT_MODIFY_TEXT | \
			     ME_MIGHT_MODIFY_EXTENTS | ME_MIGHT_MOVE_SOE)


extern int inside_undo;
extern int in_modeline_generation;

extern Fixnum mouse_highlight_priority;

EXFUN (Fextent_at, 5);
EXFUN (Fextent_property, 3);
EXFUN (Fput_text_property, 5);
EXFUN (Fextent_live_p, 1);
EXFUN (Fextent_detached_p, 1);
EXFUN (Fdelete_extent, 1);
EXFUN (Fdetach_extent, 1);
EXFUN (Fdelete_extent, 1);
EXFUN (Fextent_end_position, 2);
EXFUN (Fextent_object, 1);
EXFUN (Fextent_properties, 1);
EXFUN (Fextent_face, 1);
EXFUN (Fextent_start_position, 2);
EXFUN (Fget_char_property, 4);
EXFUN (Fmake_extent, 3);
EXFUN (Fcopy_extent, 2);
EXFUN (Fnext_extent_change, 2);
EXFUN (Fprevious_extent_change, 2);
EXFUN (Fprevious_single_char_property_change, 4);
EXFUN (Fset_extent_endpoints, 4);
EXFUN (Fset_extent_parent, 2);
EXFUN (Fset_extent_property, 3);
EXFUN (Fset_extent_priority, 2);
EXFUN (Fset_extent_face, 2);
EXFUN (Fmap_extents, 8);

extern Lisp_Object Qduplicable;

enum extent_at_flag
{
  EXTENT_AT_DEFAULT = 0,
  EXTENT_AT_AFTER = 0,
  EXTENT_AT_BEFORE,
  EXTENT_AT_AT
};

Bytexpos extent_endpoint_byte (EXTENT extent, int endp);
Charxpos extent_endpoint_char (EXTENT extent, int endp);
Bytexpos next_previous_single_property_change (Bytexpos pos, Lisp_Object prop,
					       Lisp_Object object,
					       Bytexpos limit,
					       Boolint next,
					       Boolint text_props_only);
Lisp_Object get_char_property (Bytexpos position, Lisp_Object prop,
			       Lisp_Object object, enum extent_at_flag fl,
			       int text_props_only);
void adjust_extents (Lisp_Object object, Memxpos from,
		     Memxpos to, int amount);
void adjust_extents_for_deletion (Lisp_Object object, Bytexpos from,
				  Bytexpos to, int gapsize,
				  int numdel, int movegapsize);
void verify_extent_modification (Lisp_Object object, Bytexpos from,
				 Bytexpos to,
				 Lisp_Object inhibit_read_only_value);
void process_extents_for_insertion (Lisp_Object object,
				    Bytexpos opoint, Bytecount length);
void process_extents_for_deletion (Lisp_Object object, Bytexpos from,
				   Bytexpos to, int destroy_them);
void report_extent_modification (Lisp_Object buffer, Bytexpos start,
				 Bytexpos end, int afterp);
void add_string_extents (Lisp_Object string, struct buffer *buf,
			 Bytexpos opoint, Bytecount length);
void splice_in_string_extents (Lisp_Object string, struct buffer *buf,
			       Bytexpos opoint, Bytecount length,
			       Bytecount pos);
void copy_string_extents (Lisp_Object new_object,
			  Lisp_Object old_string,
			  Bytecount new_pos, Bytecount old_pos,
			  Bytecount length);
void stretch_string_extents (Lisp_Object new_object, Lisp_Object old_string,
                             Bytecount new_pos, Bytecount old_pos,
                             Bytecount old_length, Bytecount new_length);

/* Return a bytecount appropriate for use when creating an extent with
   STREAM's current position as its end-position or its start-position.  Most
   appropriate for use with stretch_string_extents(). */
DECLARE_INLINE_HEADER (
Bytexpos
stream_extent_position (Lisp_Object stream)
)
{
  if (LRECORDP (stream))
    {
      switch ((enum lrecord_type) (XRECORD_LHEADER (stream)->type))
        {
        case lrecord_type_lstream:
          return Lstream_byte_count (XLSTREAM (stream));
        case lrecord_type_buffer:
          return BYTE_BUF_PT (XBUFFER (stream));
        case lrecord_type_marker:
          return marker_byte_position (stream);
        }
    }
  return -1;
}

void detach_all_extents (Lisp_Object object);
Lisp_Object extent_at (Bytexpos position, Lisp_Object object,
		       Lisp_Object property, EXTENT before,
		       enum extent_at_flag at_flag, int all_extents);

typedef int (*map_extents_fun) (EXTENT extent, void *arg);

void map_extents (Bytexpos from, Bytexpos to, map_extents_fun fn,
		  void *arg, Lisp_Object obj, EXTENT after,
		  unsigned int flags);


struct extent_fragment *extent_fragment_new (Lisp_Object buffer_or_string,
					     struct frame *frm);
face_index extent_fragment_update (struct window *w,
				   struct extent_fragment *ef,
				   Bytexpos pos, Lisp_Object last_glyph);
void extent_fragment_delete (struct extent_fragment *ef);

/* from alloc.c */
struct extent *allocate_extent (void);

void attach_extent_auxiliary (EXTENT ext);
void uninit_object_extents (Lisp_Object);

#ifdef ERROR_CHECK_EXTENTS
void sledgehammer_extent_check (Lisp_Object obj);
#endif

#ifdef MEMORY_USAGE_STATS
Bytecount compute_buffer_extent_usage (struct buffer *b);
#endif

#endif /* INCLUDED_extents_h_ */
