aboutsummaryrefslogtreecommitdiffstats
path: root/src/textprop.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/textprop.c')
-rw-r--r--src/textprop.c287
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
4This file is part of GNU Emacs. 5This file is part of GNU Emacs.
5 6
@@ -59,7 +60,7 @@ Lisp_Object Qinvisible, Qintangible, Qmouse_face;
59static Lisp_Object Qread_only; 60static Lisp_Object Qread_only;
60Lisp_Object Qminibuffer_prompt; 61Lisp_Object Qminibuffer_prompt;
61 62
62/* Sticky properties */ 63/* Sticky properties. */
63Lisp_Object Qfront_sticky, Qrear_nonsticky; 64Lisp_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
91static void
92modify_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
116INTERVAL 127INTERVAL
117validate_interval_range (Lisp_Object object, Lisp_Object *begin, Lisp_Object *end, int force) 128validate_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
208static int 220static bool
209interval_has_all_properties (Lisp_Object plist, INTERVAL i) 221interval_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
244static int 255static bool
245interval_has_some_properties (Lisp_Object plist, INTERVAL i) 256interval_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
266static int 277static bool
267interval_has_some_properties_list (Lisp_Object list, INTERVAL i) 278interval_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
353static int 364static bool
354add_properties (Lisp_Object plist, INTERVAL i, Lisp_Object object) 365add_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
429static int 439static bool
430remove_properties (Lisp_Object plist, Lisp_Object list, INTERVAL i, Lisp_Object object) 440remove_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.
1118Return t if any property value actually changed, nil otherwise. */) 1129Return 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
1322void 1354void
1323set_text_properties_1 (Lisp_Object start, Lisp_Object end, Lisp_Object properties, Lisp_Object buffer, INTERVAL i) 1355set_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.
1414Use `set-text-properties' if you want to remove all text properties. */) 1445Use `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.
1499Return t if any property was actually removed, nil otherwise. */) 1557Return 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
1681text_property_stickiness (Lisp_Object prop, Lisp_Object pos, Lisp_Object buffer) 1741text_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
1904int 1963void
1905add_text_properties_from_list (Lisp_Object object, Lisp_Object list, Lisp_Object delta) 1964add_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