Mercurial > hg > xemacs-beta
annotate lisp/text-props.el @ 5617:b0d712bbc2a6
The "flush" face property.
-------------------- ChangeLog entries follow: --------------------
src/ChangeLog addition:
2011-12-23 Didier Verna <didier@xemacs.org>
* faces.h (struct Lisp_Face): New 'flush slot.
* faces.h (struct face_cachel): New 'flush and 'flush_specified
flags.
* faces.h (WINDOW_FACE_CACHEL_FLUSH_P):
* faces.h (FACE_FLUSH_P): New macros.
* faces.c: Declare Qflush.
* lisp.h: Externalize it.
* faces.c (syms_of_faces): Define it.
* faces.c (vars_of_faces): Update built-in face specifiers.
* faces.c (complex_vars_of_faces): Update specifier fallbacks.
* faces.c (mark_face):
* faces.c (face_equal):
* faces.c (face_getprop):
* faces.c (face_putprop):
* faces.c (face_remprop):
* faces.c (face_plist):
* faces.c (reset_face):
* faces.c (update_face_inheritance_mapper):
* faces.c (Fmake_face):
* faces.c (update_face_cachel_data):
* faces.c (merge_face_cachel_data):
* faces.c (Fcopy_face):
* fontcolor.c (face_boolean_validate): Handle the flush property.
* redisplay.h (struct display_line): Rename 'default_findex slot to
clearer name 'clear_findex.
* redisplay.h (DISPLAY_LINE_INIT): Update accordingly.
* redisplay-output.c (compare_display_blocks):
* redisplay-output.c (output_display_line):
* redisplay-output.c (redisplay_output_window):
* redisplay.c (regenerate_window_extents_only_changed):
* redisplay.c (regenerate_window_incrementally): Update the
comparison tests between the current and desired display lines to
cope for different 'clear_findex values.
* redisplay.c (create_text_block): Initialize the display line's
'clear_findex slot to DEFAULT_INDEX. Record a new 'clear_findex
value when we encounter a newline character displayed in a flushed
face.
* redisplay.c (create_string_text_block): Record a new
'clear_findex value when we encounter a newline character
displayed in a flushed face.
lisp/ChangeLog addition:
2011-12-23 Didier Verna <didier@xemacs.org>
* cl-macs.el (face-flush-p): New defsetf.
* faces.el (set-face-property): Document the flush property.
* faces.el (face-flush-p): New function.
* faces.el (set-face-flush-p): New function.
* faces.el (face-equal):
* cus-face.el (custom-face-attributes):
* x-faces.el (x-init-face-from-resources):
* x-faces.el (make-face-x-resource-internal): Handle the flush
property.
author | Didier Verna <didier@xemacs.org> |
---|---|
date | Fri, 23 Dec 2011 10:56:16 +0100 |
parents | 308d34e9f07d |
children |
rev | line source |
---|---|
428 | 1 ;;; text-props.el --- implements properties of characters |
2 | |
3 ;; Copyright (C) 1993-4, 1997 Free Software Foundation, Inc. | |
4 ;; Copyright (C) 1995 Amdahl Corporation. | |
5 ;; Copyright (C) 1995 Ben Wing. | |
6 | |
7 ;; Author: Jamie Zawinski <jwz@jwz.org> | |
8 ;; Maintainer: XEmacs Development Team | |
9 ;; Keywords: extensions, wp, faces, dumped | |
10 | |
11 ;; This file is part of XEmacs. | |
12 | |
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
1275
diff
changeset
|
13 ;; XEmacs is free software: you can redistribute it and/or modify it |
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
1275
diff
changeset
|
14 ;; under the terms of the GNU General Public License as published by the |
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
1275
diff
changeset
|
15 ;; Free Software Foundation, either version 3 of the License, or (at your |
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
1275
diff
changeset
|
16 ;; option) any later version. |
428 | 17 |
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
1275
diff
changeset
|
18 ;; XEmacs is distributed in the hope that it will be useful, but WITHOUT |
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
1275
diff
changeset
|
19 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
1275
diff
changeset
|
20 ;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
1275
diff
changeset
|
21 ;; for more details. |
428 | 22 |
23 ;; You should have received a copy of the GNU General Public License | |
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
1275
diff
changeset
|
24 ;; along with XEmacs. If not, see <http://www.gnu.org/licenses/>. |
428 | 25 |
26 ;;; Synched up with: Not in FSF. | |
27 | |
28 ;;; Commentary: | |
29 | |
30 ;; This file is dumped with XEmacs. | |
31 | |
32 ;; This is a nearly complete implementation of the FSF19 text properties API. | |
33 ;; Please let me know if you notice any differences in behavior between | |
34 ;; this implementation and the FSF implementation. | |
35 | |
36 ;; However, keep in mind that this interface has been implemented because it | |
37 ;; is useful. Compatibility with code written for FSF19 is a secondary goal | |
38 ;; to having a clean and useful interface. | |
39 | |
40 ;; The cruftier parts of the FSF API, such as the special handling of | |
41 ;; properties like `mouse-face', `front-sticky', and other properties whose | |
42 ;; value is a list of names of *other* properties set at this position, are | |
43 ;; not implemented. The reason for this is that if you feel you need that | |
44 ;; kind of functionality, it's a good hint that you should be using extents | |
45 ;; instead of text properties. | |
46 | |
47 ;; When should I use Text Properties, and when should I use Extents? | |
48 ;; ================================================================== | |
49 | |
50 ;; If you are putting a `button' or `hyperlink' of some kind into a buffer, | |
51 ;; the most natural interface is one which deals with properties of regions | |
52 ;; with explicit endpoints that behave more-or-less like markers. That is | |
53 ;; what `make-extent', `extent-at', and `extent-property' are for. | |
54 | |
55 ;; If you are dealing with styles of text, where things do not have explicit | |
56 ;; endpoints (as is done in font-lock.el and shell-font.el) or if you want to | |
57 ;; partition a buffer (that is, change some attribute of a range from one | |
58 ;; value to another without disturbing the properties outside of that range) | |
59 ;; then an interface that deals with properties of characters may be most | |
60 ;; natural. | |
61 | |
62 ;; Another way of thinking of it is, do you care where the endpoints of the | |
63 ;; region are? If you do, then you should use extents. If it's ok for the | |
64 ;; region to become divided, and for two regions with identical properties to | |
65 ;; be merged into one region, then you might want to use text properties. | |
66 | |
67 ;; Some applications want the attributes they add to be copied by the killing | |
68 ;; and yanking commands, and some do not. This is orthogonal to whether text | |
69 ;; properties or extents are used. Remember that text properties are | |
70 ;; implemented in terms of extents, so anything you can do with one you can | |
71 ;; do with the other. It's just a matter of which way of creating and | |
72 ;; managing them is most appropriate to your application. | |
73 | |
74 ;; Implementation details: | |
75 ;; ======================= | |
76 | |
77 ;; This package uses extents with a non-nil 'text-prop property. It assumes | |
78 ;; free reign over the endpoints of any extent with that property. It will | |
79 ;; not alter any extent which does not have that property. | |
80 | |
81 ;; Right now, the text-property functions create one extent for each distinct | |
82 ;; property; that is, if a range of text has two text-properties on it, there | |
83 ;; will be two extents. As the set of text-properties is going to be small, | |
84 ;; this is probably not a big deal. It would be possible to share extents. | |
85 | |
86 ;; One tricky bit is that undo/kill/yank must be made to not fragment things: | |
87 ;; these extents must not be allowed to overlap. We accomplish this by using | |
88 ;; a custom `paste-function' property on the extents. | |
89 | |
90 ;; shell-font.el and font-lock.el could put-text-property to attach fonts to | |
91 ;; the buffer. However, what these packages are interested in is the | |
92 ;; efficient extent partitioning behavior which this code exhibits, not the | |
93 ;; duplicability aspect of it. In fact, either of these packages could be | |
94 ;; implemented by creating a one-character non-expandable extent for each | |
95 ;; character in the buffer, except that that would be extremely wasteful of | |
96 ;; memory. (Redisplay performance would be fine, however.) | |
97 | |
98 ;; If these packages were to use put-text-property to make the extents, then | |
99 ;; when one copied text from a shell buffer or a font-locked source buffer | |
100 ;; and pasted it somewhere else (a sendmail buffer, or a buffer not in | |
101 ;; font-lock mode) then the fonts would follow, and there's no easy way to | |
102 ;; get rid of them (other than pounding out a call to put-text-property by | |
103 ;; hand.) This is annoying. Maybe it wouldn't be so annoying if there was a | |
104 ;; more general set of commands for handling styles of text (in fact, if | |
105 ;; there were such a thing, copying the fonts would probably be exactly what | |
106 ;; one wanted) but we aren't there yet. So these packages use the interface | |
107 ;; of `put-nonduplicable-text-property' which is the same, except that it | |
108 ;; doesn't make duplicable extents. | |
109 | |
110 ;; `put-text-property' and `put-nonduplicable-text-property' don't get along: | |
111 ;; they will interfere with each other, reusing each others' extents without | |
112 ;; checking that the "duplicableness" is correct. This is a bug, but it's | |
113 ;; one that I don't care enough to fix this right now. | |
114 | |
115 ;;; Code: | |
116 | |
117 (defun set-text-properties (start end props &optional buffer-or-string) | |
118 "You should NEVER use this function. It is ideologically blasphemous. | |
119 It is provided only to ease porting of broken FSF Emacs programs. | |
120 Instead, use `remove-text-properties' to remove the specific properties | |
121 you do not want. | |
122 | |
123 Completely replace properties of text from START to END. | |
124 The third argument PROPS is the new property list. | |
125 The optional fourth argument, BUFFER-OR-STRING, | |
126 is the string or buffer containing the text." | |
127 (map-extents #'(lambda (extent ignored) | |
128 ;; #### dmoore - shouldn't this use | |
129 ;; (extent-start-position extent) | |
130 ;; (extent-end-position extent) | |
131 (remove-text-properties start end | |
132 (list (extent-property extent | |
133 'text-prop) | |
134 nil) | |
135 buffer-or-string) | |
136 nil) | |
137 buffer-or-string start end nil nil 'text-prop) | |
138 (add-text-properties start end props buffer-or-string)) | |
139 | |
140 | |
141 ;;; The following functions can probably stay in lisp, since they're so simple. | |
142 | |
143 ;(defun get-text-property (pos prop &optional buffer) | |
144 ; "Returns the value of the PROP property at the given position." | |
145 ; (let ((e (extent-at pos buffer prop))) | |
146 ; (if e | |
147 ; (extent-property e prop) | |
148 ; nil))) | |
149 | |
150 (defun extent-properties-at-1 (position buffer-or-string text-props-only) | |
151 (let ((extent nil) | |
152 (props nil) | |
153 new-props) | |
154 (while (setq extent (extent-at position buffer-or-string | |
155 (if text-props-only 'text-prop nil) | |
156 extent)) | |
157 (if text-props-only | |
158 ;; Only return the one prop which the `text-prop' property points at. | |
159 (let ((prop (extent-property extent 'text-prop))) | |
160 (setq new-props (list prop (extent-property extent prop)))) | |
161 ;; Return all the properties... | |
162 (setq new-props (extent-properties extent)) | |
163 ;; ...but! Don't return the `begin-glyph' or `end-glyph' properties | |
164 ;; unless the position is exactly at the appropriate endpoint. Yeah, | |
165 ;; this is kind of a kludge. | |
166 ;; #### Bug, this doesn't work for end-glyphs (on end-open extents) | |
167 ;; because we've already passed the extent with the glyph by the time | |
168 ;; it's appropriate to return the glyph. We could return the end | |
169 ;; glyph one character early I guess... But then next-property-change | |
170 ;; would have to stop one character early as well. It could back up | |
171 ;; when it hit an end-glyph... | |
172 ;; #### Another bug, if there are multiple glyphs at the same position, | |
173 ;; we only see the first one. | |
174 (cond ((or (extent-begin-glyph extent) (extent-end-glyph extent)) | |
175 (if (/= position (if (extent-property extent 'begin-glyph) | |
176 (extent-start-position extent) | |
177 (extent-end-position extent))) | |
178 (let ((rest new-props) | |
179 prev) | |
180 (while rest | |
181 (cond ((or (eq (car rest) 'begin-glyph) | |
182 (eq (car rest) 'end-glyph)) | |
183 (if prev | |
184 (setcdr prev (cdr (cdr rest))) | |
185 (setq new-props (cdr (cdr new-props)))) | |
186 (setq rest nil))) | |
187 (setq prev rest | |
188 rest (cdr rest)))))))) | |
189 (cond ((null props) | |
190 (setq props new-props)) | |
191 (t | |
192 (while new-props | |
193 (or (getf props (car new-props)) | |
194 (setq props (cons (car new-props) | |
195 (cons (car (cdr new-props)) | |
196 props)))) | |
197 (setq new-props (cdr (cdr new-props))))))) | |
198 props)) | |
199 | |
200 (defun extent-properties-at (position &optional object) | |
201 "Return the properties of the character at the given position in OBJECT. | |
202 OBJECT is either a string or a buffer. The properties of overlapping | |
203 extents are merged. The returned value is a property list, some of | |
204 which may be shared with other structures. You must not modify it. | |
205 | |
206 If POSITION is at the end of OBJECT, the value is nil. | |
207 | |
208 This returns all properties on all extents. | |
209 See also `text-properties-at'." | |
210 (extent-properties-at-1 position object nil)) | |
211 | |
212 (defun text-properties-at (position &optional object) | |
213 "Return the properties of the character at the given position in OBJECT. | |
214 OBJECT is either a string or a buffer. The properties of overlapping | |
215 extents are merged. The returned value is a property list, some of | |
216 which may be shared with other structures. You must not modify it. | |
217 | |
218 If POSITION is at the end of OBJECT, the value is nil. | |
219 | |
220 This returns only those properties added with `put-text-property'. | |
221 See also `extent-properties-at'." | |
222 (extent-properties-at-1 position object t)) | |
223 | |
224 (defun text-property-any (start end prop value &optional buffer-or-string) | |
225 "Check text from START to END to see if PROP is ever `eq' to VALUE. | |
226 If so, return the position of the first character whose PROP is `eq' | |
227 to VALUE. Otherwise return nil. | |
228 The optional fifth argument, BUFFER-OR-STRING, is the buffer or string | |
229 containing the text and defaults to the current buffer." | |
230 (while (and start (< start end) | |
231 (not (eq value (get-text-property start prop buffer-or-string)))) | |
232 (setq start (next-single-property-change start prop buffer-or-string end))) | |
233 ;; we have to insert a special check for end due to the illogical | |
234 ;; definition of next-single-property-change (blame FSF for this). | |
1275 | 235 (if (and start (>= start end)) nil start)) |
428 | 236 |
237 (defun text-property-not-all (start end prop value &optional buffer-or-string) | |
238 "Check text from START to END to see if PROP is ever not `eq' to VALUE. | |
239 If so, return the position of the first character whose PROP is not | |
240 `eq' to VALUE. Otherwise, return nil. | |
241 The optional fifth argument, BUFFER-OR-STRING, is the buffer or string | |
242 containing the text and defaults to the current buffer." | |
243 (if (not (eq value (get-text-property start prop buffer-or-string))) | |
244 start | |
245 (let ((retval (next-single-property-change start prop | |
246 buffer-or-string end))) | |
247 ;; we have to insert a special check for end due to the illogical | |
248 ;; definition of previous-single-property-change (blame FSF for this). | |
1275 | 249 (if (and retval (>= retval end)) nil retval)))) |
428 | 250 |
251 ;; Older versions that only work sometimes (when VALUE is non-nil | |
252 ;; for text-property-any, and maybe only when VALUE is nil for | |
253 ;; text-property-not-all). They might be faster in those cases, | |
254 ;; but that's not obvious. | |
255 | |
256 ;(defun text-property-any (start end prop value &optional buffer) | |
257 ; "Check text from START to END to see if PROP is ever `eq' to VALUE. | |
258 ;If so, return the position of the first character whose PROP is `eq' | |
259 ;to VALUE. Otherwise return nil." | |
260 ; ;; #### what should (text-property-any x y 'foo nil) return when there | |
261 ; ;; is no foo property between x and y? Either t or nil seems sensible, | |
262 ; ;; since a character with a property of nil is indistinguishable from | |
263 ; ;; a character without that property set. | |
264 ; (map-extents | |
265 ; #'(lambda (e ignore) | |
266 ; (if (eq value (extent-property e prop)) | |
267 ; ;; return non-nil to stop mapping | |
268 ; (max start (extent-start-position e)) | |
269 ; nil)) | |
270 ; nil start end buffer)) | |
271 ; | |
272 ;(defun text-property-not-all (start end prop value &optional buffer) | |
273 ; "Check text from START to END to see if PROP is ever not `eq' to VALUE. | |
274 ;If so, return the position of the first character whose PROP is not | |
275 ;`eq' to VALUE. Otherwise, return nil." | |
276 ; (let (maxend) | |
277 ; (map-extents | |
278 ; #'(lambda (e ignore) | |
279 ; ;;### no, actually, this is harder. We need to collect all props | |
280 ; ;; for a given character, and then determine whether no extent | |
281 ; ;; contributes the given value. Doing this without consing lots | |
282 ; ;; of lists is the tricky part. | |
283 ; (if (eq value (extent-property e prop)) | |
284 ; (progn | |
285 ; (setq maxend (extent-end-position e)) | |
286 ; nil) | |
287 ; (max start maxend))) | |
288 ; nil start end buffer))) | |
289 | |
290 (defun next-property-change (pos &optional buffer-or-string limit) | |
291 "Return the position of next property change. | |
292 Scans forward from POS in BUFFER-OR-STRING (defaults to the current buffer) | |
293 until it finds a change in some text property, then returns the position of | |
294 the change. | |
295 Returns nil if the properties remain unchanged all the way to the end. | |
296 If the value is non-nil, it is a position greater than POS, never equal. | |
297 If the optional third argument LIMIT is non-nil, don't search | |
298 past position LIMIT; return LIMIT if nothing is found before LIMIT. | |
299 If two or more extents with conflicting non-nil values for a property overlap | |
300 a particular character, it is undefined which value is considered to be | |
301 the value of the property. (Note that this situation will not happen if | |
302 you always use the text-property primitives.)" | |
303 (let ((limit-was-nil (null limit))) | |
304 (or limit (setq limit (if (bufferp buffer-or-string) | |
305 (point-max buffer-or-string) | |
306 (length buffer-or-string)))) | |
307 (let ((value (extent-properties-at pos buffer-or-string))) | |
308 (while | |
309 (and (< (setq pos (next-extent-change pos buffer-or-string)) limit) | |
310 (plists-eq value (extent-properties-at pos buffer-or-string))))) | |
311 (if (< pos limit) pos | |
312 (if limit-was-nil nil | |
313 limit)))) | |
314 | |
315 (defun previous-property-change (pos &optional buffer-or-string limit) | |
316 "Return the position of previous property change. | |
317 Scans backward from POS in BUFFER-OR-STRING (defaults to the current buffer) | |
318 until it finds a change in some text property, then returns the position of | |
319 the change. | |
320 Returns nil if the properties remain unchanged all the way to the beginning. | |
321 If the value is non-nil, it is a position less than POS, never equal. | |
322 If the optional third argument LIMIT is non-nil, don't search back | |
323 past position LIMIT; return LIMIT if nothing is found until LIMIT. | |
324 If two or more extents with conflicting non-nil values for a property overlap | |
325 a particular character, it is undefined which value is considered to be | |
326 the value of the property. (Note that this situation will not happen if | |
327 you always use the text-property primitives.)" | |
328 (let ((limit-was-nil (null limit))) | |
329 (or limit (setq limit (if (bufferp buffer-or-string) | |
330 (point-min buffer-or-string) | |
331 0))) | |
332 (let ((value (extent-properties-at (1- pos) buffer-or-string))) | |
333 (while | |
334 (and (> (setq pos (previous-extent-change pos buffer-or-string)) | |
335 limit) | |
336 (plists-eq value (extent-properties-at (1- pos) | |
337 buffer-or-string))))) | |
338 (if (> pos limit) pos | |
339 (if limit-was-nil nil | |
340 limit)))) | |
341 | |
342 (defun text-property-bounds (pos prop &optional object at-flag) | |
343 "Return the bounds of property PROP at POS. | |
344 This returns a cons (START . END) of the largest region of text containing | |
345 POS which has a non-nil value for PROP. The return value is nil if POS | |
346 does not have a non-nil value for PROP. OBJECT specifies the buffer | |
347 or string to search in. Optional arg AT-FLAG controls what \"at POS\" | |
348 means, and has the same meaning as for `extent-at'." | |
349 (or object (setq object (current-buffer))) | |
350 (and (get-char-property pos prop object at-flag) | |
351 (let ((begin (if (stringp object) 0 (point-min object))) | |
352 (end (if (stringp object) (length object) (point-max object)))) | |
353 (cons (previous-single-property-change (1+ pos) prop object begin) | |
354 (next-single-property-change pos prop object end))))) | |
355 | |
356 (defun next-text-property-bounds (count pos prop &optional object) | |
357 "Return the COUNTth bounded property region of property PROP after POS. | |
358 If COUNT is less than zero, search backwards. This returns a cons | |
359 \(START . END) of the COUNTth maximal region of text that begins after POS | |
360 \(starts before POS) and has a non-nil value for PROP. If there aren't | |
361 that many regions, nil is returned. OBJECT specifies the buffer or | |
362 string to search in." | |
363 (or object (setq object (current-buffer))) | |
364 (let ((begin (if (stringp object) 0 (point-min object))) | |
365 (end (if (stringp object) (length object) (point-max object)))) | |
366 (catch 'hit-end | |
367 (if (> count 0) | |
368 (progn | |
369 (while (> count 0) | |
370 (if (>= pos end) | |
371 (throw 'hit-end nil) | |
372 (and (get-char-property pos prop object) | |
373 (setq pos (next-single-property-change pos prop | |
374 object end))) | |
375 (setq pos (next-single-property-change pos prop object end))) | |
376 (setq count (1- count))) | |
377 (and (< pos end) | |
378 (cons pos (next-single-property-change pos prop object end)))) | |
379 (while (< count 0) | |
380 (if (<= pos begin) | |
381 (throw 'hit-end nil) | |
382 (and (get-char-property (1- pos) prop object) | |
383 (setq pos (previous-single-property-change pos prop | |
384 object begin))) | |
385 (setq pos (previous-single-property-change pos prop object | |
386 begin))) | |
387 (setq count (1+ count))) | |
388 (and (> pos begin) | |
389 (cons (previous-single-property-change pos prop object begin) | |
390 pos)))))) | |
391 | |
392 ;(defun detach-all-extents (&optional buffer) | |
393 ; (map-extents #'(lambda (x i) (detach-extent x) nil) | |
394 ; buffer)) | |
395 | |
396 | |
397 (provide 'text-props) | |
398 | |
399 ;;; text-props.el ends here |