1 ;;; overlay.el --- overlay support.
3 ;; Copyright (C) 1997 Free Software Foundation, Inc.
5 ;; Author: Joe Nuspl <nuspl@sequent.com>
6 ;; Maintainer: XEmacs Development Team (in <hniksic@xemacs.org> incarnation)
9 ;; This file is part of XEmacs.
11 ;; XEmacs is free software; you can redistribute it and/or modify it
12 ;; under the terms of the GNU General Public License as published by
13 ;; the Free Software Foundation; either version 2, or (at your option)
16 ;; XEmacs is distributed in the hope that it will be useful, but
17 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 ;; General Public License for more details.
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with XEmacs; see the file COPYING. If not, write to the
23 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24 ;; Boston, MA 02111-1307, USA.
26 ;;; Synched up with: Not in FSF.
30 ;; Unlike the text-properties interface, these functions are in fact
31 ;; totally useless in XEmacs. They are a more or less straightforward
32 ;; interface to the much better extent API, provided exclusively for
33 ;; GNU Emacs compatibility. If you notice an incompatibility not
34 ;; mentioned below, be sure to mention it. Anyways, you should really
37 ;; Known incompatibilities with the FSF interface:
39 ;; 1. There is not an `overlay' type. Any extent with non-nil
40 ;; 'overlay property is considered an "overlay".
42 ;; 2. Some features of FSF overlays have not been implemented in
43 ;; extents (or are unneeded). Specifically, those are the
44 ;; following special properties: window, insert-in-front-hooks,
45 ;; insert-behind-hooks, and modification-hooks. Some of these will
46 ;; probably be implemented for extents in the future.
48 ;; 3. In FSF, beginning and end of an overlay are markers, which means
49 ;; that you can use `insert-before-markers' to change insertion
50 ;; property of overlay. It will not work in this emulation, and we
51 ;; have no plans of providing it.
53 ;; 4. The `overlays-in' and `overlays-at' functions in some cases
54 ;; don't work as they should. To be fixed RSN.
56 ;; 5. Finally, setting or modification of overlay properties specific
57 ;; to extents will have unusual results. While (overlay-put
58 ;; overlay 'start-open t) does nothing under FSF, it has a definite
59 ;; effect under XEmacs. This is solved by simply avoiding such
60 ;; names (see `set-extent-property' for a list).
62 ;; Some functions were broken; fixed-up by Hrvoje Niksic, June 1997.
67 ;; Have compiled 21.4 code also work on XEmacs binaries with real support
68 ;; for multiple values, by avoiding runtime calls to #'values:
69 (eval-when-compile (when (eq 'list (symbol-function 'values))
70 (define-compiler-macro values (&rest args)
73 (defun overlayp (object)
74 "Return t if OBJECT is an overlay."
76 (extent-property object 'overlay)))
79 (defsubst overlay-normalize-pos (pos buffer)
80 "Return the normalized POS, so 1 <= POS <= \(1+ \(length BUFFER))."
82 (buffer-max (1+ (buffer-size buffer))))
83 (cond ((< pos buffer-min)
90 (defsubst overlay-normalize-begin-end-buffer (beg end &optional buffer)
91 "Normalize BEG and END so that 1 <= BEG <= END <= \(1+ \(length BUFFER)).
93 If BUFFER is nil, the current buffer is assumed. If BEG is
94 greater than END, exchange their value.
96 Returns values BEG END BUFFER. See `multiple-value-setq' and
97 `multiple-value-bind'. "
98 (check-argument-type #'bufferp (setq buffer (or buffer (current-buffer))))
99 (setq beg (overlay-normalize-pos beg buffer)
100 end (overlay-normalize-pos end buffer))
102 (setq beg (prog1 end (setq end beg))))
103 (values beg end buffer))
105 (defun make-overlay (beg end &optional buffer front-advance rear-advance)
106 "Create a new overlay with range BEG to END in BUFFER.
107 If omitted, BUFFER defaults to the current buffer.
108 BEG and END may be integers or markers.
109 The fourth arg FRONT-ADVANCE, if non-nil, makes the
110 front delimiter advance when text is inserted there.
111 The fifth arg REAR-ADVANCE, if non-nil, makes the
112 rear delimiter advance when text is inserted there.
114 BEG and END will be normalized so 1 <= BEG <= END <= \(1+ \(length BUFFER)).
115 If BUFFER is nil, the current buffer is assumed. If BEG is
116 greater than END, exchange their value."
120 (overlay-normalize-begin-end-buffer beg end buffer))
121 (let ((overlay (make-extent beg end buffer)))
122 (set-extent-property overlay 'overlay t)
124 (set-extent-property overlay 'start-open t)
125 (set-extent-property overlay 'start-closed t))
127 (set-extent-property overlay 'end-closed t)
128 (set-extent-property overlay 'end-open t))
131 (defun move-overlay (overlay beg end &optional buffer)
132 "Set the endpoints of OVERLAY to BEG and END in BUFFER.
133 If BUFFER is omitted, leave OVERLAY in the same buffer it inhabits now.
134 If BUFFER is omitted, and OVERLAY is in no buffer, put it in the current
138 BEG and END will be normalized so 1 <= BEG <= END <= \(1+ \(length BUFFER)).
139 If BUFFER is nil, the current buffer is assumed. If BEG is
140 greater than END, exchange their value."
142 (check-argument-type 'overlayp overlay)
144 (setq buffer (extent-object overlay)))
145 (multiple-value-setq (beg end buffer)
146 (overlay-normalize-begin-end-buffer beg end buffer))
147 (check-argument-type 'bufferp buffer)
149 (extent-property overlay 'evaporate)
150 (delete-overlay overlay))
152 (setq beg (prog1 end (setq end beg))))
153 (set-extent-endpoints overlay beg end buffer)
156 (defun delete-overlay (overlay)
157 "Delete the overlay OVERLAY from its buffer."
158 (check-argument-type 'overlayp overlay)
159 (detach-extent overlay)
162 (defun overlay-start (overlay)
163 "Return the position at which OVERLAY starts."
164 (check-argument-type 'overlayp overlay)
165 (extent-start-position overlay))
167 (defun overlay-end (overlay)
168 "Return the position at which OVERLAY ends."
169 (check-argument-type 'overlayp overlay)
170 (extent-end-position overlay))
172 (defun overlay-buffer (overlay)
173 "Return the buffer OVERLAY belongs to."
174 (check-argument-type 'overlayp overlay)
175 (extent-object overlay))
177 (defun overlay-properties (overlay)
178 "Return a list of the properties on OVERLAY.
179 This is a copy of OVERLAY's plist; modifying its conses has no effect on
181 (check-argument-type 'overlayp overlay)
182 (extent-properties overlay))
184 (defun overlays-at (pos &optional buffer)
185 "Return a list of the overlays that contain position POS."
186 (overlays-in pos pos buffer))
188 (defun overlays-in (beg end &optional buffer)
189 "Return a list of the overlays that overlap the region BEG ... END.
190 Overlap means that at least one character is contained within the overlay
191 and also contained within the specified region.
192 Empty overlays are included in the result if they are located at BEG
193 or between BEG and END.
195 BEG and END will be normalized so 1 <= BEG <= END <= \(1+ \(length CURRENT-BUFFER))."
196 (setq beg (overlay-normalize-pos beg buffer)
197 end (overlay-normalize-pos end buffer))
198 (mapcar-extents #'identity nil nil beg end
199 'all-extents-closed-open 'overlay))
201 (defun next-overlay-change (pos &optional buffer)
202 "Return the next position after POS where an overlay starts or ends.
203 If there are no more overlay boundaries after POS, return (point-max).
205 POS will be normalized so 1 <= POS <= \(1+ \(length CURRENT-BUFFER))."
206 (let ((next (point-max buffer))
208 (setq pos (overlay-normalize-pos pos buffer))
210 (lambda (overlay ignore)
211 (when (or (and (< (setq tmp (extent-start-position overlay)) next)
213 (and (< (setq tmp (extent-end-position overlay)) next)
217 nil pos nil nil 'all-extents-closed-open 'overlay)
220 (defun previous-overlay-change (pos &optional buffer)
221 "Return the previous position before POS where an overlay starts or ends.
222 If there are no more overlay boundaries before POS, return (point-min).
224 POS will be normalized so 1 <= POS <= \(1+ \(length CURRENT-BUFFER))."
225 (let ((prev (point-min buffer))
227 (setq pos (overlay-normalize-pos pos buffer))
229 (lambda (overlay ignore)
230 (when (or (and (> (setq tmp (extent-end-position overlay)) prev)
232 (and (> (setq tmp (extent-start-position overlay)) prev)
236 nil nil pos nil 'all-extents-closed-open 'overlay)
239 (defun overlay-lists ()
240 "Return a pair of lists giving all the overlays of the current buffer.
241 The car has all the overlays before the overlay center;
242 the cdr has all the overlays after the overlay center.
243 Recentering overlays moves overlays between these lists.
244 The lists you get are copies, so that changing them has no effect.
245 However, the overlays you get are the real objects that the buffer uses."
246 (or (boundp 'xemacs-internal-overlay-center-pos)
247 (overlay-recenter (1+ (/ (- (point-max) (point-min)) 2))))
248 (let ((pos xemacs-internal-overlay-center-pos)
250 (map-extents (lambda (overlay ignore)
251 (if (> pos (extent-end-position overlay))
252 (push overlay before)
253 (push overlay after))
255 nil nil nil nil 'all-extents-closed-open 'overlay)
256 (cons (nreverse before) (nreverse after))))
258 (defun overlay-recenter (pos &optional buffer)
259 "Recenter the overlays of the current buffer around position POS.
261 POS will be normalized so 1 <= POS <= \(1+ \(length CURRENT-BUFFER))."
262 (setq pos (overlay-normalize-pos pos buffer))
263 (set (make-local-variable 'xemacs-internal-overlay-center-pos) pos))
265 (defun overlay-get (overlay prop)
266 "Get the property of overlay OVERLAY with property name PROP."
267 (check-argument-type 'overlayp overlay)
268 (let ((value (extent-property overlay prop))
270 (if (and (null value)
271 (setq category (extent-property overlay 'category)))
275 (defun overlay-put (overlay prop value)
276 "Set one property of overlay OVERLAY: give property PROP value VALUE."
277 (check-argument-type 'overlayp overlay)
278 (cond ((eq prop 'evaporate)
279 (set-extent-property overlay 'detachable value))
280 ((eq prop 'before-string)
281 (set-extent-property overlay 'begin-glyph
282 (make-glyph (vector 'string :data value))))
283 ((eq prop 'after-string)
284 (set-extent-property overlay 'end-glyph
285 (make-glyph (vector 'string :data value))))
286 ((eq prop 'local-map)
287 (set-extent-property overlay 'keymap value))
288 ((memq prop '(window insert-in-front-hooks insert-behind-hooks
290 (error "cannot support overlay '%s property under XEmacs"
292 (set-extent-property overlay prop value))
294 (defun copy-overlay (o)
295 "Return a copy of overlay O."
296 (let ((o1 (if (overlay-buffer o)
297 (make-overlay (overlay-start o) (overlay-end o)
298 ;; FIXME: there's no easy way to find the
299 ;; insertion-type of the two markers.
301 (let ((o1 (make-overlay (point-min) (point-min))))
304 (props (overlay-properties o)))
306 (overlay-put o1 (pop props) (pop props)))
309 (defun remove-overlays (&optional beg end name val)
310 "Clear BEG and END of overlays whose property NAME has value VAL.
311 Overlays might be moved and/or split.
312 BEG and END default respectively to the beginning and end of buffer."
313 ;; This speeds up the loops over overlays.
314 (unless beg (setq beg (point-min)))
315 (unless end (setq end (point-max)))
316 (overlay-recenter end)
318 (setq beg (prog1 end (setq end beg))))
320 (dolist (o (overlays-in beg end))
321 (when (eq (overlay-get o name) val)
322 ;; Either push this overlay outside beg...end
323 ;; or split it to exclude beg...end
324 ;; or delete it entirely (if it is contained in beg...end).
325 (if (< (overlay-start o) beg)
326 (if (> (overlay-end o) end)
328 (move-overlay (copy-overlay o)
329 (overlay-start o) beg)
330 (move-overlay o end (overlay-end o)))
331 (move-overlay o (overlay-start o) beg))
332 (if (> (overlay-end o) end)
333 (move-overlay o end (overlay-end o))
334 (delete-overlay o)))))))
339 ;;; overlay.el ends here