diff options
| author | Eli Zaretskii | 2013-03-28 20:13:59 +0200 |
|---|---|---|
| committer | Eli Zaretskii | 2013-03-28 20:13:59 +0200 |
| commit | d76bf86f438d4f5f9fe493ab76f02ffc78f3ae2e (patch) | |
| tree | 04fa8bc7bd2058a316a7ee30f8741d25bfd0b060 /src/textprop.c | |
| parent | 2ef26ceb192c7683754cf0b4aa3087f501254332 (diff) | |
| parent | e74aeda863cd6896e06e92586f87b45d63d67d15 (diff) | |
| download | emacs-d76bf86f438d4f5f9fe493ab76f02ffc78f3ae2e.tar.gz emacs-d76bf86f438d4f5f9fe493ab76f02ffc78f3ae2e.zip | |
Merge from trunk and resolve conflicts.
Diffstat (limited to 'src/textprop.c')
| -rw-r--r-- | src/textprop.c | 287 |
1 files changed, 171 insertions, 116 deletions
diff --git a/src/textprop.c b/src/textprop.c index 379eafb73f7..cc364d5a38c 100644 --- a/src/textprop.c +++ b/src/textprop.c | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | /* Interface code for dealing with text properties. | 1 | /* Interface code for dealing with text properties. |
| 2 | Copyright (C) 1993-1995, 1997, 1999-2012 Free Software Foundation, Inc. | 2 | Copyright (C) 1993-1995, 1997, 1999-2013 Free Software Foundation, |
| 3 | Inc. | ||
| 3 | 4 | ||
| 4 | This file is part of GNU Emacs. | 5 | This file is part of GNU Emacs. |
| 5 | 6 | ||
| @@ -59,7 +60,7 @@ Lisp_Object Qinvisible, Qintangible, Qmouse_face; | |||
| 59 | static Lisp_Object Qread_only; | 60 | static Lisp_Object Qread_only; |
| 60 | Lisp_Object Qminibuffer_prompt; | 61 | Lisp_Object Qminibuffer_prompt; |
| 61 | 62 | ||
| 62 | /* Sticky properties */ | 63 | /* Sticky properties. */ |
| 63 | Lisp_Object Qfront_sticky, Qrear_nonsticky; | 64 | Lisp_Object Qfront_sticky, Qrear_nonsticky; |
| 64 | 65 | ||
| 65 | /* If o1 is a cons whose cdr is a cons, return non-zero and set o2 to | 66 | /* If o1 is a cons whose cdr is a cons, return non-zero and set o2 to |
| @@ -85,8 +86,18 @@ text_read_only (Lisp_Object propval) | |||
| 85 | xsignal0 (Qtext_read_only); | 86 | xsignal0 (Qtext_read_only); |
| 86 | } | 87 | } |
| 87 | 88 | ||
| 89 | /* Prepare to modify the region of BUFFER from START to END. */ | ||
| 90 | |||
| 91 | static void | ||
| 92 | modify_region (Lisp_Object buffer, Lisp_Object start, Lisp_Object end) | ||
| 93 | { | ||
| 94 | struct buffer *buf = XBUFFER (buffer), *old = current_buffer; | ||
| 95 | |||
| 96 | set_buffer_internal (buf); | ||
| 97 | modify_region_1 (XINT (start), XINT (end), true); | ||
| 98 | set_buffer_internal (old); | ||
| 99 | } | ||
| 88 | 100 | ||
| 89 | |||
| 90 | /* Extract the interval at the position pointed to by BEGIN from | 101 | /* Extract the interval at the position pointed to by BEGIN from |
| 91 | OBJECT, a string or buffer. Additionally, check that the positions | 102 | OBJECT, a string or buffer. Additionally, check that the positions |
| 92 | pointed to by BEGIN and END are within the bounds of OBJECT, and | 103 | pointed to by BEGIN and END are within the bounds of OBJECT, and |
| @@ -114,9 +125,10 @@ text_read_only (Lisp_Object propval) | |||
| 114 | #define hard 1 | 125 | #define hard 1 |
| 115 | 126 | ||
| 116 | INTERVAL | 127 | INTERVAL |
| 117 | validate_interval_range (Lisp_Object object, Lisp_Object *begin, Lisp_Object *end, int force) | 128 | validate_interval_range (Lisp_Object object, Lisp_Object *begin, |
| 129 | Lisp_Object *end, bool force) | ||
| 118 | { | 130 | { |
| 119 | register INTERVAL i; | 131 | INTERVAL i; |
| 120 | ptrdiff_t searchpos; | 132 | ptrdiff_t searchpos; |
| 121 | 133 | ||
| 122 | CHECK_STRING_OR_BUFFER (object); | 134 | CHECK_STRING_OR_BUFFER (object); |
| @@ -187,14 +199,14 @@ validate_plist (Lisp_Object list) | |||
| 187 | 199 | ||
| 188 | if (CONSP (list)) | 200 | if (CONSP (list)) |
| 189 | { | 201 | { |
| 190 | register int i; | 202 | bool odd_length = 0; |
| 191 | register Lisp_Object tail; | 203 | Lisp_Object tail; |
| 192 | for (i = 0, tail = list; CONSP (tail); i++) | 204 | for (tail = list; CONSP (tail); tail = XCDR (tail)) |
| 193 | { | 205 | { |
| 194 | tail = XCDR (tail); | 206 | odd_length ^= 1; |
| 195 | QUIT; | 207 | QUIT; |
| 196 | } | 208 | } |
| 197 | if (i & 1) | 209 | if (odd_length) |
| 198 | error ("Odd length text property list"); | 210 | error ("Odd length text property list"); |
| 199 | return list; | 211 | return list; |
| 200 | } | 212 | } |
| @@ -202,20 +214,19 @@ validate_plist (Lisp_Object list) | |||
| 202 | return Fcons (list, Fcons (Qnil, Qnil)); | 214 | return Fcons (list, Fcons (Qnil, Qnil)); |
| 203 | } | 215 | } |
| 204 | 216 | ||
| 205 | /* Return nonzero if interval I has all the properties, | 217 | /* Return true if interval I has all the properties, |
| 206 | with the same values, of list PLIST. */ | 218 | with the same values, of list PLIST. */ |
| 207 | 219 | ||
| 208 | static int | 220 | static bool |
| 209 | interval_has_all_properties (Lisp_Object plist, INTERVAL i) | 221 | interval_has_all_properties (Lisp_Object plist, INTERVAL i) |
| 210 | { | 222 | { |
| 211 | register Lisp_Object tail1, tail2, sym1; | 223 | Lisp_Object tail1, tail2; |
| 212 | register int found; | ||
| 213 | 224 | ||
| 214 | /* Go through each element of PLIST. */ | 225 | /* Go through each element of PLIST. */ |
| 215 | for (tail1 = plist; CONSP (tail1); tail1 = Fcdr (XCDR (tail1))) | 226 | for (tail1 = plist; CONSP (tail1); tail1 = Fcdr (XCDR (tail1))) |
| 216 | { | 227 | { |
| 217 | sym1 = XCAR (tail1); | 228 | Lisp_Object sym1 = XCAR (tail1); |
| 218 | found = 0; | 229 | bool found = 0; |
| 219 | 230 | ||
| 220 | /* Go through I's plist, looking for sym1 */ | 231 | /* Go through I's plist, looking for sym1 */ |
| 221 | for (tail2 = i->plist; CONSP (tail2); tail2 = Fcdr (XCDR (tail2))) | 232 | for (tail2 = i->plist; CONSP (tail2); tail2 = Fcdr (XCDR (tail2))) |
| @@ -238,13 +249,13 @@ interval_has_all_properties (Lisp_Object plist, INTERVAL i) | |||
| 238 | return 1; | 249 | return 1; |
| 239 | } | 250 | } |
| 240 | 251 | ||
| 241 | /* Return nonzero if the plist of interval I has any of the | 252 | /* Return true if the plist of interval I has any of the |
| 242 | properties of PLIST, regardless of their values. */ | 253 | properties of PLIST, regardless of their values. */ |
| 243 | 254 | ||
| 244 | static int | 255 | static bool |
| 245 | interval_has_some_properties (Lisp_Object plist, INTERVAL i) | 256 | interval_has_some_properties (Lisp_Object plist, INTERVAL i) |
| 246 | { | 257 | { |
| 247 | register Lisp_Object tail1, tail2, sym; | 258 | Lisp_Object tail1, tail2, sym; |
| 248 | 259 | ||
| 249 | /* Go through each element of PLIST. */ | 260 | /* Go through each element of PLIST. */ |
| 250 | for (tail1 = plist; CONSP (tail1); tail1 = Fcdr (XCDR (tail1))) | 261 | for (tail1 = plist; CONSP (tail1); tail1 = Fcdr (XCDR (tail1))) |
| @@ -263,10 +274,10 @@ interval_has_some_properties (Lisp_Object plist, INTERVAL i) | |||
| 263 | /* Return nonzero if the plist of interval I has any of the | 274 | /* Return nonzero if the plist of interval I has any of the |
| 264 | property names in LIST, regardless of their values. */ | 275 | property names in LIST, regardless of their values. */ |
| 265 | 276 | ||
| 266 | static int | 277 | static bool |
| 267 | interval_has_some_properties_list (Lisp_Object list, INTERVAL i) | 278 | interval_has_some_properties_list (Lisp_Object list, INTERVAL i) |
| 268 | { | 279 | { |
| 269 | register Lisp_Object tail1, tail2, sym; | 280 | Lisp_Object tail1, tail2, sym; |
| 270 | 281 | ||
| 271 | /* Go through each element of LIST. */ | 282 | /* Go through each element of LIST. */ |
| 272 | for (tail1 = list; CONSP (tail1); tail1 = XCDR (tail1)) | 283 | for (tail1 = list; CONSP (tail1); tail1 = XCDR (tail1)) |
| @@ -347,15 +358,14 @@ set_properties (Lisp_Object properties, INTERVAL interval, Lisp_Object object) | |||
| 347 | 358 | ||
| 348 | OBJECT should be the string or buffer the interval is in. | 359 | OBJECT should be the string or buffer the interval is in. |
| 349 | 360 | ||
| 350 | Return nonzero if this changes I (i.e., if any members of PLIST | 361 | Return true if this changes I (i.e., if any members of PLIST |
| 351 | are actually added to I's plist) */ | 362 | are actually added to I's plist) */ |
| 352 | 363 | ||
| 353 | static int | 364 | static bool |
| 354 | add_properties (Lisp_Object plist, INTERVAL i, Lisp_Object object) | 365 | add_properties (Lisp_Object plist, INTERVAL i, Lisp_Object object) |
| 355 | { | 366 | { |
| 356 | Lisp_Object tail1, tail2, sym1, val1; | 367 | Lisp_Object tail1, tail2, sym1, val1; |
| 357 | register int changed = 0; | 368 | bool changed = 0; |
| 358 | register int found; | ||
| 359 | struct gcpro gcpro1, gcpro2, gcpro3; | 369 | struct gcpro gcpro1, gcpro2, gcpro3; |
| 360 | 370 | ||
| 361 | tail1 = plist; | 371 | tail1 = plist; |
| @@ -369,9 +379,9 @@ add_properties (Lisp_Object plist, INTERVAL i, Lisp_Object object) | |||
| 369 | /* Go through each element of PLIST. */ | 379 | /* Go through each element of PLIST. */ |
| 370 | for (tail1 = plist; CONSP (tail1); tail1 = Fcdr (XCDR (tail1))) | 380 | for (tail1 = plist; CONSP (tail1); tail1 = Fcdr (XCDR (tail1))) |
| 371 | { | 381 | { |
| 382 | bool found = 0; | ||
| 372 | sym1 = XCAR (tail1); | 383 | sym1 = XCAR (tail1); |
| 373 | val1 = Fcar (XCDR (tail1)); | 384 | val1 = Fcar (XCDR (tail1)); |
| 374 | found = 0; | ||
| 375 | 385 | ||
| 376 | /* Go through I's plist, looking for sym1 */ | 386 | /* Go through I's plist, looking for sym1 */ |
| 377 | for (tail2 = i->plist; CONSP (tail2); tail2 = Fcdr (XCDR (tail2))) | 387 | for (tail2 = i->plist; CONSP (tail2); tail2 = Fcdr (XCDR (tail2))) |
| @@ -399,7 +409,7 @@ add_properties (Lisp_Object plist, INTERVAL i, Lisp_Object object) | |||
| 399 | 409 | ||
| 400 | /* I's property has a different value -- change it */ | 410 | /* I's property has a different value -- change it */ |
| 401 | Fsetcar (this_cdr, val1); | 411 | Fsetcar (this_cdr, val1); |
| 402 | changed++; | 412 | changed = 1; |
| 403 | break; | 413 | break; |
| 404 | } | 414 | } |
| 405 | 415 | ||
| @@ -412,7 +422,7 @@ add_properties (Lisp_Object plist, INTERVAL i, Lisp_Object object) | |||
| 412 | sym1, Qnil, object); | 422 | sym1, Qnil, object); |
| 413 | } | 423 | } |
| 414 | set_interval_plist (i, Fcons (sym1, Fcons (val1, i->plist))); | 424 | set_interval_plist (i, Fcons (sym1, Fcons (val1, i->plist))); |
| 415 | changed++; | 425 | changed = 1; |
| 416 | } | 426 | } |
| 417 | } | 427 | } |
| 418 | 428 | ||
| @@ -426,14 +436,14 @@ add_properties (Lisp_Object plist, INTERVAL i, Lisp_Object object) | |||
| 426 | (If PLIST is non-nil, use that, otherwise use LIST.) | 436 | (If PLIST is non-nil, use that, otherwise use LIST.) |
| 427 | OBJECT is the string or buffer containing I. */ | 437 | OBJECT is the string or buffer containing I. */ |
| 428 | 438 | ||
| 429 | static int | 439 | static bool |
| 430 | remove_properties (Lisp_Object plist, Lisp_Object list, INTERVAL i, Lisp_Object object) | 440 | remove_properties (Lisp_Object plist, Lisp_Object list, INTERVAL i, Lisp_Object object) |
| 431 | { | 441 | { |
| 432 | register Lisp_Object tail1, tail2, sym, current_plist; | 442 | Lisp_Object tail1, tail2, sym, current_plist; |
| 433 | register int changed = 0; | 443 | bool changed = 0; |
| 434 | 444 | ||
| 435 | /* Nonzero means tail1 is a plist, otherwise it is a list. */ | 445 | /* True means tail1 is a plist, otherwise it is a list. */ |
| 436 | int use_plist; | 446 | bool use_plist; |
| 437 | 447 | ||
| 438 | current_plist = i->plist; | 448 | current_plist = i->plist; |
| 439 | 449 | ||
| @@ -456,7 +466,7 @@ remove_properties (Lisp_Object plist, Lisp_Object list, INTERVAL i, Lisp_Object | |||
| 456 | object); | 466 | object); |
| 457 | 467 | ||
| 458 | current_plist = XCDR (XCDR (current_plist)); | 468 | current_plist = XCDR (XCDR (current_plist)); |
| 459 | changed++; | 469 | changed = 1; |
| 460 | } | 470 | } |
| 461 | 471 | ||
| 462 | /* Go through I's plist, looking for SYM. */ | 472 | /* Go through I's plist, looking for SYM. */ |
| @@ -472,7 +482,7 @@ remove_properties (Lisp_Object plist, Lisp_Object list, INTERVAL i, Lisp_Object | |||
| 472 | sym, XCAR (XCDR (this)), object); | 482 | sym, XCAR (XCDR (this)), object); |
| 473 | 483 | ||
| 474 | Fsetcdr (XCDR (tail2), XCDR (XCDR (this))); | 484 | Fsetcdr (XCDR (tail2), XCDR (XCDR (this))); |
| 475 | changed++; | 485 | changed = 1; |
| 476 | } | 486 | } |
| 477 | tail2 = this; | 487 | tail2 = this; |
| 478 | } | 488 | } |
| @@ -587,8 +597,9 @@ get_char_property_and_overlay (Lisp_Object position, register Lisp_Object prop, | |||
| 587 | 597 | ||
| 588 | if (WINDOWP (object)) | 598 | if (WINDOWP (object)) |
| 589 | { | 599 | { |
| 600 | CHECK_LIVE_WINDOW (object); | ||
| 590 | w = XWINDOW (object); | 601 | w = XWINDOW (object); |
| 591 | object = w->buffer; | 602 | object = w->contents; |
| 592 | } | 603 | } |
| 593 | if (BUFFERP (object)) | 604 | if (BUFFERP (object)) |
| 594 | { | 605 | { |
| @@ -1118,10 +1129,11 @@ If OBJECT is a string, START and END are 0-based indices into it. | |||
| 1118 | Return t if any property value actually changed, nil otherwise. */) | 1129 | Return t if any property value actually changed, nil otherwise. */) |
| 1119 | (Lisp_Object start, Lisp_Object end, Lisp_Object properties, Lisp_Object object) | 1130 | (Lisp_Object start, Lisp_Object end, Lisp_Object properties, Lisp_Object object) |
| 1120 | { | 1131 | { |
| 1121 | register INTERVAL i, unchanged; | 1132 | INTERVAL i, unchanged; |
| 1122 | register ptrdiff_t s, len; | 1133 | ptrdiff_t s, len; |
| 1123 | register int modified = 0; | 1134 | bool modified = 0; |
| 1124 | struct gcpro gcpro1; | 1135 | struct gcpro gcpro1; |
| 1136 | bool first_time = 1; | ||
| 1125 | 1137 | ||
| 1126 | properties = validate_plist (properties); | 1138 | properties = validate_plist (properties); |
| 1127 | if (NILP (properties)) | 1139 | if (NILP (properties)) |
| @@ -1130,6 +1142,7 @@ Return t if any property value actually changed, nil otherwise. */) | |||
| 1130 | if (NILP (object)) | 1142 | if (NILP (object)) |
| 1131 | XSETBUFFER (object, current_buffer); | 1143 | XSETBUFFER (object, current_buffer); |
| 1132 | 1144 | ||
| 1145 | retry: | ||
| 1133 | i = validate_interval_range (object, &start, &end, hard); | 1146 | i = validate_interval_range (object, &start, &end, hard); |
| 1134 | if (!i) | 1147 | if (!i) |
| 1135 | return Qnil; | 1148 | return Qnil; |
| @@ -1141,31 +1154,50 @@ Return t if any property value actually changed, nil otherwise. */) | |||
| 1141 | and live buffers are always protected. */ | 1154 | and live buffers are always protected. */ |
| 1142 | GCPRO1 (properties); | 1155 | GCPRO1 (properties); |
| 1143 | 1156 | ||
| 1144 | /* If we're not starting on an interval boundary, we have to | 1157 | /* If this interval already has the properties, we can skip it. */ |
| 1145 | split this interval. */ | 1158 | if (interval_has_all_properties (properties, i)) |
| 1146 | if (i->position != s) | ||
| 1147 | { | 1159 | { |
| 1148 | /* If this interval already has the properties, we can | 1160 | ptrdiff_t got = LENGTH (i) - (s - i->position); |
| 1149 | skip it. */ | 1161 | |
| 1150 | if (interval_has_all_properties (properties, i)) | 1162 | do |
| 1151 | { | 1163 | { |
| 1152 | ptrdiff_t got = (LENGTH (i) - (s - i->position)); | ||
| 1153 | if (got >= len) | 1164 | if (got >= len) |
| 1154 | RETURN_UNGCPRO (Qnil); | 1165 | RETURN_UNGCPRO (Qnil); |
| 1155 | len -= got; | 1166 | len -= got; |
| 1156 | i = next_interval (i); | 1167 | i = next_interval (i); |
| 1168 | got = LENGTH (i); | ||
| 1157 | } | 1169 | } |
| 1158 | else | 1170 | while (interval_has_all_properties (properties, i)); |
| 1171 | } | ||
| 1172 | else if (i->position != s) | ||
| 1173 | { | ||
| 1174 | /* If we're not starting on an interval boundary, we have to | ||
| 1175 | split this interval. */ | ||
| 1176 | unchanged = i; | ||
| 1177 | i = split_interval_right (unchanged, s - unchanged->position); | ||
| 1178 | copy_properties (unchanged, i); | ||
| 1179 | } | ||
| 1180 | |||
| 1181 | if (BUFFERP (object) && first_time) | ||
| 1182 | { | ||
| 1183 | ptrdiff_t prev_total_length = TOTAL_LENGTH (i); | ||
| 1184 | ptrdiff_t prev_pos = i->position; | ||
| 1185 | |||
| 1186 | modify_region (object, start, end); | ||
| 1187 | /* If someone called us recursively as a side effect of | ||
| 1188 | modify_region, and changed the intervals behind our back | ||
| 1189 | (could happen if lock_file, called by prepare_to_modify_buffer, | ||
| 1190 | triggers redisplay, and that calls add-text-properties again | ||
| 1191 | in the same buffer), we cannot continue with I, because its | ||
| 1192 | data changed. So we restart the interval analysis anew. */ | ||
| 1193 | if (TOTAL_LENGTH (i) != prev_total_length | ||
| 1194 | || i->position != prev_pos) | ||
| 1159 | { | 1195 | { |
| 1160 | unchanged = i; | 1196 | first_time = 0; |
| 1161 | i = split_interval_right (unchanged, s - unchanged->position); | 1197 | goto retry; |
| 1162 | copy_properties (unchanged, i); | ||
| 1163 | } | 1198 | } |
| 1164 | } | 1199 | } |
| 1165 | 1200 | ||
| 1166 | if (BUFFERP (object)) | ||
| 1167 | modify_region (XBUFFER (object), XINT (start), XINT (end), 1); | ||
| 1168 | |||
| 1169 | /* We are at the beginning of interval I, with LEN chars to scan. */ | 1201 | /* We are at the beginning of interval I, with LEN chars to scan. */ |
| 1170 | for (;;) | 1202 | for (;;) |
| 1171 | { | 1203 | { |
| @@ -1184,7 +1216,8 @@ Return t if any property value actually changed, nil otherwise. */) | |||
| 1184 | signal_after_change (XINT (start), XINT (end) - XINT (start), | 1216 | signal_after_change (XINT (start), XINT (end) - XINT (start), |
| 1185 | XINT (end) - XINT (start)); | 1217 | XINT (end) - XINT (start)); |
| 1186 | 1218 | ||
| 1187 | return modified ? Qt : Qnil; | 1219 | eassert (modified); |
| 1220 | return Qt; | ||
| 1188 | } | 1221 | } |
| 1189 | 1222 | ||
| 1190 | if (LENGTH (i) == len) | 1223 | if (LENGTH (i) == len) |
| @@ -1208,7 +1241,7 @@ Return t if any property value actually changed, nil otherwise. */) | |||
| 1208 | } | 1241 | } |
| 1209 | 1242 | ||
| 1210 | len -= LENGTH (i); | 1243 | len -= LENGTH (i); |
| 1211 | modified += add_properties (properties, i, object); | 1244 | modified |= add_properties (properties, i, object); |
| 1212 | i = next_interval (i); | 1245 | i = next_interval (i); |
| 1213 | } | 1246 | } |
| 1214 | } | 1247 | } |
| @@ -1302,7 +1335,7 @@ set_text_properties (Lisp_Object start, Lisp_Object end, Lisp_Object properties, | |||
| 1302 | } | 1335 | } |
| 1303 | 1336 | ||
| 1304 | if (BUFFERP (object) && !NILP (coherent_change_p)) | 1337 | if (BUFFERP (object) && !NILP (coherent_change_p)) |
| 1305 | modify_region (XBUFFER (object), XINT (start), XINT (end), 1); | 1338 | modify_region (object, start, end); |
| 1306 | 1339 | ||
| 1307 | set_text_properties_1 (start, end, properties, object, i); | 1340 | set_text_properties_1 (start, end, properties, object, i); |
| 1308 | 1341 | ||
| @@ -1313,14 +1346,13 @@ set_text_properties (Lisp_Object start, Lisp_Object end, Lisp_Object properties, | |||
| 1313 | } | 1346 | } |
| 1314 | 1347 | ||
| 1315 | /* Replace properties of text from START to END with new list of | 1348 | /* Replace properties of text from START to END with new list of |
| 1316 | properties PROPERTIES. BUFFER is the buffer containing | 1349 | properties PROPERTIES. OBJECT is the buffer or string containing |
| 1317 | the text. This does not obey any hooks. | 1350 | the text. This does not obey any hooks. |
| 1318 | You can provide the interval that START is located in as I, | 1351 | You should provide the interval that START is located in as I. |
| 1319 | or pass NULL for I and this function will find it. | ||
| 1320 | START and END can be in any order. */ | 1352 | START and END can be in any order. */ |
| 1321 | 1353 | ||
| 1322 | void | 1354 | void |
| 1323 | set_text_properties_1 (Lisp_Object start, Lisp_Object end, Lisp_Object properties, Lisp_Object buffer, INTERVAL i) | 1355 | set_text_properties_1 (Lisp_Object start, Lisp_Object end, Lisp_Object properties, Lisp_Object object, INTERVAL i) |
| 1324 | { | 1356 | { |
| 1325 | register INTERVAL prev_changed = NULL; | 1357 | register INTERVAL prev_changed = NULL; |
| 1326 | register ptrdiff_t s, len; | 1358 | register ptrdiff_t s, len; |
| @@ -1339,8 +1371,7 @@ set_text_properties_1 (Lisp_Object start, Lisp_Object end, Lisp_Object propertie | |||
| 1339 | else | 1371 | else |
| 1340 | return; | 1372 | return; |
| 1341 | 1373 | ||
| 1342 | if (i == NULL) | 1374 | eassert (i); |
| 1343 | i = find_interval (buffer_intervals (XBUFFER (buffer)), s); | ||
| 1344 | 1375 | ||
| 1345 | if (i->position != s) | 1376 | if (i->position != s) |
| 1346 | { | 1377 | { |
| @@ -1351,11 +1382,11 @@ set_text_properties_1 (Lisp_Object start, Lisp_Object end, Lisp_Object propertie | |||
| 1351 | { | 1382 | { |
| 1352 | copy_properties (unchanged, i); | 1383 | copy_properties (unchanged, i); |
| 1353 | i = split_interval_left (i, len); | 1384 | i = split_interval_left (i, len); |
| 1354 | set_properties (properties, i, buffer); | 1385 | set_properties (properties, i, object); |
| 1355 | return; | 1386 | return; |
| 1356 | } | 1387 | } |
| 1357 | 1388 | ||
| 1358 | set_properties (properties, i, buffer); | 1389 | set_properties (properties, i, object); |
| 1359 | 1390 | ||
| 1360 | if (LENGTH (i) == len) | 1391 | if (LENGTH (i) == len) |
| 1361 | return; | 1392 | return; |
| @@ -1378,7 +1409,7 @@ set_text_properties_1 (Lisp_Object start, Lisp_Object end, Lisp_Object propertie | |||
| 1378 | /* We have to call set_properties even if we are going to | 1409 | /* We have to call set_properties even if we are going to |
| 1379 | merge the intervals, so as to make the undo records | 1410 | merge the intervals, so as to make the undo records |
| 1380 | and cause redisplay to happen. */ | 1411 | and cause redisplay to happen. */ |
| 1381 | set_properties (properties, i, buffer); | 1412 | set_properties (properties, i, object); |
| 1382 | if (prev_changed) | 1413 | if (prev_changed) |
| 1383 | merge_interval_left (i); | 1414 | merge_interval_left (i); |
| 1384 | return; | 1415 | return; |
| @@ -1389,7 +1420,7 @@ set_text_properties_1 (Lisp_Object start, Lisp_Object end, Lisp_Object propertie | |||
| 1389 | /* We have to call set_properties even if we are going to | 1420 | /* We have to call set_properties even if we are going to |
| 1390 | merge the intervals, so as to make the undo records | 1421 | merge the intervals, so as to make the undo records |
| 1391 | and cause redisplay to happen. */ | 1422 | and cause redisplay to happen. */ |
| 1392 | set_properties (properties, i, buffer); | 1423 | set_properties (properties, i, object); |
| 1393 | if (!prev_changed) | 1424 | if (!prev_changed) |
| 1394 | prev_changed = i; | 1425 | prev_changed = i; |
| 1395 | else | 1426 | else |
| @@ -1414,13 +1445,15 @@ Return t if any property was actually removed, nil otherwise. | |||
| 1414 | Use `set-text-properties' if you want to remove all text properties. */) | 1445 | Use `set-text-properties' if you want to remove all text properties. */) |
| 1415 | (Lisp_Object start, Lisp_Object end, Lisp_Object properties, Lisp_Object object) | 1446 | (Lisp_Object start, Lisp_Object end, Lisp_Object properties, Lisp_Object object) |
| 1416 | { | 1447 | { |
| 1417 | register INTERVAL i, unchanged; | 1448 | INTERVAL i, unchanged; |
| 1418 | register ptrdiff_t s, len; | 1449 | ptrdiff_t s, len; |
| 1419 | register int modified = 0; | 1450 | bool modified = 0; |
| 1451 | bool first_time = 1; | ||
| 1420 | 1452 | ||
| 1421 | if (NILP (object)) | 1453 | if (NILP (object)) |
| 1422 | XSETBUFFER (object, current_buffer); | 1454 | XSETBUFFER (object, current_buffer); |
| 1423 | 1455 | ||
| 1456 | retry: | ||
| 1424 | i = validate_interval_range (object, &start, &end, soft); | 1457 | i = validate_interval_range (object, &start, &end, soft); |
| 1425 | if (!i) | 1458 | if (!i) |
| 1426 | return Qnil; | 1459 | return Qnil; |
| @@ -1428,31 +1461,50 @@ Use `set-text-properties' if you want to remove all text properties. */) | |||
| 1428 | s = XINT (start); | 1461 | s = XINT (start); |
| 1429 | len = XINT (end) - s; | 1462 | len = XINT (end) - s; |
| 1430 | 1463 | ||
| 1431 | if (i->position != s) | 1464 | /* If there are no properties on this entire interval, return. */ |
| 1465 | if (! interval_has_some_properties (properties, i)) | ||
| 1432 | { | 1466 | { |
| 1433 | /* No properties on this first interval -- return if | 1467 | ptrdiff_t got = LENGTH (i) - (s - i->position); |
| 1434 | it covers the entire region. */ | 1468 | |
| 1435 | if (! interval_has_some_properties (properties, i)) | 1469 | do |
| 1436 | { | 1470 | { |
| 1437 | ptrdiff_t got = (LENGTH (i) - (s - i->position)); | ||
| 1438 | if (got >= len) | 1471 | if (got >= len) |
| 1439 | return Qnil; | 1472 | return Qnil; |
| 1440 | len -= got; | 1473 | len -= got; |
| 1441 | i = next_interval (i); | 1474 | i = next_interval (i); |
| 1475 | got = LENGTH (i); | ||
| 1442 | } | 1476 | } |
| 1443 | /* Split away the beginning of this interval; what we don't | 1477 | while (! interval_has_some_properties (properties, i)); |
| 1444 | want to modify. */ | 1478 | } |
| 1445 | else | 1479 | /* Split away the beginning of this interval; what we don't |
| 1480 | want to modify. */ | ||
| 1481 | else if (i->position != s) | ||
| 1482 | { | ||
| 1483 | unchanged = i; | ||
| 1484 | i = split_interval_right (unchanged, s - unchanged->position); | ||
| 1485 | copy_properties (unchanged, i); | ||
| 1486 | } | ||
| 1487 | |||
| 1488 | if (BUFFERP (object) && first_time) | ||
| 1489 | { | ||
| 1490 | ptrdiff_t prev_total_length = TOTAL_LENGTH (i); | ||
| 1491 | ptrdiff_t prev_pos = i->position; | ||
| 1492 | |||
| 1493 | modify_region (object, start, end); | ||
| 1494 | /* If someone called us recursively as a side effect of | ||
| 1495 | modify_region, and changed the intervals behind our back | ||
| 1496 | (could happen if lock_file, called by prepare_to_modify_buffer, | ||
| 1497 | triggers redisplay, and that calls add-text-properties again | ||
| 1498 | in the same buffer), we cannot continue with I, because its | ||
| 1499 | data changed. So we restart the interval analysis anew. */ | ||
| 1500 | if (TOTAL_LENGTH (i) != prev_total_length | ||
| 1501 | || i->position != prev_pos) | ||
| 1446 | { | 1502 | { |
| 1447 | unchanged = i; | 1503 | first_time = 0; |
| 1448 | i = split_interval_right (unchanged, s - unchanged->position); | 1504 | goto retry; |
| 1449 | copy_properties (unchanged, i); | ||
| 1450 | } | 1505 | } |
| 1451 | } | 1506 | } |
| 1452 | 1507 | ||
| 1453 | if (BUFFERP (object)) | ||
| 1454 | modify_region (XBUFFER (object), XINT (start), XINT (end), 1); | ||
| 1455 | |||
| 1456 | /* We are at the beginning of an interval, with len to scan */ | 1508 | /* We are at the beginning of an interval, with len to scan */ |
| 1457 | for (;;) | 1509 | for (;;) |
| 1458 | { | 1510 | { |
| @@ -1461,7 +1513,13 @@ Use `set-text-properties' if you want to remove all text properties. */) | |||
| 1461 | if (LENGTH (i) >= len) | 1513 | if (LENGTH (i) >= len) |
| 1462 | { | 1514 | { |
| 1463 | if (! interval_has_some_properties (properties, i)) | 1515 | if (! interval_has_some_properties (properties, i)) |
| 1464 | return modified ? Qt : Qnil; | 1516 | { |
| 1517 | eassert (modified); | ||
| 1518 | if (BUFFERP (object)) | ||
| 1519 | signal_after_change (XINT (start), XINT (end) - XINT (start), | ||
| 1520 | XINT (end) - XINT (start)); | ||
| 1521 | return Qt; | ||
| 1522 | } | ||
| 1465 | 1523 | ||
| 1466 | if (LENGTH (i) == len) | 1524 | if (LENGTH (i) == len) |
| 1467 | { | 1525 | { |
| @@ -1484,7 +1542,7 @@ Use `set-text-properties' if you want to remove all text properties. */) | |||
| 1484 | } | 1542 | } |
| 1485 | 1543 | ||
| 1486 | len -= LENGTH (i); | 1544 | len -= LENGTH (i); |
| 1487 | modified += remove_properties (properties, Qnil, i, object); | 1545 | modified |= remove_properties (properties, Qnil, i, object); |
| 1488 | i = next_interval (i); | 1546 | i = next_interval (i); |
| 1489 | } | 1547 | } |
| 1490 | } | 1548 | } |
| @@ -1499,9 +1557,9 @@ markers). If OBJECT is a string, START and END are 0-based indices into it. | |||
| 1499 | Return t if any property was actually removed, nil otherwise. */) | 1557 | Return t if any property was actually removed, nil otherwise. */) |
| 1500 | (Lisp_Object start, Lisp_Object end, Lisp_Object list_of_properties, Lisp_Object object) | 1558 | (Lisp_Object start, Lisp_Object end, Lisp_Object list_of_properties, Lisp_Object object) |
| 1501 | { | 1559 | { |
| 1502 | register INTERVAL i, unchanged; | 1560 | INTERVAL i, unchanged; |
| 1503 | register ptrdiff_t s, len; | 1561 | ptrdiff_t s, len; |
| 1504 | register int modified = 0; | 1562 | bool modified = 0; |
| 1505 | Lisp_Object properties; | 1563 | Lisp_Object properties; |
| 1506 | properties = list_of_properties; | 1564 | properties = list_of_properties; |
| 1507 | 1565 | ||
| @@ -1515,26 +1573,28 @@ Return t if any property was actually removed, nil otherwise. */) | |||
| 1515 | s = XINT (start); | 1573 | s = XINT (start); |
| 1516 | len = XINT (end) - s; | 1574 | len = XINT (end) - s; |
| 1517 | 1575 | ||
| 1518 | if (i->position != s) | 1576 | /* If there are no properties on the interval, return. */ |
| 1577 | if (! interval_has_some_properties_list (properties, i)) | ||
| 1519 | { | 1578 | { |
| 1520 | /* No properties on this first interval -- return if | 1579 | ptrdiff_t got = LENGTH (i) - (s - i->position); |
| 1521 | it covers the entire region. */ | 1580 | |
| 1522 | if (! interval_has_some_properties_list (properties, i)) | 1581 | do |
| 1523 | { | 1582 | { |
| 1524 | ptrdiff_t got = (LENGTH (i) - (s - i->position)); | ||
| 1525 | if (got >= len) | 1583 | if (got >= len) |
| 1526 | return Qnil; | 1584 | return Qnil; |
| 1527 | len -= got; | 1585 | len -= got; |
| 1528 | i = next_interval (i); | 1586 | i = next_interval (i); |
| 1587 | got = LENGTH (i); | ||
| 1529 | } | 1588 | } |
| 1530 | /* Split away the beginning of this interval; what we don't | 1589 | while (! interval_has_some_properties_list (properties, i)); |
| 1531 | want to modify. */ | 1590 | } |
| 1532 | else | 1591 | /* Split away the beginning of this interval; what we don't |
| 1533 | { | 1592 | want to modify. */ |
| 1534 | unchanged = i; | 1593 | else if (i->position != s) |
| 1535 | i = split_interval_right (unchanged, s - unchanged->position); | 1594 | { |
| 1536 | copy_properties (unchanged, i); | 1595 | unchanged = i; |
| 1537 | } | 1596 | i = split_interval_right (unchanged, s - unchanged->position); |
| 1597 | copy_properties (unchanged, i); | ||
| 1538 | } | 1598 | } |
| 1539 | 1599 | ||
| 1540 | /* We are at the beginning of an interval, with len to scan. | 1600 | /* We are at the beginning of an interval, with len to scan. |
| @@ -1565,7 +1625,7 @@ Return t if any property was actually removed, nil otherwise. */) | |||
| 1565 | else if (LENGTH (i) == len) | 1625 | else if (LENGTH (i) == len) |
| 1566 | { | 1626 | { |
| 1567 | if (!modified && BUFFERP (object)) | 1627 | if (!modified && BUFFERP (object)) |
| 1568 | modify_region (XBUFFER (object), XINT (start), XINT (end), 1); | 1628 | modify_region (object, start, end); |
| 1569 | remove_properties (Qnil, properties, i, object); | 1629 | remove_properties (Qnil, properties, i, object); |
| 1570 | if (BUFFERP (object)) | 1630 | if (BUFFERP (object)) |
| 1571 | signal_after_change (XINT (start), XINT (end) - XINT (start), | 1631 | signal_after_change (XINT (start), XINT (end) - XINT (start), |
| @@ -1578,7 +1638,7 @@ Return t if any property was actually removed, nil otherwise. */) | |||
| 1578 | i = split_interval_left (i, len); | 1638 | i = split_interval_left (i, len); |
| 1579 | copy_properties (unchanged, i); | 1639 | copy_properties (unchanged, i); |
| 1580 | if (!modified && BUFFERP (object)) | 1640 | if (!modified && BUFFERP (object)) |
| 1581 | modify_region (XBUFFER (object), XINT (start), XINT (end), 1); | 1641 | modify_region (object, start, end); |
| 1582 | remove_properties (Qnil, properties, i, object); | 1642 | remove_properties (Qnil, properties, i, object); |
| 1583 | if (BUFFERP (object)) | 1643 | if (BUFFERP (object)) |
| 1584 | signal_after_change (XINT (start), XINT (end) - XINT (start), | 1644 | signal_after_change (XINT (start), XINT (end) - XINT (start), |
| @@ -1589,7 +1649,7 @@ Return t if any property was actually removed, nil otherwise. */) | |||
| 1589 | if (interval_has_some_properties_list (properties, i)) | 1649 | if (interval_has_some_properties_list (properties, i)) |
| 1590 | { | 1650 | { |
| 1591 | if (!modified && BUFFERP (object)) | 1651 | if (!modified && BUFFERP (object)) |
| 1592 | modify_region (XBUFFER (object), XINT (start), XINT (end), 1); | 1652 | modify_region (object, start, end); |
| 1593 | remove_properties (Qnil, properties, i, object); | 1653 | remove_properties (Qnil, properties, i, object); |
| 1594 | modified = 1; | 1654 | modified = 1; |
| 1595 | } | 1655 | } |
| @@ -1681,7 +1741,7 @@ int | |||
| 1681 | text_property_stickiness (Lisp_Object prop, Lisp_Object pos, Lisp_Object buffer) | 1741 | text_property_stickiness (Lisp_Object prop, Lisp_Object pos, Lisp_Object buffer) |
| 1682 | { | 1742 | { |
| 1683 | Lisp_Object prev_pos, front_sticky; | 1743 | Lisp_Object prev_pos, front_sticky; |
| 1684 | int is_rear_sticky = 1, is_front_sticky = 0; /* defaults */ | 1744 | bool is_rear_sticky = 1, is_front_sticky = 0; /* defaults */ |
| 1685 | Lisp_Object defalt = Fassq (prop, Vtext_property_default_nonsticky); | 1745 | Lisp_Object defalt = Fassq (prop, Vtext_property_default_nonsticky); |
| 1686 | 1746 | ||
| 1687 | if (NILP (buffer)) | 1747 | if (NILP (buffer)) |
| @@ -1756,7 +1816,7 @@ copy_text_properties (Lisp_Object start, Lisp_Object end, Lisp_Object src, Lisp_ | |||
| 1756 | Lisp_Object stuff; | 1816 | Lisp_Object stuff; |
| 1757 | Lisp_Object plist; | 1817 | Lisp_Object plist; |
| 1758 | ptrdiff_t s, e, e2, p, len; | 1818 | ptrdiff_t s, e, e2, p, len; |
| 1759 | int modified = 0; | 1819 | bool modified = 0; |
| 1760 | struct gcpro gcpro1, gcpro2; | 1820 | struct gcpro gcpro1, gcpro2; |
| 1761 | 1821 | ||
| 1762 | i = validate_interval_range (src, &start, &end, soft); | 1822 | i = validate_interval_range (src, &start, &end, soft); |
| @@ -1827,7 +1887,7 @@ copy_text_properties (Lisp_Object start, Lisp_Object end, Lisp_Object src, Lisp_ | |||
| 1827 | res = Fadd_text_properties (Fcar (res), Fcar (Fcdr (res)), | 1887 | res = Fadd_text_properties (Fcar (res), Fcar (Fcdr (res)), |
| 1828 | Fcar (Fcdr (Fcdr (res))), dest); | 1888 | Fcar (Fcdr (Fcdr (res))), dest); |
| 1829 | if (! NILP (res)) | 1889 | if (! NILP (res)) |
| 1830 | modified++; | 1890 | modified = 1; |
| 1831 | stuff = Fcdr (stuff); | 1891 | stuff = Fcdr (stuff); |
| 1832 | } | 1892 | } |
| 1833 | 1893 | ||
| @@ -1898,33 +1958,28 @@ text_property_list (Lisp_Object object, Lisp_Object start, Lisp_Object end, Lisp | |||
| 1898 | /* Add text properties to OBJECT from LIST. LIST is a list of triples | 1958 | /* Add text properties to OBJECT from LIST. LIST is a list of triples |
| 1899 | (START END PLIST), where START and END are positions and PLIST is a | 1959 | (START END PLIST), where START and END are positions and PLIST is a |
| 1900 | property list containing the text properties to add. Adjust START | 1960 | property list containing the text properties to add. Adjust START |
| 1901 | and END positions by DELTA before adding properties. Value is | 1961 | and END positions by DELTA before adding properties. */ |
| 1902 | non-zero if OBJECT was modified. */ | ||
| 1903 | 1962 | ||
| 1904 | int | 1963 | void |
| 1905 | add_text_properties_from_list (Lisp_Object object, Lisp_Object list, Lisp_Object delta) | 1964 | add_text_properties_from_list (Lisp_Object object, Lisp_Object list, Lisp_Object delta) |
| 1906 | { | 1965 | { |
| 1907 | struct gcpro gcpro1, gcpro2; | 1966 | struct gcpro gcpro1, gcpro2; |
| 1908 | int modified_p = 0; | ||
| 1909 | 1967 | ||
| 1910 | GCPRO2 (list, object); | 1968 | GCPRO2 (list, object); |
| 1911 | 1969 | ||
| 1912 | for (; CONSP (list); list = XCDR (list)) | 1970 | for (; CONSP (list); list = XCDR (list)) |
| 1913 | { | 1971 | { |
| 1914 | Lisp_Object item, start, end, plist, tem; | 1972 | Lisp_Object item, start, end, plist; |
| 1915 | 1973 | ||
| 1916 | item = XCAR (list); | 1974 | item = XCAR (list); |
| 1917 | start = make_number (XINT (XCAR (item)) + XINT (delta)); | 1975 | start = make_number (XINT (XCAR (item)) + XINT (delta)); |
| 1918 | end = make_number (XINT (XCAR (XCDR (item))) + XINT (delta)); | 1976 | end = make_number (XINT (XCAR (XCDR (item))) + XINT (delta)); |
| 1919 | plist = XCAR (XCDR (XCDR (item))); | 1977 | plist = XCAR (XCDR (XCDR (item))); |
| 1920 | 1978 | ||
| 1921 | tem = Fadd_text_properties (start, end, plist, object); | 1979 | Fadd_text_properties (start, end, plist, object); |
| 1922 | if (!NILP (tem)) | ||
| 1923 | modified_p = 1; | ||
| 1924 | } | 1980 | } |
| 1925 | 1981 | ||
| 1926 | UNGCPRO; | 1982 | UNGCPRO; |
| 1927 | return modified_p; | ||
| 1928 | } | 1983 | } |
| 1929 | 1984 | ||
| 1930 | 1985 | ||