home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / gnu / lucid / lemacs-19.6 / src / extents.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-13  |  86.9 KB  |  3,119 lines

  1. /* This file is part of GNU Emacs.
  2.  
  3. GNU Emacs is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 1, or (at your option)
  6. any later version.
  7.  
  8. GNU Emacs is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11. GNU General Public License for more details.
  12.  
  13. You should have received a copy of the GNU General Public License
  14. along with GNU Emacs; see the file COPYING.  If not, write to
  15. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  16.  
  17. #include "config.h"
  18. #include "lisp.h"
  19. #include "buffer.h" 
  20. #include "process.h"
  21.  
  22. #include "xterm.h"     /* for struct x_bitmap in set_extent_glyph_1() */
  23.  
  24. #include "extents.h"
  25. #include "faces.h"
  26. #include "hash.h"
  27.  
  28. #ifdef ENERGIZE
  29. #include <editorreq.h>
  30. #include <X11/Intrinsic.h> /* for "Boolean" typedef, believe it or not... */
  31. #include "extents-data.h"
  32. #endif
  33.  
  34. /************** Typedefs and Structs ***********************/
  35.  
  36. struct slow_map_extents_arg
  37. {
  38.   Lisp_Object map_arg;
  39.   Lisp_Object map_routine;
  40. };
  41.  
  42. struct replicate_extents_struct
  43. {
  44.   int from;
  45.   int length;
  46.   struct buffer *buf;
  47.   Lisp_Object head;
  48.   Lisp_Object nconc_cell;
  49. };
  50.  
  51. /* not used at the moment */   
  52. struct process_extents_for_insertion_struct
  53. {
  54.   int opoint;
  55.   int length;
  56.   struct buffer *buf;
  57. };
  58.    
  59. struct process_extents_for_deletion_struct
  60. {
  61.   int start;
  62.   int end;
  63.   int destroy_included_extents;
  64. };
  65.  
  66. struct extent_at_struct
  67. {
  68.   EXTENT best_match;
  69.   int flag;
  70. };
  71.  
  72.  
  73. /************** Functions ***********************/
  74. extern DUP make_extent_replica (void);
  75.  
  76. /*extern Lisp_Object list_sort 
  77. (Lisp_Object list, Lisp_Object lisp_arg, 
  78.  int (*pred_fn)(Lisp_Object x, Lisp_Object y, Lisp_Object arg));*/
  79.  
  80. void map_extents (int from, int to, elisp_emf efn, emf fn, void *arg, 
  81.                   struct buffer *buf, int closed_end);
  82.  
  83. static void soe_push (EXTENT extent, struct buffer *b);
  84. static void soe_delq (EXTENT extent, struct buffer *b);
  85. static void soe_clear (struct buffer *b);
  86.  
  87. void init_buffer_cached_stack (struct buffer *b);
  88. void free_buffer_cached_stack (struct buffer *b);
  89.  
  90. static EXTENT_FRAGMENT befa_internal (int pos, struct buffer *buf);
  91. EXTENT_FRAGMENT buffer_extent_fragment_at (int pos, struct buffer *buf,
  92.                                            struct screen *s);
  93.  
  94. static void add_to_replicas_lists (c_hashtable table, Lisp_Object dup_list, 
  95.                                    int offset, int length);
  96.  
  97.  
  98. /************** Macros ***********************/
  99.  
  100. #define max(A,B) ((A) > (B) ? (A) : (B))
  101. #define min(A,B) ((A) <= (B) ? (A) : (B))
  102.  
  103. #define MAX_INT ((long) 0x7fffffff)
  104.    
  105. #define BUFNAME(buf) &(XSTRING(buf->name)->data[0])
  106. #define SYMNAME(sym) &(XSYMBOL(sym)->name->data[0])
  107.  
  108. /* if buf is the one in the cache, invalidate the cache -- used in
  109.    places where changes to extents list occur that might not affect 
  110.    the buffer modiff */
  111. #define CHECK_RESET_EXTENT_FRAGMENT(x) \
  112. {if (((char *) extent_fragment.buf) == ((char *)(x))) \
  113.   {extent_fragment.buf = 0; Vextent_fragment_buffer = Qnil;}}
  114.  
  115. #define EXTENT_LESS_VALS(e,st,nd) (((e)->start < (st)) || \
  116.                    (((e)->start == (st)) && \
  117.                    ((e)->end > (nd))))
  118.  
  119. #define EXTENT_LESS(e,x) EXTENT_LESS_VALS(e, (x)->start, (x)->end)
  120.  
  121. #define EXTENT_LESS_EQ(e,x) (((e)->start < (x)->start) || \
  122.                  (((e)->start == (x)->start) && \
  123.                  ((e)->end >= (x)->end)))
  124.  
  125. #define EXTENT_E_LESS_VALS(e,st,nd) (((e)->end < (nd)) || \
  126.                      (((e)->end == (nd)) && \
  127.                      ((e)->start < (st))))
  128.  
  129. #define EXTENT_E_LESS(e,x) EXTENT_E_LESS_VALS(e,(x)->start,(x)->end)
  130.  
  131. #define EXTENT_OVER_INDEX(e,i) ((((e)->start <= (i)) && ((e)->end > (i))) || \
  132.                 (((e)->start == (i)) && ((e)->end == (i))))
  133.   
  134. #define EXTENT_PAST_INDEX(e,i) (((e)->end > (i)) || \
  135.                 ((((e)->start == (i)) && ((e)->end == (i)))))
  136.  
  137. /************** Variables ***********************/
  138.  
  139. Lisp_Object Vlast_highlighted_extent;
  140.  
  141. static Lisp_Object Vextent_fragment_buffer;
  142. static struct extent_fragment extent_fragment;
  143. static struct extent_fragment default_extent_fragment;
  144.  
  145. int extent_cache_invalid;    /* set this to force a recomputation */
  146.  
  147.  
  148.  
  149. /*********************************
  150.   EXTENTS.C INTERNAL UTILITIES
  151.   *******************************/
  152.  
  153. static void
  154. check_from_to (int from, int to, struct buffer* buf)
  155.   if ((from < BUF_BEG (buf)) || (from > BUF_Z (buf))) 
  156.     error ("Bad buffer position %d for buffer %s", 
  157.            from, BUFNAME(buf)); 
  158.   if ((to < BUF_BEG (buf)) || (to > BUF_Z (buf))) 
  159.     error ("Bad buffer position %d for buffer %s", 
  160.        to, BUFNAME(buf));
  161.  
  162. static int
  163. adjust_extent_index (int i, int from, int to, int amount)
  164. {
  165.   /* Some sanity checking */
  166.   if (amount > 0)
  167.     {
  168.       if (i > to && i < to + amount)
  169.     abort ();
  170.     }
  171.   else 
  172.     {
  173.       if (i > from + amount && i < from)
  174.     abort ();
  175.     }
  176.  
  177.   if (i >= from && i <= to)
  178.     i += amount;
  179.  
  180.   return i;
  181. }
  182.  
  183. static int
  184. extent_index_to_buffer_pos (int i, struct buffer *buf)
  185. {
  186.   if (i > BUF_GPT (buf) + BUF_GAP_SIZE (buf))
  187.     i -= BUF_GAP_SIZE (buf);
  188.   else if (i > BUF_GPT (buf))
  189.     i = BUF_GPT (buf);
  190.  
  191.   if ((i < BUF_BEG (buf)) || (i > BUF_Z (buf)))
  192.     abort();
  193.   else
  194.     return i;
  195. }
  196.  
  197. static int
  198. buffer_pos_to_extent_index (int pos, struct buffer *buf)
  199. {
  200.   if ((pos < BUF_BEG (buf)) || (pos > BUF_Z (buf)))
  201.     abort();
  202.   else if (pos <= BUF_GPT (buf))
  203.     return pos;
  204.   else 
  205.     return (pos + BUF_GAP_SIZE (buf));
  206. }
  207.  
  208. static int
  209. extent_index_offset (int index, int offset, struct buffer *buf)
  210. {
  211.   int pos = extent_index_to_buffer_pos (index, buf);
  212.   return buffer_pos_to_extent_index (pos + offset, buf);
  213. }
  214.  
  215. static EXTENT 
  216. buffer_starting_extent (int index, struct buffer *buf)
  217. {
  218.   struct stack_of_extents *soe = buf->cached_stack;
  219.   EXTENT first_extent = NULL;
  220.   EXTENT ext;
  221.   int i;
  222.  
  223.   /* no extents on the buffer */
  224.   if (!EXTENTP (buf->extents))
  225.     return NULL;
  226.   
  227.   first_extent = XEXTENT (buf->extents);
  228.  
  229.   /* no cache or cache not valid */
  230.   if (!soe || soe->buf_index <= 0)
  231.     return first_extent;
  232.  
  233.   /* index is after the cached values */
  234.   if (index >= soe->buf_index)
  235.     {
  236.       ext = NULL;
  237.       for (i = 0; i < soe->stack_index; i++)
  238.     if (soe->stack [i]->end > index)
  239.       {
  240.         ext = soe->stack [i];
  241.         break;
  242.       }
  243.       if (!ext)
  244.     ext = soe->previous_extent;
  245.       return ext ? ext : first_extent;
  246.     }
  247.  
  248.   /* index is before the cached values */
  249.  
  250.   /* The extent which is before the first one in the 
  251.      cache is a good starting point for backing up
  252.      previous extent. */
  253.   if (soe->stack_index)
  254.     ext = soe->stack [0];
  255.   else
  256.     /* if there is nothing in the cache the previous extent
  257.        can be used */
  258.     ext = soe->previous_extent;
  259.  
  260.   /* no previous extent in the cache */
  261.   if (!ext)
  262.     return first_extent;
  263.     
  264.   /* previous is closer to index than to the beginning of the buffer */
  265.   if ((ext->end / 2) < index)
  266.     {
  267.       EXTENT starting_one = ext;
  268.  
  269.       while (ext && ext->end >= index)
  270.     {
  271.           ext = ext->e_previous;
  272.           if (ext && ext->start < starting_one->start)
  273.         starting_one = ext;
  274.         }
  275.       starting_one = starting_one->previous;
  276.       return (ext && starting_one) ? starting_one : first_extent;
  277.     }
  278.  
  279.   /* default */
  280.   return first_extent;
  281. }
  282.  
  283.  
  284. void
  285. adjust_extents (int from, int to, int amount, struct buffer* buf)
  286. {
  287.   EXTENT current;
  288.  
  289.   if (NILP (buf->extents))
  290.     return;
  291.   else if (!EXTENTP (buf->extents))
  292.     abort ();
  293.  
  294.   current = buffer_starting_extent (from, buf);
  295.   
  296.   CHECK_RESET_EXTENT_FRAGMENT (buf);
  297.   
  298.   while (current)
  299.     {
  300.       if (current->end < from)
  301.     ;
  302.       else if (current->start <= to)
  303.     {
  304.       current->start = adjust_extent_index (current->start, from, to,
  305.                         amount);
  306.       if (current->end <= to)
  307.         current->end = adjust_extent_index (current->end, from, to,
  308.                         amount);
  309.     }
  310.       else 
  311.     break;
  312.       
  313.       if (current == current->next) abort ();
  314.       current = current->next;
  315.     }
  316.   
  317.   if (buf->cached_stack
  318.       && buf->cached_stack->buf_index > 0
  319.       && buf->cached_stack->buf_index > from
  320.       && buf->cached_stack->buf_index <= to)
  321.     buf->cached_stack->buf_index += amount;
  322. }
  323.  
  324. struct end_points
  325. {
  326.   int start;
  327.   int end;
  328. };
  329.  
  330. static int
  331. verify_extent_mf (EXTENT extent, void *arg)
  332. {
  333.   struct end_points* ep = (struct end_points*)arg;
  334.   
  335.   if ((EXTENT_FLAGS(extent) & EF_WRITE_PROTECT)
  336.       && (extent->end > ep->start)
  337.       && (extent->start <= ep->end))
  338.     {
  339.       error ("Attempt to modify a read-only region");
  340.       return 1;
  341.     }
  342.   else
  343.     return 0;
  344. }
  345.  
  346. #ifdef ENERGIZE
  347. extern int inside_parse_buffer; /* total kludge */
  348. #endif
  349.  
  350. void
  351. verify_extent_modification (struct buffer *buf, int from, int to)
  352. {
  353.   struct end_points ep;
  354.  
  355.   check_from_to (from, to, buf);
  356.   ep.start = buffer_pos_to_extent_index (from, buf);
  357.   ep.end = buffer_pos_to_extent_index (to, buf);
  358.  
  359.   if (inside_undo ||
  360. #ifdef ENERGIZE
  361.       inside_parse_buffer ||
  362. #endif
  363.       NILP (buf->extents))
  364.     return;
  365.   else if (!EXTENTP (buf->extents))
  366.     abort();
  367.   else
  368.     map_extents (from, to, 0, verify_extent_mf, (void*)&ep, buf, 0);
  369. }
  370.  
  371. /* At the moment only this function, buffer_extent_fragment_at(), 
  372.    update_cache_forward(), map_extents() and adjust_extents (),
  373.    know how to "cdr" down a list of extents. 
  374.    See the comment at map_extents() for information 
  375.    about the ordering rule. */
  376. static void 
  377. splice_extent_into_buffer (EXTENT extent, Lisp_Object buffer)
  378. {
  379.   Lisp_Object extents_root;
  380.   Lisp_Object extent_obj;
  381.   struct buffer *buf = XBUFFER(buffer);
  382.  
  383.   CHECK_BUFFER (buffer, 0);  
  384.   CHECK_RESET_EXTENT_FRAGMENT (buf);
  385.    
  386.   XSET (extent_obj, Lisp_Extent, extent);
  387.  
  388.   init_buffer_cached_stack (buf);
  389.  
  390.   extents_root = buf->extents;
  391.  
  392.   if (NILP (extents_root))
  393.     buf->extents = extent_obj;
  394.   else if (!EXTENTP (extents_root))
  395.     abort();
  396.   else
  397.     {
  398.       int start = extent->start;
  399.       int end = extent->end;
  400.       EXTENT tmp = buffer_starting_extent (start, buf);
  401.       EXTENT prev = (tmp ? tmp->previous : 0);
  402.  
  403.       while (tmp && EXTENT_LESS_VALS (tmp, start, end))
  404.         {
  405.           prev = tmp;
  406.           tmp = tmp->next;
  407.       if (prev == tmp) abort ();
  408.         }
  409.  
  410.       if (!tmp && !prev)
  411.         abort();
  412.  
  413.       if (prev)
  414.         { 
  415.           EXTENT caboose = prev->next;
  416.       if (extent == prev) abort ();
  417.       if (extent == caboose) abort ();
  418.           prev->next = extent; 
  419.           extent->previous = prev; 
  420.           extent->next = caboose; 
  421.           if (caboose)
  422.             caboose->previous = extent;
  423.         }
  424.       else 
  425.         {
  426.           EXTENT engine = tmp->previous;
  427.           if (engine)
  428.             engine->next = tmp;
  429.       if (extent == tmp) abort ();
  430.           extent->previous = engine; 
  431.           extent->next = tmp; 
  432.           tmp->previous = extent; 
  433.  
  434.       buf->extents = extent_obj;
  435.         }
  436.  
  437.       if (!tmp)        /* one of these exists; pick one */
  438.         tmp = prev;
  439.  
  440.       /* if tmp (some arbitrary extent in the middle of nowhere but likely
  441.      to be close to where we want to be) is before the extents we want
  442.      to insert between (in e order) then go forward
  443.        */
  444.       if (EXTENT_E_LESS_VALS (tmp, start, end))
  445.     {
  446.       prev = tmp->e_previous;
  447.       while (tmp && EXTENT_E_LESS_VALS (tmp, start, end))
  448.         {
  449.           prev = tmp;
  450.           tmp = tmp->e_next;
  451.           if (prev == tmp) abort ();
  452.         }
  453.     }
  454.       else    /* go backward */
  455.         {
  456.           prev = tmp;
  457.       while (prev && !EXTENT_E_LESS_VALS (prev, start, end))
  458.             {
  459.           /* we always go into this loop at least once */
  460.               tmp = prev;
  461.               prev = tmp->e_previous;
  462.             }
  463.       if (prev == tmp) abort ();
  464.         }
  465.  
  466.       if (!tmp && !prev)
  467.         abort();
  468.  
  469.       if (prev)
  470.         { 
  471.           EXTENT caboose = prev->e_next;
  472.       if (extent == prev) abort ();
  473.       if (extent == caboose) abort ();
  474.           prev->e_next = extent; 
  475.           extent->e_previous = prev; 
  476.           extent->e_next = caboose; 
  477.           if (caboose)
  478.             caboose->e_previous = extent;
  479.         }
  480.       else 
  481.         {
  482.           EXTENT engine = tmp->e_previous;
  483.           if (engine)
  484.             engine->e_next = tmp;
  485.       if (extent == tmp) abort ();
  486.           extent->e_previous = engine; 
  487.           extent->e_next = tmp; 
  488.           tmp->e_previous = extent; 
  489.         }
  490.     }
  491.  
  492.   soe_push (extent, buf);
  493.   CLEAR_EXTENT_FLAG (extent, EF_DETACHED);
  494. }
  495.  
  496. static void set_extent_flags (EXTENT extent);
  497. static void set_extent_attributes_index (EXTENT extent);
  498.  
  499. static void
  500. restore_extent_state (EXTENT extent)
  501. {
  502.   set_extent_flags (extent);
  503.   set_extent_attributes_index (extent);
  504. }
  505.  
  506. static Lisp_Object
  507. make_extent_internal (int from, int to, Lisp_Object buffer, void *data)
  508. {
  509.   EXTENT extent;
  510.   Lisp_Object extent_obj = Qnil;
  511.   struct buffer *buf = XBUFFER (buffer);
  512.  
  513.   CHECK_BUFFER (buffer, 0);  
  514.   check_from_to (from, to, buf);
  515.    
  516.   if ((from < 0) || (to < from))
  517.     error ("START == %d, END == %d -- bad start/end for extent",
  518.            from, to);
  519.  
  520.   if (NILP (buf->name))
  521.     error ("Can't put an extent in a killed buffer");
  522.  
  523.   if ((from < BUF_BEG(buf)) || (to > BUF_Z(buf)))
  524.     error ("START == %d, END == %d -- bad start/end for extent in buffer %s",
  525.            from, to, BUFNAME(buf));
  526.     
  527.   extent = make_extent();
  528.   XSET(extent_obj, Lisp_Extent, extent);
  529.  
  530.   extent->buffer = buffer;
  531.   extent->flags = 0;
  532.   extent->priority = 0;
  533.  
  534. #ifdef ENERGIZE
  535.   if (data)
  536.     {
  537.       Energize_Extent_Data *ext = (Energize_Extent_Data *) data;
  538.       set_energize_extent_data (extent, data);
  539.       if (ext->extent)
  540.     abort ();
  541.       ext->extent = extent_obj;
  542.     }
  543. #endif
  544.  
  545.   extent->start = buffer_pos_to_extent_index (from, buf);
  546.   extent->end = buffer_pos_to_extent_index (to, buf);
  547.  
  548.   splice_extent_into_buffer (extent, buffer);
  549.  
  550.   restore_extent_state (extent);
  551.   return extent_obj;
  552. }
  553.  
  554.  
  555. static int 
  556. extent_endpoint (EXTENT extent, int endp)
  557. {
  558.   int i = (endp)?(extent->end):(extent->start);
  559.   if (EXTENT_DESTROYED_P (extent))
  560.     return -1;
  561.   else if (EXTENT_DETACHED_P (extent))
  562.     return 0;
  563.   else if (BUFFERP (extent->buffer))
  564.     return extent_index_to_buffer_pos (i, XBUFFER(extent->buffer));
  565.   else
  566.     return i;
  567. }
  568.  
  569. static void
  570. set_extent_flags (EXTENT extent)
  571. {
  572. #ifdef ENERGIZE
  573.   Energize_Extent_Data *ext = energize_extent_data (extent);
  574. #endif
  575.  
  576.   /* clear every flag except the EF_DETACHED flag */
  577.   if (EXTENT_DESTROYED_P (extent))
  578.     return;
  579.   else if (EXTENT_DETACHED_P (extent))
  580.     extent->flags = EF_DETACHED;
  581.   else
  582.     extent->flags = 0;
  583.  
  584. #ifdef ENERGIZE
  585.   if (ext)
  586.     {
  587.       switch (ext->extentType)
  588.     {
  589.     case CEAttribute:
  590.       break;
  591.  
  592.     case CEAbbreviation:
  593.       break;
  594.  
  595.     case CEWriteProtect:
  596.       SET_EXTENT_FLAG (extent, EF_WRITE_PROTECT);
  597.       break;
  598.           
  599.     case CEGeneric:
  600.       if (ext->u.generic.gData->id)
  601.         SET_EXTENT_FLAG (extent, EF_MENU);
  602.       if (ext->u.generic.gData->glyph)
  603.         {
  604.           SET_EXTENT_FLAG (extent, EF_END_GLYPH);
  605.           extent->end_glyph = ext->u.generic.gData->glyph;
  606.           BUF_FACECHANGE (XBUFFER (extent->buffer))++;
  607.         }
  608.       if (ext->u.generic.gData->cl && ext->u.generic.gData->cl->glyph)
  609.         {
  610.           SET_EXTENT_FLAG (extent, EF_START_GLYPH);
  611.           extent->begin_glyph = ext->u.generic.gData->cl->glyph;
  612.           BUF_FACECHANGE (XBUFFER (extent->buffer))++;
  613.         }
  614.       if (ext->u.generic.gData->cl && 
  615.           (ext->u.generic.gData->cl->flags & CCElectric))
  616.         SET_EXTENT_FLAG (extent, EF_HIGHLIGHT);
  617.       if (ext->u.generic.gData->cl && 
  618.           (ext->u.generic.gData->cl->flags & CCWarnModified))
  619.         SET_EXTENT_FLAG (extent, EF_WARN_MODIFY);
  620.       if (ext->u.generic.gData->cl && 
  621.           (ext->u.generic.gData->cl->flags & CCColumn))
  622.         SET_EXTENT_FLAG (extent, EF_COLUMN);
  623.       SET_EXTENT_FLAG (extent, EF_DUPLICABLE);
  624.       break;
  625.           
  626.     default:
  627.       break;
  628.     }
  629.     }
  630. #endif /* ENERGIZE */
  631. }
  632.  
  633. static void
  634. set_extent_attributes_index (EXTENT extent)
  635. {
  636. #ifdef ENERGIZE
  637.   Energize_Extent_Data *ext = energize_extent_data (extent);
  638.   int graphic_attributes;
  639.  
  640.   if (!ext) 
  641.     extent->attr_index = -1;
  642.   else
  643.     {
  644.       extern Lisp_Object Venergize_attributes_mapping;
  645.       Lisp_Object face;
  646.  
  647.       switch (ext->extentType)
  648.         {
  649.         case CEAttribute:
  650.           graphic_attributes = ext->u.attr.attrValue;
  651.           break;
  652.       
  653.         case CEGeneric:
  654.           graphic_attributes = ext->u.generic.gData->attribute;
  655.           break;
  656.       
  657.         case CEWriteProtect:
  658.           /* this type has NO display attributes */
  659.           extent->attr_index = -1;
  660.           return;
  661.       
  662.         default:
  663.           graphic_attributes = GA_NO_CHANGE;
  664.         }
  665.   
  666.       if (graphic_attributes >= GA_MAX) 
  667.         graphic_attributes = GA_NO_CHANGE;
  668.  
  669.       /* The Venergize_attributes_mapping global is an A-list of the form
  670.      ((<kernel attribute number> <attribute name> . <emacs face id>)..)
  671.      It is initialized by connect-to-energize in energize-init.el. */
  672.       if (CONSP (Venergize_attributes_mapping))
  673.     {
  674.       face = Fassq (graphic_attributes, Venergize_attributes_mapping);
  675.       if (CONSP (face))
  676.         {
  677.           face = XCONS(face)->cdr;
  678.           if (CONSP (face))
  679.         {
  680.           face = XCONS(face)->cdr;
  681.           if (FIXNUMP (face))
  682.             graphic_attributes = XINT (face);
  683.         }
  684.         }
  685.     }
  686.       extent->attr_index = graphic_attributes;
  687.     }
  688. #else /* ! ENERGIZE */
  689.   extent->attr_index = -1;
  690. #endif /* ! ENERGIZE */
  691.   return;
  692. }
  693.  
  694. #ifdef ENERGIZE
  695. extern unsigned long generic_id_for_extent (Energize_Extent_Data *);
  696.  
  697. static unsigned long
  698. extent_to_generic_id (Lisp_Object extent_obj)
  699. {
  700.   if (!EXTENTP (extent_obj)) 
  701.     return 0;
  702.   else 
  703.     {
  704.       Energize_Extent_Data *ext =
  705.     energize_extent_data (XEXTENT (extent_obj));
  706.       return generic_id_for_extent (ext);
  707.     }
  708. }
  709. #endif /* ENERGIZE */
  710.  
  711.  
  712. /*********************************
  713.   EXTENTS.C EXTERNAL UTILITIES
  714.   *******************************/
  715.  
  716. void 
  717. detach_extent (EXTENT extent) 
  718.   EXTENT prev = extent->previous; 
  719.   EXTENT next = extent->next; 
  720.   EXTENT e_prev = extent->e_previous; 
  721.   EXTENT e_next = extent->e_next; 
  722.   struct buffer *buf = XBUFFER(extent->buffer);
  723.   Lisp_Object obj_extent = buf->extents;
  724.  
  725.   CHECK_RESET_EXTENT_FRAGMENT (buf);
  726.  
  727.   soe_delq (extent, buf);
  728.  
  729.   if (XEXTENT (obj_extent) == extent)
  730.     {
  731.       if (next)
  732.         XSET (obj_extent, Lisp_Extent, next);
  733.       else
  734.         obj_extent = Qnil;
  735.       
  736.       XBUFFER (extent->buffer)->extents = obj_extent;
  737.     }
  738.  
  739.   if (prev) 
  740.     {
  741.       prev->next = next; 
  742.       extent->previous = 0;
  743.     }
  744.   if (next) 
  745.     {
  746.       next->previous = prev; 
  747.       extent->next = 0; 
  748.     }
  749.  
  750.  
  751.   if (e_prev) 
  752.     {
  753.       if (e_next == e_prev) abort ();
  754.       e_prev->e_next = e_next; 
  755.       extent->e_previous = 0;
  756.     }
  757.   if (e_next) 
  758.     {
  759.       if (e_next == e_prev) abort ();
  760.       e_next->e_previous = e_prev; 
  761.       extent->e_next = 0; 
  762.     }
  763.  
  764.   SET_EXTENT_FLAG (extent, EF_DETACHED);
  765.  
  766.   extent->start = 0;
  767.   extent->end = 0;
  768. }
  769.  
  770. #ifdef ENERGIZE
  771. extern void energize_extent_finalization (EXTENT);
  772. #endif
  773.  
  774. static void 
  775. destroy_extent (EXTENT extent) 
  776.   detach_extent (extent);
  777. #ifdef ENERGIZE
  778.   energize_extent_finalization (extent);
  779. #endif
  780.   extent->flags = EF_DESTROYED;
  781.   extent->start = 0;
  782.   extent->end = 0;
  783.   extent->next = 0;
  784.   extent->previous = 0;
  785.   extent->e_next = 0;
  786.   extent->e_previous = 0;
  787.   extent->user_data = Qnil;
  788.   extent->attr_index = 0;
  789.   extent->buffer = Qnil;
  790. }
  791.  
  792. static void   
  793. update_extent (EXTENT extent, int from, int to, int set_endpoints,
  794.            struct buffer *buf)
  795. {
  796.   if ((!BUFFERP (extent->buffer)) ||
  797.       (XBUFFER(extent->buffer) != buf))
  798.     error ("extent 0x%x not part of specified buffer %s", extent, 
  799.            BUFNAME (buf));
  800.  
  801.   if (set_endpoints)
  802.     {
  803.       check_from_to (from, to, buf);
  804.       
  805.       /* most of the time the extent doesn't need to be changed -- the
  806.      big problem is that the kernel actually doesn't know what is going
  807.      all too often */
  808.       if ((from < to) && ((EXTENT_FLAGS (extent) & EF_DETACHED) ||
  809.               (extent_endpoint (extent, 0) != from) ||
  810.               (extent_endpoint (extent, 1) != to)))
  811.     {
  812.       int new_start = buffer_pos_to_extent_index (from, buf);
  813.       int new_end = buffer_pos_to_extent_index (to, buf);
  814.       Lisp_Object buffer;
  815.       XSET (buffer, Lisp_Buffer, buf);
  816.       
  817.       detach_extent (extent);
  818.       extent->start = new_start;
  819.       extent->end = new_end;
  820.       splice_extent_into_buffer (extent, buffer);
  821.     }
  822.     }
  823.  
  824.   restore_extent_state (extent);
  825.   return;
  826. }
  827.  
  828. #ifdef ENERGIZE
  829.  
  830. /* creates a new extent or update an old one for ext in binfo and returns it */
  831. Lisp_Object
  832. make_extent_for_data (BufferInfo *binfo, Energize_Extent_Data *ext,
  833.               int from, int to, int set_endpoints)
  834. {
  835.   Lisp_Object extent_obj;
  836.   Lisp_Object buffer = binfo->emacs_buffer;
  837.   struct buffer *b = XBUFFER (buffer);
  838.   
  839.   to = min (to, BUF_Z (b));
  840.   from = min (from, to);
  841.   
  842.   if (extent_obj = ext->extent)
  843.     update_extent (XEXTENT (extent_obj), from, to, set_endpoints,
  844.            XBUFFER (buffer));
  845.   else
  846.     extent_obj = make_extent_internal (from, to, buffer, ext);
  847.   
  848.   SET_EXTENT_FLAG (XEXTENT (extent_obj), EF_DUPLICABLE);
  849.  
  850.   return extent_obj;
  851. }
  852.  
  853. #endif /* ENERGIZE */
  854.  
  855.  
  856. /*********************************
  857.   EXTENTS.C MAPPING FUNCTIONS
  858.   *******************************/
  859.  
  860.  
  861. /* Apply a function to each extent overlapping [from, to) (or [from, to],
  862.    if the closed_end arg is non-zero) in buffer. If the function ever
  863.    returns a non-zero value, quit immediately.  At the moment only this
  864.    function, buffer_extent_fragment_at(), update_cache_forward(), 
  865.    adjust_extents () and splice_extent_into_buffer() 
  866.    knows how to "cdr" down a list of extents.
  867.    Extents are ordered with increasing start position and then decreasing
  868.    end position. (This is what might be called "display order" -- if extent
  869.    A occurs after extent B, then the display attributes of extent A
  870.    override those of extent B in the region covered by both A and B. Note
  871.    that multiple extents with the same start and end postions may be in any
  872.    order.) Part of this comment is duplicated at update_cache_forward().*/
  873. void
  874. map_extents 
  875. (int from, int to, elisp_emf efn, emf fn, void *arg, struct buffer *buf, 
  876.  int closed_end)
  877. {
  878.   Lisp_Object extents_root = buf->extents;
  879.   int start;
  880.   int end;
  881.  
  882.   if ((from > to) || (NILP (extents_root)))
  883.     return;
  884.   
  885.   /* making an error here is wrong as this can be called from within
  886.      * make_gap () during which the buffer state is incoherent, ie the new
  887.      * GPT is already set but the new Z is not. 
  888.      * This is a little scary, maybe the function that updates the
  889.      * extents when the gap is moved should not call map_extents. 
  890.      * --Matthieu. */
  891.   /* check_from_to(from, to, buf); */
  892.   /* We silently return if mapping out of the buffer valid positions */
  893.   if ((from < BUF_BEG (buf)) || (from > BUF_Z (buf))
  894.       || (to < BUF_BEG (buf)) || (to > BUF_Z (buf)))
  895.     return;
  896.  
  897.   start = buffer_pos_to_extent_index (from, buf);
  898.   if (closed_end)
  899.     {
  900.       if (to == BUF_Z(buf))
  901.         end = buffer_pos_to_extent_index (to, buf) + 1;
  902.       else
  903.         end = buffer_pos_to_extent_index (to + 1, buf);
  904.     }
  905.   else
  906.     end = buffer_pos_to_extent_index (to, buf);
  907.  
  908.   if (!EXTENTP (extents_root))
  909.     abort();
  910.   else 
  911.     {
  912.       EXTENT tmp = buffer_starting_extent (start, buf);
  913.       EXTENT next;
  914.  
  915.       if (efn)
  916.         while (tmp)
  917.           {
  918.             /* this lets the map function be delete_extent, too */
  919.             next = tmp->next;
  920.         if (next == tmp) abort ();
  921.             if (tmp->end < start)
  922.               tmp = next;
  923.             else if (tmp->start < end)
  924.               {
  925.                 Lisp_Object tmp_obj;
  926.                 XSET (tmp_obj, Lisp_Extent, tmp);
  927.                 if ((*efn)(tmp_obj, arg))
  928.                   return;
  929.                 tmp = next; 
  930.               }
  931.             else 
  932.               return;
  933.           }
  934.       else
  935.         while (tmp)
  936.           {
  937.             /* this lets the map function be delete_extent, too */
  938.             next = tmp->next;
  939.         if (next == tmp) abort ();
  940.             if (tmp->end < start)
  941.               tmp = next;
  942.             else if (tmp->start < end)
  943.               {
  944.                 if ((*fn)(tmp, arg))
  945.                   return;
  946.               }
  947.             else 
  948.               return;
  949.    
  950.             tmp = next;
  951.           }
  952.     }
  953.   return;
  954. }
  955.  
  956. static int
  957. slow_map_extents_function (Lisp_Object extent_obj, void *arg)
  958. {
  959.   struct slow_map_extents_arg *slow_arg =
  960.     (struct slow_map_extents_arg *) arg;
  961.   if (NILP (call2 (slow_arg->map_routine, extent_obj, slow_arg->map_arg)))
  962.     return 0;
  963.   else
  964.     return 1;
  965. }
  966.  
  967. DEFUN ("map-extents", Fmap_extents, Smap_extents, 1, 6, 0,
  968.        "Usage: (map-extents FUNCTION BUFFER FROM TO MAPARG) \n\
  969. Map FUNCTION over the extents which overlap region in BUFFER starting at\n\
  970.  FROM and ending at TO.  FUNCTION is called with arguments (extent, MAPARG).\n\
  971. All arguments except FUNCTION are optional, with FROM, TO, MAPARG, and\n\
  972.  BUFFER defaulting to the beginning of BUFFER, the end of BUFFER, NIL, and\n\
  973.  current buffer, respectively.\n\
  974. If the function returns non-nil, then map-extents returns immediately.\n\
  975. map-extents always returns nil.")
  976.   (function, buffer, from, to, maparg, closed_end)
  977.   Lisp_Object function, buffer, from, to, maparg, closed_end;
  978. {
  979.   elisp_emf map_funct;
  980.   int closed;
  981.   
  982.   if (!NILP (closed_end))
  983.     closed = 1;
  984.   else 
  985.     closed = 0;
  986.  
  987.   if (NILP (buffer)) XSET (buffer, Lisp_Buffer, current_buffer);
  988.   CHECK_BUFFER (buffer, 0);
  989.   
  990.  
  991.   if (NILP (from)) XSET (from, Lisp_Int, BUF_BEG (XBUFFER (buffer)));
  992.   if (NILP (to)) XSET (to, Lisp_Int, BUF_Z (XBUFFER (buffer)));
  993.   CHECK_FIXNUM (from, 1);
  994.   CHECK_FIXNUM (to, 2);
  995.   check_from_to (XINT(from), XINT(to), (XBUFFER (buffer)));
  996.   if (XINT(from) > XINT (to))
  997.     error ("MAP-EXTENTS args FROM (== %d) and TO (== %d) are inconsistent.",
  998.            XINT (from), XINT (to));
  999.   
  1000.   if (SUBRP (function))
  1001.     {
  1002.       map_funct = (elisp_emf) XSUBR (function)->function;
  1003.       map_extents (XINT (from), XINT (to), map_funct, 0,
  1004.                    (void *)maparg, XBUFFER(buffer), closed);
  1005.     }
  1006.   else
  1007.     {
  1008.       struct slow_map_extents_arg sma_space;
  1009.       sma_space.map_arg = maparg;
  1010.       sma_space.map_routine = function;
  1011.       map_funct = slow_map_extents_function;
  1012.       map_extents 
  1013.         (XINT (from), XINT (to), map_funct, 0, (void *) &sma_space, 
  1014.          XBUFFER(buffer), closed);
  1015.     }
  1016.   
  1017.   return Qnil;
  1018. }
  1019.  
  1020.  
  1021. /*********************************
  1022.   EXTENTS.C GRAPHICAL DISPLAY
  1023.   *******************************/
  1024. static int
  1025. extent_highlightable_p (Lisp_Object extent_obj)
  1026. {
  1027.  return (EXTENTP (extent_obj) && 
  1028.          (EXTENT_FLAGS (XEXTENT (extent_obj)) & EF_HIGHLIGHT));
  1029. }
  1030.  
  1031. /* The display code looks into the Vlast_highlighted_extent variable to 
  1032.    correctly display highlighted extents. NOTE: When we have extents
  1033.    that are either open or closed at either end, we will need to
  1034.    figure out the endpoints of the call to redisplay_no_change() 
  1035.    accordingly. */
  1036. static Lisp_Object
  1037. do_highlight (Lisp_Object extent_obj, int flag)
  1038. {
  1039.   if (((Vlast_highlighted_extent == extent_obj) && !NILP(flag)) ||
  1040.       (NILP (Vlast_highlighted_extent) && NILP (flag)))
  1041.     return Qnil;
  1042.   else
  1043.     {
  1044.       Lisp_Object old_parent = 
  1045.         (EXTENTP (Vlast_highlighted_extent))?
  1046.           (XEXTENT(Vlast_highlighted_extent)->buffer):Qnil;
  1047.       Lisp_Object new_parent = 
  1048.         (EXTENTP (extent_obj))?(XEXTENT(extent_obj)->buffer):Qnil;
  1049.  
  1050.       if (BUFFERP (old_parent))
  1051.         {
  1052.           Vlast_highlighted_extent = Qnil;
  1053.           BUF_FACECHANGE (XBUFFER (old_parent))++;
  1054.           windows_or_buffers_changed++;
  1055.         }
  1056.  
  1057.       if ((BUFFERP (new_parent)) &&
  1058.           !NILP (flag))
  1059.         {
  1060.           Vlast_highlighted_extent = extent_obj;
  1061.           BUF_FACECHANGE (XBUFFER (new_parent))++;
  1062.           windows_or_buffers_changed++;
  1063.         }
  1064.       else
  1065.         Vlast_highlighted_extent = Qnil;
  1066.     }
  1067.   return Qnil;
  1068. }
  1069.  
  1070. DEFUN ("highlight-extent", Fhighlight_extent, Shighlight_extent, 1, 2, 0,
  1071.  "If EXTENT is `highlightable' (has the 'highlight property) then highlight\n\
  1072. it (by using merging it with 'highlight face.)  If FLAG is nil, then\n\
  1073. unhighlight it instead.")
  1074.      (extent_obj, flag)
  1075.      Lisp_Object extent_obj, flag;
  1076. {
  1077.   if (NILP (extent_obj))
  1078.     return do_highlight (Qnil, Qnil);
  1079.   else if (!extent_highlightable_p (extent_obj))
  1080.     return Qnil;
  1081.   else
  1082.     return do_highlight (extent_obj, flag);
  1083. }
  1084.  
  1085.  
  1086. DEFUN ("force-highlight-extent", Fforce_highlight_extent, 
  1087.        Sforce_highlight_extent, 1, 2, 0,
  1088.  "Highlight any EXTENT if FLAG is not nil, else unhighlight it.\n\
  1089. This is the same as `highlight-extent', except that it will work even\n\
  1090. on extents without the 'highlight property.")
  1091.      (extent_obj, flag)
  1092.      Lisp_Object extent_obj, flag;
  1093. {
  1094.   if (NILP (extent_obj))
  1095.     return do_highlight (Qnil, Qnil);
  1096.   else if (!EXTENTP (extent_obj))
  1097.     return Qnil;
  1098.   else
  1099.     return do_highlight (extent_obj, flag);
  1100. }
  1101.  
  1102.  
  1103. /*********************************
  1104.   EXTENTS.C DATATYPE FUNCTIONS
  1105.   *******************************/
  1106.  
  1107. GLYPH
  1108. extent_glyph_at (EXTENT extent, int pos, int endp)
  1109. {
  1110.   if (! extent)
  1111.     return 0;
  1112.   else if (! BUFFERP (extent->buffer))
  1113.     return 0;
  1114.   else if (endp && pos == (extent_endpoint (extent, 1) - 1))
  1115.     return extent->end_glyph;
  1116.   else if (!endp && pos == extent_endpoint (extent, 0))
  1117.     return extent->begin_glyph;
  1118.   else
  1119.     return 0;
  1120. }
  1121.  
  1122. DEFUN ("extent-start-position", Fextent_start_position, 
  1123.        Sextent_start_position, 1, 1, 0,
  1124.        "Return start position of EXTENT.")
  1125.      (extent_obj)
  1126.      Lisp_Object extent_obj;
  1127. {
  1128.   CHECK_EXTENT (extent_obj, 0);
  1129.   return make_number (extent_endpoint (XEXTENT(extent_obj), 0));
  1130. }
  1131.  
  1132.  
  1133. DEFUN ("extent-end-position", Fextent_end_position, 
  1134.        Sextent_end_position, 1, 1, 0,
  1135.        "Return first position after EXTENT.")
  1136.      (extent_obj)
  1137.      Lisp_Object extent_obj;
  1138. {
  1139.   CHECK_EXTENT (extent_obj, 0);
  1140.   return make_number (extent_endpoint (XEXTENT(extent_obj), 1));
  1141. }
  1142.  
  1143. DEFUN ("extent-length", Fextent_length, Sextent_length, 1, 1, 0,
  1144.        "Return length of EXTENT in characters.")
  1145.      (extent_obj)
  1146.      Lisp_Object extent_obj;
  1147. {
  1148.   CHECK_EXTENT (extent_obj, 0);
  1149.   return make_number (extent_endpoint (XEXTENT(extent_obj), 1) - 
  1150.                       extent_endpoint (XEXTENT(extent_obj), 0));
  1151. }
  1152.  
  1153. DEFUN ("extent-buffer", Fextent_buffer, Sextent_buffer, 1, 1, 0,
  1154.        "Return buffer of EXTENT.")
  1155.      (extent_obj)
  1156.      Lisp_Object extent_obj;
  1157. {
  1158.   CHECK_EXTENT (extent_obj, 0);
  1159.   return (XEXTENT(extent_obj)->buffer);
  1160. }
  1161.  
  1162.  
  1163. #ifdef ENERGIZE 
  1164.  
  1165. DEFUN ("extent-to-generic-id", Fextent_to_generic_id, Sextent_to_generic_id,
  1166.        1, 1, 0, "Return Energize ID of buffer of EXTENT.")
  1167.      (extent_obj)
  1168.      Lisp_Object extent_obj;
  1169. {
  1170.   unsigned long gid;
  1171.   extern Lisp_Object word_to_lisp ();
  1172.   CHECK_EXTENT (extent_obj, 0);
  1173.   gid = extent_to_generic_id (extent_obj);
  1174.   return word_to_lisp (gid);
  1175. }
  1176.  
  1177. #endif
  1178.  
  1179.  
  1180. /*********************************
  1181.   EXTENTS.C FLAGS INFO
  1182.   *******************************/
  1183.  
  1184. /* Does this extent have a lineinfo-column glyph */   
  1185. int
  1186. glyph_in_column_p (Lisp_Object extent_obj)
  1187. {
  1188.   CHECK_EXTENT (extent_obj, 0);
  1189.   return !!(EXTENT_FLAGS(XEXTENT(extent_obj)) & EF_COLUMN);
  1190. }
  1191.  
  1192. /* This is the only place `PT' is an lvalue in all of emacs. */
  1193.  
  1194. static void
  1195. set_point_internal (charno)
  1196.      int charno;
  1197. {
  1198.   point = charno;
  1199.   if (charno > GPT)
  1200.     charno += GAP_SIZE;
  1201.   XMARKER (current_buffer->point_marker)->bufpos = charno;
  1202. }
  1203.  
  1204. void
  1205. set_point (position)
  1206.      int position;
  1207. {
  1208.   int opoint = point;
  1209.  
  1210.   if (position == opoint)
  1211.     return;
  1212.   else if (position > Z)
  1213.     abort();
  1214.  
  1215.   if (position > ZV || position < BEGV)
  1216.     abort ();
  1217.  
  1218.   set_point_internal (position);
  1219.  
  1220.   if (!current_buffer->extents)
  1221.     abort();
  1222.  
  1223.   /* NOTE: We used to run "class hooks" at this point, and we
  1224.      will want to run extent hooks here in the future, both for
  1225.      point-entered and point-exited. */
  1226. }
  1227.  
  1228. void
  1229. set_buffer_point (buffer, position)
  1230.      struct buffer *buffer;
  1231.      int position;
  1232. {
  1233.   if (buffer == current_buffer)
  1234.     set_point (position);
  1235.   else
  1236.     {
  1237.       int count = specpdl_depth;
  1238.       record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
  1239.       internal_set_buffer (buffer);
  1240.       set_point (position);
  1241.       unbind_to (count, Qnil);
  1242.     }
  1243. }
  1244.  
  1245. /* Don't have invisible extents at the moment */
  1246. int
  1247. last_visible_position (int opoint, struct buffer *buf)
  1248. {
  1249.   return opoint;
  1250. }
  1251.  
  1252. static int
  1253. extent_at_mf (EXTENT extent, void *arg)
  1254. {
  1255.   struct extent_at_struct *eas_ptr = (struct extent_at_struct *) arg;
  1256.  
  1257.   if ((eas_ptr->flag == 0) || (EXTENT_FLAGS (extent) & eas_ptr->flag))
  1258.     {
  1259.       EXTENT current = eas_ptr->best_match;
  1260.  
  1261.       if (!current)
  1262.         eas_ptr->best_match = extent;
  1263.       else if (current->start > extent->start)
  1264.         return 0;
  1265.       /* we return the "last" best fit, instead of the first --
  1266.      this is because then the glyph closest to two equivalent
  1267.      extents corresponds to the "extent-at" the text just past
  1268.      that same glyph */
  1269.       else if (EXTENT_LESS_EQ (current, extent))
  1270.         eas_ptr->best_match = extent;
  1271.     }
  1272.  
  1273.   return 0;
  1274. }
  1275.  
  1276. /* find "smallest" matching extent containing pos -- (flag == 0) means 
  1277.    all extents match, else (EXTENT_FLAGS (extent) & flag) must be true;
  1278.    for more than one matching extent with precisely the same endpoints,
  1279.    we choose the last extent in the extents_list */
  1280. EXTENT
  1281. extent_at (int pos, struct buffer *buf, int flag)
  1282. {
  1283.   if (NILP (buf->extents))
  1284.     return 0;
  1285.   else if (!EXTENTP (buf->extents))
  1286.     abort();
  1287.   else
  1288.     {
  1289.       struct extent_at_struct eas;
  1290.       eas.best_match = 0;
  1291.       eas.flag = flag;
  1292.       
  1293.       map_extents (pos, pos, 0, extent_at_mf, (void *) &eas, buf, 1);
  1294.       return eas.best_match;
  1295.     }
  1296. }
  1297.  
  1298. DEFUN ("make-extent", Fmake_extent, Smake_extent, 2, 3, 0,
  1299.        "Make extent for range [FROM, TO) in BUFFER -- BUFFER defaults to \n\
  1300. current buffer.  Insertions at point TO will be outside of the extent;\n\
  1301. insertions at FROM will be inside the extent (and the extent will grow.)")
  1302.   (from, to, buffer)
  1303.    Lisp_Object from, to, buffer;
  1304. {
  1305.   Lisp_Object extent_obj;
  1306.   CHECK_FIXNUM (from, 0);
  1307.   CHECK_FIXNUM (to, 0);
  1308.   if (NILP (buffer))
  1309.     XSET (buffer, Lisp_Buffer, current_buffer);
  1310.   CHECK_BUFFER (buffer, 0);
  1311.   extent_obj = make_extent_internal (XINT(from), XINT(to), buffer, 0);
  1312.   return extent_obj;
  1313. }
  1314.  
  1315. DEFUN ("delete-extent", Fdelete_extent, Sdelete_extent, 1, 1, 0,
  1316.  "Remove EXTENT from its buffer; this does not modify the buffer's text,\n\
  1317. only its display properties.")
  1318.   (extent_obj)
  1319.    Lisp_Object extent_obj;
  1320. {
  1321.   EXTENT extent;
  1322.  
  1323.   CHECK_EXTENT (extent_obj, 0);
  1324.   extent = XEXTENT (extent_obj);
  1325.  
  1326.   if (NILP (XBUFFER (extent->buffer)->name))
  1327.     error ("Deleting extent in killed buffer");
  1328.  
  1329.   BUF_FACECHANGE (XBUFFER (extent->buffer))++;
  1330.   windows_or_buffers_changed++;
  1331.   destroy_extent (extent);
  1332.   return Qnil;
  1333. }
  1334.  
  1335. DEFUN ("update-extent", Fupdate_extent, Supdate_extent, 3, 3, 0,
  1336.        "Set the endpoints of EXTENT to START, END.")
  1337.   (extent_obj, start, end)
  1338.    Lisp_Object extent_obj, start, end;
  1339. {
  1340.   EXTENT extent = XEXTENT (extent_obj);
  1341.   int from = XINT (start);
  1342.   int to = XINT (end);
  1343.  
  1344.   CHECK_EXTENT (extent_obj, 0);
  1345.   CHECK_FIXNUM (start, 1);
  1346.   CHECK_FIXNUM (end, 2);
  1347.  
  1348.   if (!BUFFERP (extent->buffer)
  1349.       || NILP (XBUFFER (extent->buffer)->name))
  1350.     error ("EXTENT arg to UPDATE-EXTENT doesn't belong to a buffer");
  1351.  
  1352.   check_from_to (from, to, XBUFFER (extent->buffer));
  1353.       
  1354.   if (from > to)
  1355.     error ("Bad START (== %d) and END (== %d) args to UPDATE-EXTENT", from, to);
  1356.  
  1357.   detach_extent (extent);
  1358.   extent->start = buffer_pos_to_extent_index (from, XBUFFER (extent->buffer));
  1359.   extent->end = buffer_pos_to_extent_index (to, XBUFFER (extent->buffer));
  1360.   splice_extent_into_buffer (extent, extent->buffer);
  1361.  
  1362.   BUF_FACECHANGE (XBUFFER (extent->buffer))++;
  1363.   windows_or_buffers_changed++;
  1364.  
  1365.   return extent_obj;
  1366. }
  1367.  
  1368.  
  1369. DEFUN ("set-extent-attribute", Fset_extent_attribute, 
  1370.        Sset_extent_attribute, 2, 2, 0,
  1371.  "Make EXTENT have ATTRIBUTE.\n\
  1372. ATTRIBUTE must be one of the following symbols:\n\
  1373. \n\
  1374.     highlight        highlight when the mouse moves over it\n\
  1375.     write-protected    text within this extent will be unmodifyable\n\
  1376.     invisible        don't display the text in this region\n\
  1377.     unhighlight        turn off `highlight'\n\
  1378.     writable        turn off `write-protected'\n\
  1379.     visible        turn off `invisible'")
  1380.   (extent_obj, attr)
  1381.    Lisp_Object extent_obj, attr;
  1382. {
  1383.   EXTENT extent = XEXTENT (extent_obj);
  1384.  
  1385.   CHECK_EXTENT (extent_obj, 0);
  1386.   
  1387.   if (!BUFFERP (extent->buffer)
  1388.       || NILP (XBUFFER (extent->buffer)->name))
  1389.     error ("EXTENT arg to SET-EXTENT-ATTRIBUTE doesn't belong to a buffer");
  1390.  
  1391.   if (FIXNUMP (attr))
  1392.     {
  1393.       int attr_num = XINT (attr);
  1394.       if (attr_num < 0)
  1395.         attr_num = -1;
  1396.       else if (attr_num >= GA_MAX) 
  1397.         attr_num = GA_NO_CHANGE;
  1398.       extent->attr_index = attr_num;
  1399.     }
  1400.   else if (SYMBOLP (attr))
  1401.     {
  1402.       if (EQ (intern ("highlight"), attr))
  1403.         { SET_EXTENT_FLAG (extent, EF_HIGHLIGHT); }
  1404.       else if (EQ (intern ("unhighlight"), attr))
  1405.         { CLEAR_EXTENT_FLAG (extent, EF_HIGHLIGHT); }
  1406.       else if (EQ (intern ("write-protected"), attr))
  1407.         { SET_EXTENT_FLAG (extent, EF_WRITE_PROTECT); }
  1408.       else if (EQ (intern ("writable"), attr))
  1409.         { CLEAR_EXTENT_FLAG (extent, EF_WRITE_PROTECT); }
  1410.       else if (EQ (intern ("invisible"), attr))
  1411.         { SET_EXTENT_FLAG (extent, EF_INVISIBLE); }
  1412.       else if (EQ (intern ("visible"), attr))
  1413.         { CLEAR_EXTENT_FLAG (extent, EF_INVISIBLE); }
  1414.       else if (EQ (intern ("duplicable"), attr))
  1415.         { SET_EXTENT_FLAG (extent, EF_DUPLICABLE); }
  1416.       else if (EQ (intern ("non-duplicable"), attr))
  1417.         { CLEAR_EXTENT_FLAG (extent, EF_DUPLICABLE); }
  1418.       else
  1419.         error ("Unknown attribute argument, %s, to set-extent-attribute.", 
  1420.                SYMNAME (attr));
  1421.     }
  1422.   else
  1423.     error ("Unknown type of attribute argument to SET-EXTENT-ATTRIBUTE.");
  1424.  
  1425.   BUF_FACECHANGE (XBUFFER (extent->buffer))++;
  1426.   windows_or_buffers_changed++;
  1427.  
  1428.   return extent_obj;
  1429. }
  1430.  
  1431.  
  1432. DEFUN ("extent-attributes", Fextent_attributes, Sextent_attributes, 1, 2, 0,
  1433.  "Return a list of attributes of EXTENT.\n\
  1434. This list may contain any or none of the following symbols:\n\
  1435. \n\
  1436.     highlight        highlight when the mouse moves over it\n\
  1437.     write-protected    text within this extent will be unmodifyable\n\
  1438.     invisible        don't display the text in this region\n\
  1439.     begin-glyph        there is a begin-glyph\n\
  1440.     end-glyph        there is an end-glyph\n\
  1441.     detached        the text around the extent has been deleted\
  1442. ")
  1443.   (extent_obj, raw_p)
  1444.    Lisp_Object extent_obj, raw_p;
  1445. {
  1446.   Lisp_Object result = Qnil;
  1447.   EXTENT extent = XEXTENT (extent_obj);
  1448.   CHECK_EXTENT (extent_obj, 0);
  1449.  
  1450.   if (!NILP (raw_p))
  1451.     return make_number (extent->attr_index);
  1452.  
  1453.   if (EXTENT_FLAG_P (extent, EF_HIGHLIGHT))
  1454.     result = Fcons (intern ("highlight"), result);
  1455.   if (EXTENT_FLAG_P (extent, EF_WRITE_PROTECT))
  1456.     result = Fcons (intern ("write-protected"), result);
  1457.   if (EXTENT_FLAG_P (extent, EF_INVISIBLE))
  1458.     result = Fcons (intern ("invisible"), result);
  1459.   if (EXTENT_FLAG_P (extent, EF_START_GLYPH))
  1460.     result = Fcons (intern ("begin-glyph"), result);
  1461.   if (EXTENT_FLAG_P (extent, EF_END_GLYPH))
  1462.     result = Fcons (intern ("end-glyph"), result);
  1463.   if (EXTENT_FLAG_P (extent, EF_MENU))
  1464.     result = Fcons (intern ("menu"), result);
  1465.   if (EXTENT_FLAG_P (extent, EF_START_OPEN))
  1466.     result = Fcons (intern ("start-open"), result);
  1467.   if (EXTENT_FLAG_P (extent, EF_END_OPEN))
  1468.     result = Fcons (intern ("end-open"), result);
  1469.   if (EXTENT_FLAG_P (extent, EF_COLUMN))
  1470.     result = Fcons (intern ("column"), result);
  1471.   if (EXTENT_FLAG_P (extent, EF_DETACHED))
  1472.     result = Fcons (intern ("detached"), result);
  1473.   if (EXTENT_FLAG_P (extent, EF_WARN_MODIFY))
  1474.     result = Fcons (intern ("warn-modify"), result);
  1475.   if (!EXTENT_FLAG_P (extent, EF_DUPLICABLE))
  1476.     result = Fcons (intern ("non-duplicable"), result);
  1477.   return result;
  1478. }
  1479.  
  1480.  
  1481. extern struct x_pixmap *x_get_pixmap (Lisp_Object, char *hash_suffix);
  1482.  
  1483. static void
  1484. set_extent_glyph_1 (Lisp_Object extent_obj, Lisp_Object glyph, int endp)
  1485. {
  1486.   int change_p;
  1487.   int which = (endp ? EF_END_GLYPH : EF_START_GLYPH);
  1488.   EXTENT extent = XEXTENT (extent_obj);
  1489.   CHECK_EXTENT (extent_obj, 0);
  1490.   
  1491.   if (!BUFFERP (extent->buffer)
  1492.       || NILP (XBUFFER (extent->buffer)->name))
  1493.     error ("extent doesn't belong to a buffer");
  1494.  
  1495.   if (NILP (glyph))
  1496.     {
  1497.       change_p = !EXTENT_FLAG_P (extent, which);
  1498.       CLEAR_EXTENT_FLAG (extent, which);
  1499.       if (endp)
  1500.     extent->end_glyph = 0;
  1501.       else
  1502.     extent->begin_glyph = 0;
  1503.     }
  1504.   else
  1505.     {
  1506.       struct x_pixmap *p;
  1507.       CHECK_STRING (glyph, 0);
  1508.       p = x_get_pixmap (glyph, 0);
  1509.       change_p = (!EXTENT_FLAG_P (extent, which) ||
  1510.           extent->begin_glyph != p->glyph_id);
  1511.       SET_EXTENT_FLAG (extent, which);
  1512.       if (endp)
  1513.     extent->end_glyph = p->glyph_id;
  1514.       else
  1515.     extent->begin_glyph = p->glyph_id;
  1516.     }
  1517.   if (change_p)
  1518.     {
  1519.       BUF_FACECHANGE (XBUFFER (extent->buffer))++;
  1520.       windows_or_buffers_changed++;
  1521.     }
  1522. }
  1523.  
  1524. DEFUN ("set-extent-begin-glyph", Fset_extent_begin_glyph, 
  1525.        Sset_extent_begin_glyph, 2, 2, 0,
  1526.  "Display a bitmap at the beginning of the given extent.\n\
  1527. The begin-glyph should be a string naming a bitmap file (or nil.)")
  1528.   (extent_obj, begin_glyph)
  1529.    Lisp_Object extent_obj, begin_glyph;
  1530. {
  1531.   set_extent_glyph_1 (extent_obj, begin_glyph, 0);
  1532.   return extent_obj;
  1533. }
  1534.  
  1535.  
  1536. DEFUN ("set-extent-end-glyph", Fset_extent_end_glyph, 
  1537.        Sset_extent_end_glyph, 2, 2, 0,
  1538.  "Display a bitmap at the end of the given extent.\n\
  1539. The end-glyph should be a string naming a bitmap file (or nil.)")
  1540.   (extent_obj, end_glyph)
  1541.    Lisp_Object extent_obj, end_glyph;
  1542. {
  1543.   set_extent_glyph_1 (extent_obj, end_glyph, 1);
  1544.   return extent_obj;
  1545. }
  1546.  
  1547.  
  1548. DEFUN ("extent-data", Fextent_data, Sextent_data, 1, 1, 0,
  1549.  "Return the user data associated with the given extent.\n\
  1550. Set this using the `set-extent-data' function.")
  1551.     (extent)
  1552.     Lisp_Object extent;
  1553. {
  1554.   CHECK_EXTENT (extent, 0);
  1555.   return XEXTENT (extent)->user_data;
  1556. }
  1557.  
  1558. DEFUN ("set-extent-data", Fset_extent_data, Sset_extent_data, 2, 2, 0,
  1559.  "Set the user data slot of the given extent.\n\
  1560. Access this using the `extent-data' function.")
  1561.     (extent, data)
  1562.     Lisp_Object extent, data;
  1563. {
  1564.   CHECK_EXTENT (extent, 0);
  1565. #ifdef ENERGIZE
  1566.   if (energize_extent_data (XEXTENT (extent)))
  1567.     error ("thou shalt not change the user-data of Energize extents");
  1568. #endif
  1569.   XEXTENT (extent)->user_data = data;
  1570.   return data;
  1571. }
  1572.  
  1573. DEFUN ("extent-priority", Fextent_priority, Sextent_priority, 1, 1, 0,
  1574.   "Returns the display priority of EXTENT; see `set-extent-priority'.")
  1575.      (extent)
  1576.      Lisp_Object extent;
  1577. {
  1578.   CHECK_EXTENT (extent, 0);
  1579.   return make_number (XEXTENT (extent)->priority);
  1580. }
  1581.  
  1582. DEFUN ("set-extent-priority", Fset_extent_priority, Sset_extent_priority,
  1583.        2, 2, 0,
  1584.   "Changes the display priority of EXTENT.\n\
  1585. When the extent attributes are being merged for display, the priority\n\
  1586. is used to determine which extent takes precedence in the event of a\n\
  1587. conflict (two extents whose faces both specify font, for example: the\n\
  1588. font of the extent with the higher priority will be used.)\n\
  1589. Extents are created with priority 0; priorities may be negative.")
  1590.     (extent, pri)
  1591.     Lisp_Object extent, pri;
  1592. {
  1593.   int p;
  1594.   CHECK_EXTENT (extent, 0);
  1595.   CHECK_FIXNUM (pri, 0);
  1596.   p = XINT (pri);
  1597.   if (p < -0x8000 || p > 0x7fff)    /* must fit in a short */
  1598.     error ("extent priority out of range");
  1599.   XEXTENT (extent)->priority = p;
  1600.   return pri;
  1601. }
  1602.  
  1603. DEFUN ("extent-at", Fextent_at, Sextent_at, 1, 3, 0,
  1604.        "Find \"smallest\" extent at POS in BUFFER having FLAG set.  BUFFER\n\
  1605. defaults to the current buffer, FLAG defaults to nil, meaning that any\n\
  1606. extent will do. Possible values for FLAG are nil, 'menu, 'highlight,\n\
  1607. 'invisible, and 'write-protected. Returns nil if there is no matching\n\
  1608. extent at POS.")
  1609.   (pos, buffer, flag)
  1610.    Lisp_Object pos, buffer, flag;
  1611. {
  1612.   int position;
  1613.   int flag_to_check = 0;
  1614.   Lisp_Object extent_obj = Qnil;
  1615.   EXTENT extent;
  1616.  
  1617.   if (NILP (buffer))
  1618.     XSET (buffer, Lisp_Buffer, current_buffer);
  1619.  
  1620.   CHECK_FIXNUM_COERCE_MARKER (pos, 0);
  1621.   CHECK_BUFFER (buffer, 1);
  1622.   position = XINT (pos);
  1623.   check_from_to (position, position, XBUFFER (buffer));
  1624.  
  1625.   if (!NILP (flag))
  1626.     {
  1627.       CHECK_SYMBOL (flag, 2);
  1628.  
  1629.       if (EQ (intern ("menu"), flag))
  1630.         flag_to_check = EF_MENU;
  1631.       else if (EQ (intern ("highlight"), flag))
  1632.         flag_to_check = EF_HIGHLIGHT;
  1633.       else if (EQ (intern ("write-protected"), flag))
  1634.         flag_to_check = EF_WRITE_PROTECT;
  1635.       else if (EQ (intern ("start-glyph"), flag))
  1636.         flag_to_check = EF_START_GLYPH;
  1637.       else if (EQ (intern ("end-glyph"), flag))
  1638.         flag_to_check = EF_END_GLYPH;
  1639.       else if (EQ (intern ("invisible"), flag))
  1640.         flag_to_check = EF_INVISIBLE;
  1641.       else if (EQ (intern ("duplicable"), flag))
  1642.         flag_to_check = EF_DUPLICABLE;
  1643.       else
  1644.         error ("%s is unknown flag argument for extent-at", SYMNAME (flag));
  1645.     }
  1646.  
  1647.   if (extent = extent_at (position, XBUFFER (buffer), flag_to_check))
  1648.     XSET (extent_obj, Lisp_Extent, extent);
  1649.  
  1650.   return extent_obj;
  1651. }
  1652.  
  1653. DEFUN ("next-extent", Fnext_extent, Snext_extent, 1, 1, 0,
  1654.        "Find next extent after EXTENT. If EXTENT is a buffer\n\
  1655. return the first extent in the buffer.")
  1656.   (extent_obj)
  1657.    Lisp_Object extent_obj;
  1658. {
  1659.   if (BUFFERP (extent_obj))
  1660.     return XBUFFER (extent_obj)->extents;
  1661.   else if (EXTENTP (extent_obj))
  1662.     {
  1663.       Lisp_Object return_val = Qnil;
  1664.       EXTENT next = XEXTENT(extent_obj)->next;
  1665.  
  1666.       if (next == XEXTENT (extent_obj)) abort ();
  1667.       if (next)
  1668.         XSET (return_val, Lisp_Extent, next);
  1669.       return return_val;
  1670.     }
  1671.   else
  1672.     return Qnil;
  1673. }
  1674.  
  1675. #if 0
  1676.  
  1677. /* There are 2 total orders on extents in a buffer -- the normal
  1678.    (or "display") order, and the "e-order". This returns the
  1679.    "next extent" in the e-ordering.  This might be a temporary function
  1680.    or it might be permanent. */
  1681.  
  1682. DEFUN ("next-e-extent", Fnext_e_extent, Snext_e_extent, 1, 1, 0,
  1683.        "Find next extent after EXTENT using the \"e\" order. If \n\
  1684. EXTENT is a buffer, return the first extent in the buffer.")
  1685.   (extent_obj)
  1686.    Lisp_Object extent_obj;
  1687. {
  1688.   if (BUFFERP (extent_obj))
  1689.     {
  1690.       Lisp_Object return_val;
  1691.       EXTENT tmp;
  1692.  
  1693.       if (EXTENTP (XBUFFER (extent_obj)->extents))
  1694.         tmp = XEXTENT (XBUFFER (extent_obj)->extents);
  1695.       else
  1696.         return Qnil;
  1697.  
  1698.       while (tmp->e_previous)
  1699.         tmp = tmp->e_previous;
  1700.  
  1701.       XSET (return_val, Lisp_Extent, tmp);
  1702.       return return_val;
  1703.     }
  1704.   else if (EXTENTP (extent_obj))
  1705.     {
  1706.       Lisp_Object return_val = Qnil;
  1707.       EXTENT next = XEXTENT(extent_obj)->e_next;
  1708.  
  1709.       if (next)
  1710.         XSET (return_val, Lisp_Extent, next);
  1711.       return return_val;
  1712.     }
  1713.   else
  1714.     return Qnil;
  1715. }
  1716.  
  1717.  
  1718. /* Purportedly temporary debugging function -- turns a stack of
  1719.    extents into something that can be looked at in elisp. For
  1720.    a detailed explanation of a stack of extents, see below. */
  1721.  
  1722. static Lisp_Object
  1723. soe_to_lisp (struct stack_of_extents *soe, struct buffer *buf)
  1724. {
  1725.   if (!soe || 
  1726.       (soe->buf_index <= 0))
  1727.     return Qnil;
  1728.   else
  1729.     {
  1730.       Lisp_Object struct_vec = Fmake_vector (make_number (6), 
  1731.                                              make_number (0));
  1732.       Lisp_Object *struct_v = &(XVECTOR (struct_vec)->contents[0]);
  1733.       Lisp_Object stack_vec = Fmake_vector (make_number (soe->stack_index),
  1734.                                             make_number (0));
  1735.       Lisp_Object *stack_v = &(XVECTOR (stack_vec)->contents[0]);
  1736.  
  1737.       struct_v[0] = intern (":PRIOR-EXTENT");
  1738.       if (soe->previous_extent)
  1739.         XSET(struct_v[1], Lisp_Extent, soe->previous_extent);
  1740.       else
  1741.         struct_v[1] = Qnil;
  1742.     
  1743.       struct_v[2] = intern (":BUFFER-POS");
  1744.       XSET(struct_v[3], Lisp_Int, 
  1745.            extent_index_to_buffer_pos (soe->buf_index, buf));
  1746.     
  1747.       struct_v[4] = intern (":STACK");
  1748.       struct_v[5] = stack_vec;
  1749.  
  1750.       {
  1751.         int i;
  1752.       
  1753.         for (i = 0; i < soe->stack_index; i++)
  1754.           {
  1755.             EXTENT tmp = soe->stack[i];
  1756.  
  1757.             if (tmp)
  1758.               {
  1759.                 XSET(stack_v[i], Lisp_Extent, tmp);
  1760.               }
  1761.             else 
  1762.               stack_v[i] = Qnil;
  1763.           }
  1764.       }
  1765.  
  1766.       return struct_vec;
  1767.     }
  1768. }
  1769.  
  1770. /* Elisp interface for debugging stacks of extents */
  1771. DEFUN ("stack-of-extents", Fstack_of_extents, 
  1772.        Sstack_of_extents, 1, 2, 0,
  1773.        "Return stack of extents for BUFFER. Optional arg POSITION supplied\n\
  1774. means compute the correct stack of extents for POSITION in BUFFER.")
  1775.   (buffer, position)
  1776.    Lisp_Object buffer, position;
  1777. {
  1778.   Lisp_Object return_value = Qnil;
  1779.   struct stack_of_extents *soe;
  1780.   struct buffer *buf = XBUFFER (buffer);
  1781.   CHECK_BUFFER (buffer, 0);
  1782.   if (!NILP (position))
  1783.     {
  1784.       struct stack_of_extents *tmp = buf->cached_stack;
  1785.       int pos;
  1786.       CHECK_FIXNUM (position, 1);
  1787.       pos = XINT (position);
  1788.       if ((pos < BUF_BEG(buf)) || (BUF_Z (buf) < pos))
  1789.         error ("Bad position %d for buffer %s", pos, BUFNAME (buf));
  1790.       
  1791.       buf->cached_stack = 0;
  1792.       init_buffer_cached_stack (buf);
  1793.       befa_internal (pos, buf);
  1794.       soe = buf->cached_stack;
  1795.       buf->cached_stack = tmp;
  1796.     }
  1797.   else
  1798.     soe = buf->cached_stack;
  1799.       
  1800.   if (!soe)
  1801.     return Qnil;
  1802.   else
  1803.     return_value = soe_to_lisp (soe, buf);
  1804.   
  1805.   if (soe && (soe != buf->cached_stack))
  1806.     {
  1807.       EXTENT *tmp_stack = soe->stack;
  1808.       soe->stack = 0;
  1809.       if (tmp_stack)
  1810.         free (tmp_stack);
  1811.       free (soe);
  1812.     }
  1813.  
  1814.   return return_value;
  1815. }
  1816.  
  1817. #endif
  1818.  
  1819. /* Debugging and test function -- maybe permanent. */
  1820. /* Return 0 if stack is correct, 1 if stack has been cleared (which
  1821.    is not incorrect but isn't good news), and -1 if it is provably
  1822.    incorrect. */
  1823. #if 0
  1824. int verify_buffer_stack (struct buffer *buf)
  1825. {
  1826.   struct stack_of_extents *soe;
  1827.  
  1828.   if (!buf)
  1829.     buf = current_buffer;
  1830.  
  1831.   soe = buf->cached_stack;
  1832.  
  1833.   if (!soe)
  1834.     {
  1835.       if (EXTENTP (buf->extents))
  1836.         return -1;
  1837.       else if (buf->extents == Qnil)
  1838.         return 0;
  1839.       else
  1840.         abort ();
  1841.     }
  1842.   else if (soe->buf_index <= 0)
  1843.     return 1;
  1844.   else
  1845.     {
  1846.       int pos = extent_index_to_buffer_pos (soe->buf_index, buf);
  1847.       int return_value;
  1848.       buf->cached_stack = 0;
  1849.       init_buffer_cached_stack (buf);
  1850.       befa_internal (pos, buf);
  1851.       
  1852.       return_value = memcmp ((char *) soe, (char *) buf->cached_stack,
  1853.                  sizeof (*soe));
  1854.       if (!return_value)
  1855.         return_value = 
  1856.           memcmp ((char *) soe->stack, (char *) buf->cached_stack->stack, 
  1857.           soe->stack_index * sizeof (EXTENT));
  1858.       if (return_value)
  1859.         return_value = -1;
  1860.       free_buffer_cached_stack (buf);
  1861.       buf->cached_stack = soe;
  1862.       return return_value;
  1863.     }
  1864. }
  1865. #endif
  1866.  
  1867. /* Long comment: 
  1868.  
  1869.    A "Stack Of Extents" (abbreviated SOE) is a data structure that is
  1870.    an abbreviated version of an extent_fragment.  However, unlike the
  1871.    extent_fragment, of which there are really only 2, which are used
  1872.    by redisplay, and which are supposed to be FAST to manage, every
  1873.    buffer with extents has an SOE, these are supposed to be robust,
  1874.    and they don't have to be that fast to manage. What an SOE does is
  1875.    cache the information needed to try to find, given a buffer index
  1876.    I, some extent E which is "before" I in the display order (meaning
  1877.    that E doesn't include I, and any extent E' that does include I is
  1878.    "greater than" E in the display order). The purpose of this is to
  1879.    make functions like Fextent_at() and buffer_extent_fragment_at() be
  1880.    as fast at the bottom of a buffer as they are at the top, no matter
  1881.    how many extents the buffer has. (We may want to consider having
  1882.    detach_extent() and splice_extent_into_buffer() update the SOE,
  1883.    too, so that updating extents will be faster and adding extents "in
  1884.    order" will be as fast as adding them in "reverse order" is.)
  1885.  
  1886.    The two orderings of extents in a buffer, normal (or display) order
  1887.    and e-order, are defined by macros at the top of the file.
  1888.    Basically, though, normal order sorts by increasing start index and
  1889.    e-order by increasing end index.
  1890.  
  1891.    The components of an SOE are the buffer index, the vector of
  1892.    extents (in display order) that lie over that index, and the
  1893.    "previous extent", which is the last extent in the e-order whose
  1894.    end index is <= the given buffer index and which is NOT over the
  1895.    buffer index (if the extent has 0 length, it will be over the index
  1896.    if the start and end values equal the index).
  1897.  
  1898.    An SOE is "cleared" or invalidated iff the buffer index value is <=
  1899.    0, since this is never a legal buffer index -- this clearing is
  1900.    done by soe_clear(), and is called any time the SOE can't get
  1901.    updated properly. 
  1902.  
  1903.    Each time an extent is spliced into the buffer, an attempt is made
  1904.    to "push" it onto the SOE (which means that we examine the new
  1905.    extent to see if it goes over that buffer index or if it should
  1906.    replace the previous extent).  When an extent is detached, we
  1907.    similarly attempt to delq it from the SOE.
  1908.  
  1909.    Any call to the function befa_internal() changes the SOE to use the
  1910.    new buffer index via soe_duplicate(). The function
  1911.    process_extents_for_deletion() may change the endpoints of extents,
  1912.    of adjust the buffer index, so it calls soe_prune(). This function
  1913.    removes any extents that are not over the buffer index, and
  1914.    corrects the previous extent value.
  1915.  
  1916.    There are also init and free functions for the SOE, called by
  1917.    splice_extent_into_buffer() and Fkill_buffer, respectively.
  1918.  
  1919.  
  1920.  
  1921.    Finally, what's the point of all of this? The point is that given
  1922.    an index I, the set S of extents over I, and the previous extent P,
  1923.    it is possible to compute an extent before an index I' (before in
  1924.    the display order). If I' >= I, this is just P (which can be easily
  1925.    recomputed from S[0] if S exists and P does not -- see
  1926.    soe_prune()).  If I' < I, then consider the interval [E, P] of
  1927.    extents in the e-order such that E is the first extent with end
  1928.    index less than I'. Then the minimum (in the normal order) E' of
  1929.    these extents is either strictly before I' or is the "top of the
  1930.    stack at" I', and in the latter case, E'->previous is before I'.
  1931.  
  1932.    The proof is left as an exercise for the readers.
  1933.  */
  1934.  
  1935. static void soe_push (EXTENT extent, struct buffer *b)
  1936. {
  1937.   struct stack_of_extents *soe = b->cached_stack;
  1938.   if (soe)
  1939.     {
  1940.       int index = soe->buf_index;
  1941.       int on_stack = 0;
  1942.  
  1943.       if (index <= 0)
  1944.     {
  1945.       soe_clear(b);
  1946.       return;
  1947.     }
  1948.       else if (EXTENT_OVER_INDEX (extent, index))
  1949.     on_stack = 1;
  1950.  
  1951.       if (on_stack)
  1952.     {
  1953.       if (soe->stack_index == soe->stack_length)
  1954.         {
  1955.           soe->stack_length *= 2;
  1956.           soe->stack = 
  1957.         (EXTENT*)xrealloc (soe->stack, 
  1958.                    soe->stack_length * sizeof (EXTENT));
  1959.         }
  1960.  
  1961.       if (soe->stack_index == 0)
  1962.         {
  1963.           soe->stack[0] = extent;
  1964.           soe->stack_index = 1;
  1965.         }
  1966.       else
  1967.         {
  1968.           EXTENT *cef, *cef_bound, *cef_copy, *cef_put_here;
  1969.  
  1970.           /* make sure that this guy isn't in the stack already */
  1971.           soe_delq (extent, b);
  1972.       
  1973.           cef = soe->stack;
  1974.           cef_copy = cef;
  1975.           cef_bound = cef + soe->stack_index;
  1976.           cef_put_here = cef_bound;
  1977.  
  1978.           while (cef < cef_bound)
  1979.         {
  1980.           if (EXTENT_LESS (extent, *cef))
  1981.             {
  1982.               cef_put_here = cef;
  1983.               break;
  1984.             }
  1985.           cef++;
  1986.         }
  1987.   
  1988.           cef = cef_bound;
  1989.           while (cef > cef_put_here)
  1990.         {
  1991.           *cef = *(cef - 1);
  1992.           cef--;
  1993.         }
  1994.           *cef_put_here = extent;
  1995.           soe->stack_index++;
  1996.         }
  1997.     }
  1998.       else if (extent->end < index)
  1999.     {
  2000.       EXTENT prev = soe->previous_extent;
  2001.       if (!prev || EXTENT_E_LESS (prev, extent))
  2002.         soe->previous_extent = extent;
  2003.     }
  2004.     }
  2005. }
  2006.  
  2007. static void soe_duplicate (int index, EXTENT *copy_from, int copy_from_size, 
  2008.                EXTENT trial_prev, struct buffer *b)
  2009. {
  2010.   struct stack_of_extents *soe = b->cached_stack;
  2011.  
  2012.   if (!soe)
  2013.     return;
  2014.  
  2015.   if (copy_from_size > 0)
  2016.     {
  2017.       if (soe->stack_length < copy_from_size)
  2018.     {
  2019.       soe->stack_length = copy_from_size + 1;
  2020.       soe->stack = 
  2021.             (EXTENT*)xrealloc (soe->stack, 
  2022.                                soe->stack_length * sizeof (EXTENT));
  2023.     }
  2024.       memcpy ((char *) soe->stack, (char *) copy_from,
  2025.           copy_from_size * sizeof (EXTENT));
  2026.  
  2027.       trial_prev = soe->stack[0];
  2028.     }
  2029.   
  2030.   soe->stack_index = copy_from_size;
  2031.   soe->buf_index = index;
  2032.  
  2033.   if (!trial_prev || !EXTENT_PAST_INDEX (trial_prev, index))
  2034.     trial_prev = 0;
  2035.  
  2036.   while (trial_prev && EXTENT_PAST_INDEX (trial_prev, index))
  2037.     trial_prev = trial_prev->e_previous;
  2038.  
  2039.   if (!trial_prev)
  2040.     soe_clear(b);
  2041.   else
  2042.     soe->previous_extent = trial_prev;
  2043. }
  2044.  
  2045.  
  2046. static void
  2047. soe_delq (EXTENT extent, struct buffer *b)
  2048. {
  2049.   struct stack_of_extents *soe = b->cached_stack;
  2050.   if (soe)
  2051.     {
  2052.       EXTENT* cef = soe->stack;
  2053.       EXTENT* cef_copy = cef;
  2054.       EXTENT* cef_bound = cef + soe->stack_index;
  2055.       int found = 0;
  2056.  
  2057.       while (cef < cef_bound)
  2058.     {
  2059.       if (extent == *cef)
  2060.         {
  2061.           *cef = 0;
  2062.           found++;
  2063.         }
  2064.       cef++;
  2065.     }
  2066.   
  2067.       if (found > 0)
  2068.     {
  2069.       cef = cef_copy; 
  2070.       while (cef < cef_bound)
  2071.         {
  2072.           if (*cef)
  2073.         {
  2074.           *cef_copy = *cef;
  2075.           cef_copy++;
  2076.         }
  2077.           cef++;
  2078.         }
  2079.  
  2080.       soe->stack_index = cef_copy - soe->stack;
  2081.     }
  2082.  
  2083.       if (extent == soe->previous_extent)
  2084.     soe->previous_extent = extent->e_previous;
  2085.     }
  2086. }
  2087.  
  2088. void 
  2089. init_buffer_cached_stack (struct buffer *b)
  2090. {
  2091.   if (!b->cached_stack)
  2092.     {
  2093.       int default_stack_size = 10;
  2094.       struct stack_of_extents *new =
  2095.         (struct stack_of_extents *) 
  2096.           xmalloc (sizeof (struct stack_of_extents));
  2097.       memset ((char *) new, 0, sizeof (struct stack_of_extents));
  2098.       new->stack_length = default_stack_size;
  2099.       new->stack = (EXTENT *) xmalloc (default_stack_size * sizeof (EXTENT));
  2100.       b->cached_stack = new;
  2101.     }
  2102. }
  2103.  
  2104. static void
  2105. soe_clear (struct buffer *b)
  2106. {
  2107.   struct stack_of_extents *soe = b->cached_stack;
  2108.   if (soe)
  2109.     {
  2110.       soe->stack_index = 0;
  2111.       soe->buf_index = 0;
  2112.       soe->previous_extent = 0;
  2113.     }
  2114. }
  2115.  
  2116. static void
  2117. soe_prune (struct buffer *b)
  2118. {
  2119.   struct stack_of_extents *soe = b->cached_stack;
  2120.  
  2121.   if (!soe)
  2122.     return;
  2123.   
  2124.   if (soe->buf_index <= 0)
  2125.     {
  2126.       soe_clear(b);
  2127.       return;
  2128.     }
  2129.   else
  2130.     {
  2131.       EXTENT* cef = soe->stack;
  2132.       EXTENT* cef_copy = cef;
  2133.       EXTENT* cef_bound = cef + soe->stack_index;
  2134.       int index = soe->buf_index;
  2135.       int removedp = 0;
  2136.  
  2137.       while (cef < cef_bound)
  2138.     {
  2139.       EXTENT extent = *cef;
  2140.       if (!EXTENT_OVER_INDEX (extent, index))
  2141.         {
  2142.           *cef = 0;
  2143.           removedp = 1;
  2144.         }
  2145.       cef++;
  2146.     }
  2147.   
  2148.       if (removedp)
  2149.     {
  2150.       cef = cef_copy; 
  2151.       while (cef < cef_bound)
  2152.         {
  2153.           if (*cef)
  2154.         {
  2155.           *cef_copy = *cef;
  2156.           cef_copy++;
  2157.         }
  2158.           cef++;
  2159.         }
  2160.  
  2161.       soe->stack_index = cef_copy - soe->stack;
  2162.     }
  2163.     }
  2164.  
  2165.   {
  2166.     EXTENT prev;
  2167.     int index = soe->buf_index;
  2168.  
  2169.     if (soe->stack_index > 0)
  2170.       prev = soe->stack[0];
  2171.     else
  2172.       prev = soe->previous_extent;
  2173.  
  2174.     while (prev && EXTENT_PAST_INDEX (prev, index))
  2175.       prev = prev->e_previous;
  2176.     if (prev)
  2177.       soe->previous_extent = prev;
  2178.     else
  2179.       soe_clear (b);
  2180.   }
  2181. }
  2182.  
  2183. void
  2184. free_buffer_cached_stack (struct buffer *b)
  2185. {
  2186.   struct stack_of_extents *tmp = b->cached_stack;
  2187.   b->cached_stack = 0;
  2188.   if (tmp)
  2189.     {
  2190.       EXTENT *tmp_stack = tmp->stack;
  2191.       tmp->stack = 0;
  2192.       if (tmp_stack)
  2193.         xfree (tmp_stack);
  2194.       xfree (tmp);
  2195.     }
  2196. }
  2197.  
  2198. /* This function assumes that ef is correct and up to date, and then
  2199.    ef->start_index is incremented and ef->first_extent_past_stack is either
  2200.    0'd or certified correct, and then this function is called. This
  2201.    function removes all extents from the extents_stack that are "too small"
  2202.    (the only way the can be invalid here, since if they were "too big" now,
  2203.    then they would have been "too big" when ef->start_index was smaller).
  2204.    In particular, ef->extents_stack will be correct unless there are 
  2205.    "bigger extents" than those in the stack that remain to be pushed on it.
  2206.    
  2207.    At the same time, it sets ef->end_index to be the minimum of all of the
  2208.    end indicies of the extents left in the stack, if any, and the
  2209.    start_index of ef->first_extent_past_stack, if that exists. If none of
  2210.    these exist, the ef->end_index is set to be the max index of the buffer.
  2211.    This value of ef->end_index is at least as large as the correct value
  2212.    for ef->buffer and given ef->start_index, and it is correct if the
  2213.    extents_stack is complete and the value of ef->first_extent_past_stack
  2214.    passed in is correct. */
  2215.    
  2216. static void
  2217. cleanup_old_stack (EXTENT_FRAGMENT ef)
  2218. {
  2219.   EXTENT* cef = ef->extents_stack;
  2220.   EXTENT* cef_copy = cef;
  2221.   EXTENT* cef_bound = cef + ef->number_of_extents;
  2222.   int new_start = ef->start_index;
  2223.   int min_for_end = 
  2224.     (ef->first_extent_past_stack)?
  2225.       (ef->first_extent_past_stack->start):MAX_INT;
  2226.  
  2227.   while (cef < cef_bound)
  2228.     {
  2229.       int end = (*cef)->end;
  2230.       int start = (*cef)->start;
  2231.    
  2232.       /* flush any extent ending too soon, which includes any extent ending
  2233.          before this point or any extent of positive length ending AT this
  2234.          point */
  2235.       if ((end < new_start) ||
  2236.           ((end == new_start) && (start < end)))
  2237.     *cef = 0;
  2238.       /* if the extent wasn't flushed and is of positive length,
  2239.          then if it ends before our min so far, use this as the
  2240.          new min */
  2241.       else if ((end < min_for_end) && (start < end))
  2242.     min_for_end = end;
  2243.       cef++;
  2244.     }
  2245.   
  2246.     cef = cef_copy; 
  2247.     while (cef < cef_bound)
  2248.     {
  2249.       if (*cef)
  2250.     {
  2251.           *cef_copy = *cef;
  2252.           cef_copy++;
  2253.     }
  2254.       cef++;
  2255.     }
  2256.  
  2257.   ef->end_index = min_for_end;
  2258.   ef->number_of_extents = cef_copy - ef->extents_stack;
  2259. }
  2260.  
  2261. /* Long comment:
  2262.    
  2263.    This function updates the cached ef to "surround" the new buf_index 
  2264.    that is promised to be == the current ef->end_index. The on
  2265.  
  2266.    Extents are ordered with increasing start position and then decreasing
  2267.    end position. (This is what might be called "display order" -- if extent
  2268.    A occurs after extent B, then the display attributes of extent A
  2269.    override those of extent B in the region covered by both A and B. Note
  2270.    that multiple extents with the same start and end postions may be in any
  2271.    order.)
  2272.  
  2273.    The extents_stack has the extents that are "over" a given buffer
  2274.    index in the same order as in the buffer's extent list. The state
  2275.    coming in might look like this:
  2276.  
  2277.  
  2278.    extents_stack |
  2279.                  v
  2280.  
  2281.    [.......................................)
  2282.    [............................)
  2283.        [...........................)
  2284.        [.....................)
  2285.             [...........................)
  2286.                              |  <<-------  buf_index required to be this
  2287.             [________________)  <<-------  fragment boundaries
  2288.  
  2289.                                                     first_extent_past_stack |
  2290.                                                                             v
  2291.                                                     [........................)
  2292.  
  2293.                              [__)  new fragment boundaries
  2294.    
  2295.    If there is no first_extent_past_stack, then we just prune the 
  2296.    extents_stack as described below, and if there are no extents over
  2297.    the buf_index, the new fragment goes from buf_index to the end of
  2298.    the buffer. 
  2299.    
  2300.    Otherwise, the first_extent_past_stack is guaranteed to have its
  2301.    start index be >= buf_index of the fragment.
  2302.  
  2303.    If the first_extent_past_stack start is > buf_index, then the
  2304.    first_extent_past_stack will still be the same after the update.  In
  2305.    that case all that is needed is to update the extents_stack by deleting
  2306.    anything that "fell off the end", set the new start_index to the
  2307.    buf_index and compute the new end_index. (In the special case where
  2308.    there is one extent in the extents_stack, this calculation is easy,
  2309.    since that means that the new stack is empty and the new end_index for
  2310.    the fragment is next->start. If the extents_stack is empty, then
  2311.    the caller of this function is broken and we abort().)
  2312.  
  2313.    The remaining case is when the first_extent_past_stack starts at
  2314.    buf_index. If there are extents in the stack, then we need to remove all
  2315.    of the ones that have fallen off the end.  After that
  2316.    first_extent_past_stack gets pushed, and we look for any other extents
  2317.    that need pushing. While we are doing this, we need to figure out where
  2318.    the new fragment ends, and what the new first_extent_past_stack is. (We
  2319.    could consider optimizing the case of their being one extent in the
  2320.    stack
  2321.  
  2322.  
  2323.    NOTE: At the moment only this function, buffer_extent_fragment_at(),
  2324.    splice_extent_into_buffer(), adjust_extents () and map_extents() 
  2325.    know how to "cdr" down a list of extents. */
  2326.  
  2327. static EXTENT_FRAGMENT
  2328. update_cache_forward (EXTENT_FRAGMENT ef, int buf_index, struct buffer* buf)
  2329. {
  2330.   /* Incrementally update the cache forward.  This has to be FAST. */
  2331.   EXTENT next = ef->first_extent_past_stack;
  2332.  
  2333.   ef->start_index = buf_index;
  2334.  
  2335.   if (!next)
  2336.     {
  2337.       /* ef->first_extent_past_stack is correct here, because there
  2338.          isn't any */
  2339.       if (ef->number_of_extents == 1)
  2340.         {
  2341.           /* easy case for updating stack */
  2342.           ef->number_of_extents = 0;   
  2343.       ef->end_index = MAX_INT;
  2344.         }
  2345.       else if (ef->number_of_extents == 0)
  2346.         abort();
  2347.       else
  2348.         /* this will fix ef->end_index, since ef->first_extent_past_stack
  2349.            is correctly 0 and there are no more extents to add to the stack */
  2350.         cleanup_old_stack (ef);
  2351.    
  2352.       /* the stack, ef->start_index, and ef->end_index are all
  2353.          correct, so just wrap_up */   
  2354.       goto wrap_up;
  2355.     }
  2356.   else if (buf_index < next->start)
  2357.     {
  2358.       /* ef->first_extent_past_stack is correct here, because it  won't
  2359.          change as the result of this operation */
  2360.       if (ef->number_of_extents == 1)
  2361.         {
  2362.           /* easy case for updating stack -- moving into a "hole" between
  2363.              extents */
  2364.           ef->number_of_extents = 0;
  2365.           ef->end_index = next->start;
  2366.         }
  2367.       else if (ef->number_of_extents == 0)
  2368.         abort();
  2369.       else
  2370.         /* the stack will add nothing new, because
  2371.            ef->first_extent_past_stack is too big to go on the stack, and
  2372.            so it is correct, too -- this means that call will set
  2373.            ef->end_index to be == correct value; see comment for
  2374.            cleanup_old_stack() */
  2375.         cleanup_old_stack (ef);
  2376.  
  2377.       /* the stack, ef->start_index, and ef->end_index are all
  2378.          correct, so just wrap_up */   
  2379.       goto wrap_up;   
  2380.     }
  2381.   else if (ef->number_of_extents > 0)
  2382.     {
  2383.       /* ef->first_extent_past_stack wrong here, because it is next,
  2384.          and next is going onto the stack -- the stack is wrong, too */
  2385.       ef->first_extent_past_stack = 0;
  2386.       /* this will set ef->end_index to be >= correct value; see
  2387.          comment for function */
  2388.       cleanup_old_stack (ef);
  2389.     }
  2390.   else 
  2391.     /* stack is empty so needs no pruning, and we know that next->end
  2392.        is at least as big as the fragment end_index */
  2393.     ef->end_index = next->end;
  2394.  
  2395.   /* If we get to this point, ef->start_index is correct,
  2396.      ef->end_index is >= the correct value, and
  2397.      ef->first_extent_past_stack is completely wrong */
  2398.  
  2399.   {
  2400.     /* retain last extent to be pushed on the stack */
  2401.     EXTENT last;
  2402.     do
  2403.       {
  2404.         if (ef->number_of_extents == ef->extents_stack_length)
  2405.           {
  2406.             ef->extents_stack_length *= 2;
  2407.             ef->extents_stack =
  2408.               (EXTENT*)xrealloc (ef->extents_stack,
  2409.                                  ef->extents_stack_length * sizeof (EXTENT));
  2410.           }
  2411.         ef->extents_stack [ef->number_of_extents] = next;
  2412.         ef->number_of_extents += 1;
  2413.  
  2414.         last = next;
  2415.         next = next->next;
  2416.     if (next == last) abort ();
  2417.     if (next && next->previous != last) abort ();
  2418.       }
  2419.     while (next && (next->start == buf_index));
  2420.  
  2421.     /* make sure that ef->end_index is correct, since we may have
  2422.        come into this function with a value that is too big -- 
  2423.        recall that since the end values of the extents are
  2424.        decreasing while the start value stay the same, last->end
  2425.        has the smallest "end" of all things pushed onto the stack */
  2426.     if (last->end < ef->end_index)
  2427.       ef->end_index = last->end;
  2428.     if (next &&
  2429.         (next->start < ef->end_index))
  2430.       ef->end_index = next->start;
  2431.   }
  2432.   ef->first_extent_past_stack = next;
  2433.  
  2434.  wrap_up:
  2435.   ef->from = extent_index_to_buffer_pos (ef->start_index, buf);
  2436.   ef->to = 
  2437.     ((ef->end_index == MAX_INT)?MAX_INT:
  2438.      extent_index_to_buffer_pos (ef->end_index, buf));
  2439.   return ef;
  2440. }
  2441.  
  2442.  
  2443. /* Find extent fragment at pos in buf. NOTE: At the moment only this
  2444.    function, update_cache_forward(), splice_extent_into_buffer(), 
  2445.    adjust_extents () and map_extents() 
  2446.    know how to "cdr" down a list of extents. See the comment
  2447.    at map_extents() for information about the ordering rule. */
  2448.  
  2449. static EXTENT_FRAGMENT
  2450. befa_internal (int pos, struct buffer *buf)
  2451. {
  2452.   EXTENT_FRAGMENT ef;
  2453.   EXTENT current;
  2454.   EXTENT trial_prev = 0;
  2455.   int buf_index;
  2456.   int new_start;
  2457.   int new_end;
  2458.  
  2459.   buf_index = buffer_pos_to_extent_index (pos, buf);
  2460.   ef = &extent_fragment;
  2461.  
  2462.   current = buffer_starting_extent (buf_index, buf);
  2463.   
  2464.   new_start = buffer_pos_to_extent_index (BUF_BEG(buf), buf);
  2465.   new_end = MAX_INT;
  2466.   ef->number_of_extents = 0;
  2467.  
  2468.   /* Find all of the extents "over" this fragment, and at the same time
  2469.      find the "first_extent_past_stack" for the fragment and the 
  2470.      start_index. */
  2471.   while (current && 
  2472.          (current->start <= buf_index))
  2473.     {
  2474.       trial_prev = current;
  2475.  
  2476.       if ((current->end <= buf_index) && (current->end > new_start))
  2477.         {
  2478.           new_start = current->end;
  2479.         }
  2480.       /* we repeat some code in this clause and the next to save tests */
  2481.       else if (current->end > buf_index)
  2482.     {
  2483.           if (current->start > new_start)
  2484.             new_start = current->start;   
  2485.           if (current->end < new_end)
  2486.             new_end = current->end;
  2487.  
  2488.       if (ef->number_of_extents == ef->extents_stack_length)
  2489.         {
  2490.           ef->extents_stack_length *= 2;
  2491.           ef->extents_stack =
  2492.         (EXTENT*)xrealloc (ef->extents_stack,
  2493.                    ef->extents_stack_length * sizeof (EXTENT));
  2494.         }
  2495.       ef->extents_stack [ef->number_of_extents] = current;
  2496.       ef->number_of_extents += 1;
  2497.     }
  2498.       /* we repeat some code in this clause and the last to save tests */   
  2499.       else if ((current->end == current->start) && (current->end == buf_index))
  2500.     {
  2501.           new_end = new_start = buf_index;
  2502.  
  2503.       if (ef->number_of_extents == ef->extents_stack_length)
  2504.         {
  2505.           ef->extents_stack_length *= 2;
  2506.           ef->extents_stack =
  2507.         (EXTENT*)xrealloc (ef->extents_stack,
  2508.                    ef->extents_stack_length * sizeof (EXTENT));
  2509.         }
  2510.       ef->extents_stack [ef->number_of_extents] = current;
  2511.       ef->number_of_extents += 1;
  2512.     }
  2513.         
  2514.       if (current == current->next) abort ();
  2515.       current = current->next;
  2516.     }
  2517.  
  2518.   /* Check the end_index for this fragment. */
  2519.   if (current && 
  2520.       (current->start < new_end))
  2521.     new_end = current->start;
  2522.   
  2523.   XSET (Vextent_fragment_buffer, Lisp_Buffer, buf);
  2524.   ef->buf = buf;
  2525.   ef->modiff = BUF_MODIFF (buf);
  2526.   ef->face_change = BUF_FACECHANGE (buf);
  2527.   ef->first_extent_past_stack = current;
  2528.   ef->start_index = new_start;
  2529.   ef->end_index = new_end;
  2530.   ef->from = extent_index_to_buffer_pos (new_start, buf);
  2531.   ef->to = 
  2532.     (new_end == MAX_INT)?MAX_INT:extent_index_to_buffer_pos (new_end, buf);
  2533.  
  2534.   soe_duplicate (buf_index, ef->extents_stack, 
  2535.                  ef->number_of_extents, trial_prev, buf);
  2536.  
  2537.   return ef;
  2538. }
  2539.  
  2540. EXTENT_FRAGMENT
  2541. buffer_extent_fragment_at (int pos, struct buffer *buf, struct screen *s)
  2542. {
  2543.   int cache_valid;
  2544.   EXTENT_FRAGMENT ef;
  2545.   int buf_index;
  2546.  
  2547.   if (NILP (buf->extents))
  2548.     {
  2549.       Vextent_fragment_buffer = Qnil;
  2550.       extent_fragment.buf = 0;
  2551.       default_extent_fragment.from = BUF_BEG (buf);
  2552.       default_extent_fragment.to = MAX_INT;
  2553.       return &default_extent_fragment;
  2554.     }
  2555.   else if (!EXTENTP (buf->extents))
  2556.     abort ();
  2557.  
  2558.   buf_index = buffer_pos_to_extent_index (pos, buf);
  2559.   ef = &extent_fragment;
  2560.   cache_valid = (!extent_cache_invalid &&
  2561.          (buf == ef->buf) && 
  2562.                  (BUF_MODIFF(buf) == ef->modiff) &&
  2563.          (BUF_FACECHANGE (buf) == ef->face_change));
  2564.  
  2565.   if (cache_valid)
  2566.     {
  2567.       if (buf_index == ef->end_index)
  2568.     ef = update_cache_forward (ef, buf_index, buf); /* 99% of the time */
  2569.       else if ((pos >= extent_fragment.from) && (pos < extent_fragment.to))
  2570.     return ef;
  2571.       else 
  2572.     ef = befa_internal (pos, buf);
  2573.     }
  2574.   else 
  2575.     ef = befa_internal (pos, buf);
  2576.  
  2577.   setup_extent_fragment_face_ptr (s, ef);
  2578.   extent_cache_invalid = 0;
  2579.   return ef;
  2580. }
  2581.  
  2582. static void
  2583. init_extent_fragment ()
  2584. {
  2585.   int l = 30;
  2586.  
  2587.   memset ((char *) &extent_fragment, 0, sizeof (extent_fragment));
  2588.   extent_fragment.extents_stack_length = l;
  2589.   extent_fragment.extents_stack = (EXTENT *) xmalloc (l * sizeof (EXTENT));
  2590.  
  2591.   memset ((char *) &default_extent_fragment, 0,
  2592.       sizeof (default_extent_fragment));
  2593.   extent_cache_invalid = 1;
  2594. }
  2595.  
  2596. /* Modify all of the extents as required for the insertion. At the
  2597.    moment this function does nothing, but eventually it probably should
  2598.    adjust the endpoints of the extents that touch point in a manner that
  2599.    takes the the opened/closed property of the endpoint into account. */
  2600. void 
  2601. process_extents_for_insertion (int opoint, int length, struct buffer *buf)
  2602. {
  2603.   return;
  2604. }
  2605.    
  2606. static int   
  2607. process_extents_for_deletion_mf (EXTENT extent, void *arg)
  2608. {
  2609.   struct process_extents_for_deletion_struct *peds_ptr = 
  2610.     (struct process_extents_for_deletion_struct *) arg;
  2611.   
  2612.   if ((peds_ptr->start <= extent->start) && (extent->end <= peds_ptr->end))
  2613.     {
  2614.       if (peds_ptr->destroy_included_extents)
  2615.         destroy_extent (extent);
  2616.       else
  2617.         detach_extent (extent);
  2618.     }
  2619.   else if (peds_ptr->destroy_included_extents)
  2620.     return 0;
  2621.   /* the extent completely contains the deleted range, so we don't need to
  2622.      do anything about it */
  2623.   else if ((extent->start < peds_ptr->start) && (peds_ptr->end < extent->end))
  2624.     return 0;
  2625.   else
  2626.     /* these characters are going away, so the extent must be shortened 
  2627.        appropriately -- this code should probably do something about
  2628.        opened/closed endpoints, too */
  2629.     {
  2630.       int max_start = max (extent->start, peds_ptr->start);
  2631.       int min_end = min (extent->end, peds_ptr->end);
  2632.       /* this test is really unneeded, since map_extents() promises the
  2633.          two "spans of text" will overlap but it's cheap and
  2634.          I'm nervous */
  2635.       if (max_start < min_end)
  2636.         {
  2637.           if (max_start == extent->start)
  2638.             extent->start = min_end;
  2639.           else
  2640.             extent->end = max_start;
  2641.         }
  2642.     }
  2643.   return 0;
  2644. }
  2645.  
  2646. /* Delete all of the extents that are completely inside the range [from,
  2647.    to). Eventually, this function should also adjust the endpoints of the
  2648.    extents that overlap the about to be deleted range in a manner that
  2649.    takes the the opened/closed property of the endpoint into account.
  2650.    NOTE: This function must either preserve the internal ordering of the
  2651.    extents automatically or it must explicitly fix that ordering before
  2652.    quitting. At the moment the ordering is preserved automatically.
  2653.    [from to) is the range of POSITIONs being deleted and [start end) is the
  2654.    INDEX values of the gap when the deletion is completed.
  2655.    */
  2656. void process_extents_for_deletion (int from, int to, int start, int end,
  2657.                    struct buffer *buf)
  2658. {
  2659.   if (NILP (buf->extents))
  2660.     return;
  2661.   else if (!EXTENTP (buf->extents))
  2662.     abort();
  2663.   else
  2664.     {
  2665.       struct process_extents_for_deletion_struct peds;   
  2666.  
  2667.       check_from_to (from, to, buf);
  2668.  
  2669.       /* start and end don't need to be turned into index values because
  2670.          they are already -- from and to are buffer positions */
  2671.       peds.start = start;
  2672.       peds.end = end;
  2673.       peds.destroy_included_extents = 0;
  2674.       /* Need to do a map_extent with closed_end so that the extent
  2675.      just beginning or ending on the old gap are processed too.
  2676.      --Matthieu. */
  2677.       map_extents (from, to, 0, process_extents_for_deletion_mf,
  2678.                    (void *) &peds, buf, 1);
  2679.  
  2680.       if (buf->cached_stack
  2681.       && (buf->cached_stack->buf_index >= start)
  2682.       && (buf->cached_stack->buf_index < end))
  2683.     buf->cached_stack->buf_index = start;
  2684.       soe_prune (buf);
  2685.     }
  2686. }
  2687.  
  2688. void
  2689. process_extents_for_destruction (int from, int to, struct buffer *buf)
  2690. {
  2691.   if (NILP (buf->extents))
  2692.     return;
  2693.   else if (!EXTENTP (buf->extents))
  2694.     abort();
  2695.   else
  2696.     {
  2697.       struct process_extents_for_deletion_struct peds;   
  2698.  
  2699.       check_from_to (from, to, buf);
  2700.  
  2701.       peds.start = buffer_pos_to_extent_index (from, buf);
  2702.       peds.end = buffer_pos_to_extent_index (to, buf);
  2703.       peds.destroy_included_extents = 1;
  2704.       /* Need to do a map_extent with closed_end so that the extent
  2705.          just beginning or ending on the old gap are processed too.
  2706.          --Matthieu. */
  2707.       map_extents (from, to, 0, process_extents_for_deletion_mf,
  2708.                    (void *) &peds, buf, 1);
  2709.     }
  2710. }
  2711.  
  2712.  
  2713. static int
  2714. replicate_extents_mf (EXTENT extent, void *arg)
  2715. {
  2716.   struct replicate_extents_struct *res_ptr = 
  2717.     (struct replicate_extents_struct *) arg;
  2718.   Lisp_Object head = res_ptr->head;
  2719.   Lisp_Object tail = res_ptr->nconc_cell;
  2720.   int start = 
  2721.     extent_index_to_buffer_pos (extent->start, res_ptr->buf) - res_ptr->from;
  2722.   int end = 
  2723.     extent_index_to_buffer_pos (extent->end, res_ptr->buf) - res_ptr->from;
  2724.   
  2725.   if (EXTENT_FLAG_P (extent, EF_DUPLICABLE))
  2726.     {
  2727.       start = max (start, 0);
  2728.       end = min (end, res_ptr->length);
  2729.  
  2730.       /* this test should probably never fail, but I'm a bit confused at the
  2731.      moment */
  2732.       if ((start < end) || 
  2733.       ((start == end) && (extent->start == extent->end)))
  2734.     {
  2735.       Lisp_Object new_cell;   
  2736.       Lisp_Object replica;
  2737.       DUP dup = make_extent_replica ();
  2738.  
  2739.       XSET (replica, Lisp_Extent_Replica, dup);
  2740.       XSET (dup->extent, Lisp_Extent, extent);
  2741.       dup->start = start;
  2742.       dup->end = end;
  2743.       new_cell = Fcons (replica, Qnil);
  2744.    
  2745.       if (NILP (head))
  2746.         res_ptr->head = new_cell;
  2747.       else
  2748.         Fsetcdr (tail, new_cell);
  2749.       res_ptr->nconc_cell = new_cell;
  2750.     }
  2751.     }  
  2752.   return 0;
  2753. }
  2754.  
  2755. Lisp_Object 
  2756. replicate_extents (int opoint, int length, struct buffer *buf)
  2757. {
  2758.   if (NILP (buf->extents))
  2759.     return Qnil;
  2760.   else if (!EXTENTP (buf->extents))
  2761.     abort();
  2762.   else
  2763.     {
  2764.       struct replicate_extents_struct res;
  2765.       res.from = opoint;
  2766.       res.length = length;
  2767.       res.head = Qnil;
  2768.       res.buf = buf;
  2769.       res.nconc_cell = 0;
  2770.       map_extents (opoint, opoint + length, 0, replicate_extents_mf, 
  2771.                    (void *) &res, buf, 0);
  2772.       return res.head;
  2773.     }
  2774. }
  2775.  
  2776. /* We have just inserted a string of size "length" at "opoint" -- we have
  2777.    the contents of the extents slot of the string on hand, and we now need
  2778.    to do "whatever" is necessary to make the extents in the buffer be
  2779.    correctly updated. If there are no extents on the string, then that is
  2780.    nothing. If there are extents and we are inside_undo, then the extents
  2781.    argument is taken as revealed truth and the state of the buffer extents
  2782.    must be restored so that the function above would return the same string
  2783.    extents if this corresponding string were to be deleted. If we are not
  2784.    inside undo then we just splice in those extents that correspond to
  2785.    deleted extents.
  2786.  
  2787.    Note: At the moment we ONLY handle the case of the dup_list argument
  2788.    be a list of extent_replicas.
  2789.    */
  2790.  
  2791. void 
  2792. splice_in_extent_replicas (int opoint, int length, 
  2793.                            Lisp_Object dup_list, struct buffer *buf)
  2794. {
  2795.   if ((!NILP(buf->extents) && (!EXTENTP (buf->extents))) || 
  2796.       (!NILP (dup_list) && (!CONSP (dup_list))))
  2797.     abort();
  2798.   if (NILP (dup_list))   
  2799.     return;
  2800.   else if (inside_undo)
  2801.     {
  2802.       Lisp_Object tail;
  2803.       int base_start = buffer_pos_to_extent_index (opoint, buf);
  2804.       int base_end = buffer_pos_to_extent_index (opoint + length, buf);
  2805.  
  2806.       for (tail = dup_list; !NILP (tail); tail = Fcdr (tail))
  2807.         {
  2808.           Lisp_Object current_replica = Fcar (tail);
  2809.           /* only process replicas at the moment */
  2810.           if (EXTENT_REPLICA_P (current_replica)) 
  2811.             {
  2812.               DUP dup = XDUP (current_replica);
  2813.               EXTENT extent = XEXTENT (dup->extent);
  2814.               int new_start = base_start + dup->start;
  2815.               int new_end = base_start + dup->end;
  2816.  
  2817.               if (EXTENT_DESTROYED_P (extent))
  2818.                 continue;
  2819.  
  2820.               /* paranoid testing which will go away eventually */
  2821.               if ((!EXTENTP (dup->extent)) ||
  2822.                   (XBUFFER (extent->buffer) != buf))
  2823.                 abort ();
  2824.               
  2825.               if (EXTENT_FLAGS (extent) & EF_DETACHED)
  2826.                 {
  2827.                   int from = extent_index_to_buffer_pos (new_start, buf);
  2828.                   int to = extent_index_to_buffer_pos (new_end, buf);
  2829.                   update_extent (extent, from, to, 1, buf);
  2830.                 }
  2831.               else if
  2832.                 ((extent->start > extent_index_offset (base_end, 1, buf)) ||
  2833.                  (extent->end < extent_index_offset (base_start, -1, buf)))
  2834.                 error ("extent 0x%x is all fouled up wrt. dup 0x%x",
  2835.                        extent, dup);
  2836.               else
  2837.                 {
  2838.                   /* this should be safe because if you delete some text
  2839.                      all of the extents that were effected stay in the
  2840.                      same order, so when you restore what was removed
  2841.                      they should still be in the correct order */
  2842.                   extent->start = min (new_start, extent->start);
  2843.                   extent->end = max (new_end, extent->end);
  2844.           soe_push (extent, buf);
  2845.                 }
  2846.             }
  2847.         }
  2848.     }
  2849.   else
  2850.     {
  2851.       Lisp_Object tail;
  2852.       int base_start = buffer_pos_to_extent_index (opoint, buf);
  2853. /*      int base_end = buffer_pos_to_extent_index (opoint + length, buf); */
  2854.  
  2855.       for (tail = dup_list; !NILP (tail); tail = Fcdr (tail))
  2856.         {
  2857.           Lisp_Object current_replica = Fcar (tail);
  2858.           /* only process replicas at the moment */
  2859.           if (EXTENT_REPLICA_P (current_replica)) 
  2860.             {
  2861.               DUP dup = XDUP (current_replica);
  2862.               EXTENT extent = XEXTENT (dup->extent);
  2863.               int new_start = base_start + dup->start;
  2864.               int new_end = base_start + dup->end;
  2865.  
  2866.               if (EXTENT_DESTROYED_P (extent))
  2867.                 continue;
  2868.  
  2869.               /* paranoid testing which will go away eventually */
  2870.               if ((!EXTENTP (dup->extent)))
  2871.                 abort ();
  2872.  
  2873.           /* Energize extents like topleve-forms can only be pasted 
  2874.            * in the buffer they come from.  This should be parametrized
  2875.            * in the generic extent objects.  Right now just silently
  2876.            * skip the extents if it's not from the same buffer.
  2877.            * --Matthieu */
  2878.           if (XBUFFER (extent->buffer) != buf)
  2879.         continue;
  2880.  
  2881.               if (EXTENT_FLAGS (extent) & EF_DETACHED)
  2882.                 {
  2883.                   int from = extent_index_to_buffer_pos (new_start, buf);
  2884.                   int to = extent_index_to_buffer_pos (new_end, buf);
  2885.                   update_extent (extent, from, to, 1, buf);
  2886.                 }
  2887.               else if (extent->end < new_start - 1)
  2888.                 continue;
  2889.               else if (extent->start > new_end + 1)
  2890.                 continue;
  2891.               else
  2892.                 {
  2893.                   int from = 
  2894.                     extent_index_to_buffer_pos 
  2895.                       (min (new_start, extent->start), buf);
  2896.                   int to = 
  2897.                     extent_index_to_buffer_pos 
  2898.                       (max (new_end, extent->end), buf);
  2899.                   update_extent (extent, from, to, 1, buf);   
  2900.                 }
  2901.             }
  2902.         }
  2903.     }
  2904. }
  2905.  
  2906.  
  2907. /* Merge dup_list[i] into a list of replicas -- if a dup
  2908.    in listi "overlaps at the end" matches a dup from listi+1 that "overlaps
  2909.    at the beginning", merge them into one contiguous dup in the returned
  2910.    list. It is weird and probably bogus if a "detached dup" doesn't merge 
  2911.    entirely, but it isn't an error. */
  2912.    
  2913. static void merge_replicas_concating_mf (void *, void *, void *);
  2914. static void merge_replicas_pruning_mf   (void *, void *, void *);
  2915.  
  2916. Lisp_Object 
  2917. merge_replicas (int number_of_lists, struct merge_replicas_struct *vec)
  2918. {
  2919.   c_hashtable table = 0;
  2920.   Lisp_Object cells_vec[2];
  2921.   int i;
  2922.  
  2923.   cells_vec[0] = Qnil;
  2924.   cells_vec[1] = Qnil;
  2925.  
  2926.   for (i = 0; i < number_of_lists; i++)
  2927.     {
  2928.       Lisp_Object dup_list = vec[i].dup_list;
  2929.       int offset = vec[i].entry_offset;
  2930.       int length = vec[i].entry_length;
  2931.  
  2932.       if (!NILP (dup_list))
  2933.         {
  2934.           if (!table)
  2935.             table = make_hashtable (10);
  2936.           add_to_replicas_lists (table, dup_list, offset, length);
  2937.         }
  2938.     }
  2939.  
  2940.   if (table)
  2941.     {
  2942.       maphash (merge_replicas_pruning_mf, table, (void *) table);
  2943.       maphash (merge_replicas_concating_mf, table, (void *) &(cells_vec[0]));
  2944.       free_hashtable (table);
  2945.     }
  2946.   return (cells_vec[0]);
  2947. }
  2948.  
  2949. static void 
  2950. add_to_replicas_lists (c_hashtable table, Lisp_Object dup_list,
  2951.                int offset, int length)
  2952. {
  2953.   Lisp_Object tail;
  2954.   for (tail = dup_list; !NILP (tail); tail = Fcdr(tail))
  2955.     {
  2956.       Lisp_Object current_replica = Fcar (tail);
  2957.       if (EXTENT_REPLICA_P (current_replica)) 
  2958.         {
  2959.           DUP dup = XDUP (current_replica);
  2960.           EXTENT extent = XEXTENT (dup->extent);
  2961.           Lisp_Object pre_existing_cell;
  2962.           Lisp_Object tmp;
  2963.           DUP new_dup;
  2964.  
  2965.           if (EXTENT_DESTROYED_P (extent))
  2966.             continue;
  2967.  
  2968.           new_dup = make_extent_replica ();
  2969.           memcpy ((char *) new_dup, (char *) dup, sizeof (*dup));
  2970.           new_dup->start += offset;
  2971.           new_dup->end += offset;
  2972.    
  2973.           /* paranoid testing which will go away eventually */
  2974.           if (!EXTENTP (dup->extent))
  2975.             abort ();
  2976.               
  2977.           if (!gethash ((void *) extent, table, (void **) &pre_existing_cell))
  2978.             pre_existing_cell = Qnil;
  2979.    
  2980.           XSET (tmp, Lisp_Extent_Replica, new_dup);
  2981.           tmp = Fcons (tmp, pre_existing_cell);
  2982.           puthash ((void *)extent, (void *) tmp, table);
  2983.         }
  2984.     }
  2985. }
  2986.  
  2987. static void 
  2988. merge_replicas_concating_mf (void *key, void *contents, void *arg)
  2989. {
  2990.   extern Lisp_Object nconc2();
  2991.   Lisp_Object extent_cell = (Lisp_Object) contents;
  2992.   Lisp_Object *cells_vec = (Lisp_Object *) arg;
  2993.  
  2994.   if (NILP (cells_vec[0]))
  2995.     cells_vec[0] = extent_cell;
  2996.   else
  2997.     nconc2 (cells_vec[1], extent_cell);
  2998.  
  2999.   cells_vec[1] = extent_cell;
  3000.   return;
  3001. }
  3002.  
  3003. static int 
  3004. mrp_pred (Lisp_Object x, Lisp_Object y, Lisp_Object dummy)
  3005. {
  3006.   DUP dup1 = XDUP(x);
  3007.   DUP dup2 = XDUP(y);
  3008.  
  3009.   if (dup1->start < dup2->start)
  3010.     return 1;
  3011.   else if (dup1->start == dup2->start)
  3012.     {
  3013.       if (dup1->end <= dup2->end)
  3014.         return 1;
  3015.       else
  3016.         return -1;
  3017.     }
  3018.   return -1;
  3019. }
  3020.    
  3021. static void 
  3022. merge_replicas_pruning_mf (void *key, void *contents, void *arg)
  3023. {
  3024.   Lisp_Object dup_list = (Lisp_Object) contents;
  3025.   c_hashtable table = (c_hashtable) arg;
  3026.  
  3027.   if (NILP (dup_list))
  3028.     return;
  3029.    
  3030.   /* sort and merge the dup_list */
  3031.   dup_list = list_sort (dup_list, Qnil, mrp_pred);
  3032.   {
  3033.     Lisp_Object current = dup_list;
  3034.     Lisp_Object tail = Fcdr (dup_list);
  3035.     DUP current_dup = XDUP (Fcar (current));
  3036.     DUP tail_dup = XDUP(Fcar (tail));
  3037.  
  3038.     while (!NILP (tail))
  3039.       {
  3040.         tail_dup = XDUP(Fcar (tail));   
  3041.  
  3042.         if (tail_dup->start <= current_dup->end - 1)
  3043.           {
  3044.             current_dup->end = max (tail_dup->end, current_dup->end);
  3045.             Fsetcdr (current, Fcdr (tail));
  3046.           }
  3047.         else
  3048.           {
  3049.             current = tail;
  3050.             current_dup = XDUP (Fcar (current));
  3051.           }
  3052.    
  3053.         tail = Fcdr (tail);
  3054.       }
  3055.   }
  3056.    
  3057.   /* now put back the munged list */
  3058.   puthash (key, (void *) dup_list, table);
  3059.   return;
  3060. }
  3061.  
  3062.  
  3063. void
  3064. syms_of_extents() 
  3065. {
  3066.   defsubr(&Sextent_length);
  3067.   defsubr(&Sextent_start_position);
  3068.   defsubr(&Sextent_end_position);
  3069.   defsubr(&Sextent_buffer);
  3070. #ifdef ENERGIZE
  3071.   defsubr(&Sextent_to_generic_id);
  3072. #endif
  3073.   defsubr(&Smap_extents);
  3074.   defsubr(&Shighlight_extent);
  3075.   defsubr(&Sforce_highlight_extent);
  3076.   defsubr(&Sextent_at);
  3077.  
  3078.   defsubr(&Smake_extent);
  3079.   defsubr(&Snext_extent);
  3080.   defsubr(&Sdelete_extent);
  3081.   defsubr(&Supdate_extent);
  3082.   defsubr(&Sset_extent_attribute);
  3083.   defsubr(&Sextent_attributes);
  3084.   defsubr(&Sset_extent_begin_glyph);
  3085.   defsubr(&Sset_extent_end_glyph);
  3086.   defsubr(&Sextent_data);
  3087.   defsubr(&Sset_extent_data);
  3088.   defsubr(&Sextent_priority);
  3089.   defsubr(&Sset_extent_priority);
  3090. #if 0
  3091.   defsubr(&Snext_e_extent);
  3092.   defsubr(&Sstack_of_extents);
  3093. #endif
  3094.  
  3095.   Ffset (intern ("set-extent-endpoints"), intern ("update-extent"));
  3096.  
  3097. /*  DEFVAR_LISP ("   last-highlighted-extent", &Vlast_highlighted_extent,
  3098.                "Last highlighted extent; don't touch this kluge.");
  3099. */
  3100.   staticpro (&Vlast_highlighted_extent);
  3101.  
  3102.   Vlast_highlighted_extent = Qnil;
  3103.  
  3104. /*
  3105.   DEFVAR_LISP ("   buffer-of-current-extent-fragment", 
  3106.                &Vextent_fragment_buffer,
  3107.                "Buffer for current extent fragment -- this is a GC hack.");
  3108. */
  3109.   staticpro (&Vextent_fragment_buffer);
  3110.  
  3111.   Vextent_fragment_buffer = Qnil;
  3112.  
  3113.   init_extent_fragment ();
  3114. }
  3115.