Mercurial > emacs
comparison src/buffer.c @ 45374:030fb28e7ec2
* buffer.c (fix_overlays_in_range, fix_overlays_before): Don't take the address
of the cdr part of a cons cell; instead, track the parent cell and call
XSETCDR, or set the variable for the head of the list if we haven't started
down the list yet.
| author | Ken Raeburn <raeburn@raeburn.org> |
|---|---|
| date | Sun, 19 May 2002 23:12:30 +0000 |
| parents | 56ce64222cbe |
| children | a8851a32a1c7 |
comparison
equal
deleted
inserted
replaced
| 45373:0ca1f86bf6fc | 45374:030fb28e7ec2 |
|---|---|
| 3226 fix_overlays_in_range (start, end) | 3226 fix_overlays_in_range (start, end) |
| 3227 register int start, end; | 3227 register int start, end; |
| 3228 { | 3228 { |
| 3229 Lisp_Object overlay; | 3229 Lisp_Object overlay; |
| 3230 Lisp_Object before_list, after_list; | 3230 Lisp_Object before_list, after_list; |
| 3231 Lisp_Object *ptail, *pbefore = &before_list, *pafter = &after_list; | 3231 /* These are either nil, indicating that before_list or after_list |
| 3232 should be assigned, or the cons cell the cdr of which should be | |
| 3233 assigned. */ | |
| 3234 Lisp_Object beforep = Qnil, afterp = Qnil; | |
| 3235 /* 'Parent', likewise, indicates a cons cell or | |
| 3236 current_buffer->overlays_before or overlays_after, depending | |
| 3237 which loop we're in. */ | |
| 3238 Lisp_Object tail, parent; | |
| 3232 int startpos, endpos; | 3239 int startpos, endpos; |
| 3233 | 3240 |
| 3234 /* This algorithm shifts links around instead of consing and GCing. | 3241 /* This algorithm shifts links around instead of consing and GCing. |
| 3235 The loop invariant is that before_list (resp. after_list) is a | 3242 The loop invariant is that before_list (resp. after_list) is a |
| 3236 well-formed list except that its last element, the one that | 3243 well-formed list except that its last element, the CDR of beforep |
| 3237 *pbefore (resp. *pafter) points to, is still uninitialized. | 3244 (resp. afterp) if beforep (afterp) isn't nil or before_list |
| 3238 So it's not a bug that before_list isn't initialized, although | 3245 (after_list) if it is, is still uninitialized. So it's not a bug |
| 3239 it may look strange. */ | 3246 that before_list isn't initialized, although it may look |
| 3240 for (ptail = ¤t_buffer->overlays_before; CONSP (*ptail);) | 3247 strange. */ |
| 3241 { | 3248 for (parent = Qnil, tail = current_buffer->overlays_before; CONSP (tail);) |
| 3242 overlay = XCAR (*ptail); | 3249 { |
| 3250 overlay = XCAR (tail); | |
| 3243 endpos = OVERLAY_POSITION (OVERLAY_END (overlay)); | 3251 endpos = OVERLAY_POSITION (OVERLAY_END (overlay)); |
| 3244 if (endpos < start) | 3252 if (endpos < start) |
| 3245 break; | 3253 break; |
| 3246 startpos = OVERLAY_POSITION (OVERLAY_START (overlay)); | 3254 startpos = OVERLAY_POSITION (OVERLAY_START (overlay)); |
| 3247 if (endpos < end | 3255 if (endpos < end |
| 3259 } | 3267 } |
| 3260 /* Add it to the end of the wrong list. Later on, | 3268 /* Add it to the end of the wrong list. Later on, |
| 3261 recenter_overlay_lists will move it to the right place. */ | 3269 recenter_overlay_lists will move it to the right place. */ |
| 3262 if (endpos < XINT (current_buffer->overlay_center)) | 3270 if (endpos < XINT (current_buffer->overlay_center)) |
| 3263 { | 3271 { |
| 3264 *pafter = *ptail; | 3272 if (NILP (afterp)) |
| 3265 pafter = &XCDR (*ptail); | 3273 after_list = tail; |
| 3274 else | |
| 3275 XSETCDR (afterp, tail); | |
| 3276 afterp = tail; | |
| 3266 } | 3277 } |
| 3267 else | 3278 else |
| 3268 { | 3279 { |
| 3269 *pbefore = *ptail; | 3280 if (NILP (beforep)) |
| 3270 pbefore = &XCDR (*ptail); | 3281 before_list = tail; |
| 3282 else | |
| 3283 XSETCDR (beforep, tail); | |
| 3284 beforep = tail; | |
| 3271 } | 3285 } |
| 3272 *ptail = XCDR (*ptail); | 3286 if (NILP (parent)) |
| 3287 current_buffer->overlays_before = XCDR (tail); | |
| 3288 else | |
| 3289 XSETCDR (parent, XCDR (tail)); | |
| 3290 tail = XCDR (tail); | |
| 3273 } | 3291 } |
| 3274 else | 3292 else |
| 3275 ptail = &XCDR (*ptail); | 3293 parent = tail, tail = XCDR (parent); |
| 3276 } | 3294 } |
| 3277 for (ptail = ¤t_buffer->overlays_after; CONSP (*ptail);) | 3295 for (parent = Qnil, tail = current_buffer->overlays_after; CONSP (tail);) |
| 3278 { | 3296 { |
| 3279 overlay = XCAR (*ptail); | 3297 overlay = XCAR (tail); |
| 3280 startpos = OVERLAY_POSITION (OVERLAY_START (overlay)); | 3298 startpos = OVERLAY_POSITION (OVERLAY_START (overlay)); |
| 3281 if (startpos >= end) | 3299 if (startpos >= end) |
| 3282 break; | 3300 break; |
| 3283 endpos = OVERLAY_POSITION (OVERLAY_END (overlay)); | 3301 endpos = OVERLAY_POSITION (OVERLAY_END (overlay)); |
| 3284 if (startpos >= start | 3302 if (startpos >= start |
| 3293 Qnil); | 3311 Qnil); |
| 3294 tem = startpos; startpos = endpos; endpos = tem; | 3312 tem = startpos; startpos = endpos; endpos = tem; |
| 3295 } | 3313 } |
| 3296 if (endpos < XINT (current_buffer->overlay_center)) | 3314 if (endpos < XINT (current_buffer->overlay_center)) |
| 3297 { | 3315 { |
| 3298 *pafter = *ptail; | 3316 if (NILP (afterp)) |
| 3299 pafter = &XCDR (*ptail); | 3317 after_list = tail; |
| 3318 else | |
| 3319 XSETCDR (afterp, tail); | |
| 3320 afterp = tail; | |
| 3300 } | 3321 } |
| 3301 else | 3322 else |
| 3302 { | 3323 { |
| 3303 *pbefore = *ptail; | 3324 if (NILP (beforep)) |
| 3304 pbefore = &XCDR (*ptail); | 3325 before_list = tail; |
| 3326 else | |
| 3327 XSETCDR (beforep, tail); | |
| 3328 beforep = tail; | |
| 3305 } | 3329 } |
| 3306 *ptail = XCDR (*ptail); | 3330 if (NILP (parent)) |
| 3331 current_buffer->overlays_after = XCDR (tail); | |
| 3332 else | |
| 3333 XSETCDR (parent, XCDR (tail)); | |
| 3334 tail = XCDR (tail); | |
| 3307 } | 3335 } |
| 3308 else | 3336 else |
| 3309 ptail = &XCDR (*ptail); | 3337 parent = tail, tail = XCDR (parent); |
| 3310 } | 3338 } |
| 3311 | 3339 |
| 3312 /* Splice the constructed (wrong) lists into the buffer's lists, | 3340 /* Splice the constructed (wrong) lists into the buffer's lists, |
| 3313 and let the recenter function make it sane again. */ | 3341 and let the recenter function make it sane again. */ |
| 3314 *pbefore = current_buffer->overlays_before; | 3342 if (!NILP (beforep)) |
| 3315 current_buffer->overlays_before = before_list; | 3343 { |
| 3344 XSETCDR (beforep, current_buffer->overlays_before); | |
| 3345 current_buffer->overlays_before = before_list; | |
| 3346 } | |
| 3316 recenter_overlay_lists (current_buffer, | 3347 recenter_overlay_lists (current_buffer, |
| 3317 XINT (current_buffer->overlay_center)); | 3348 XINT (current_buffer->overlay_center)); |
| 3318 | 3349 |
| 3319 *pafter = current_buffer->overlays_after; | 3350 if (!NILP (afterp)) |
| 3320 current_buffer->overlays_after = after_list; | 3351 { |
| 3352 XSETCDR (afterp, current_buffer->overlays_after); | |
| 3353 current_buffer->overlays_after = after_list; | |
| 3354 } | |
| 3321 recenter_overlay_lists (current_buffer, | 3355 recenter_overlay_lists (current_buffer, |
| 3322 XINT (current_buffer->overlay_center)); | 3356 XINT (current_buffer->overlay_center)); |
| 3323 } | 3357 } |
| 3324 | 3358 |
| 3325 /* We have two types of overlay: the one whose ending marker is | 3359 /* We have two types of overlay: the one whose ending marker is |
| 3337 void | 3371 void |
| 3338 fix_overlays_before (bp, prev, pos) | 3372 fix_overlays_before (bp, prev, pos) |
| 3339 struct buffer *bp; | 3373 struct buffer *bp; |
| 3340 int prev, pos; | 3374 int prev, pos; |
| 3341 { | 3375 { |
| 3342 Lisp_Object *tailp = &bp->overlays_before; | 3376 /* If parent is nil, replace overlays_before; otherwise, XCDR(parent). */ |
| 3343 Lisp_Object *right_place; | 3377 Lisp_Object tail = bp->overlays_before, parent = Qnil; |
| 3378 Lisp_Object right_pair; | |
| 3344 int end; | 3379 int end; |
| 3345 | 3380 |
| 3346 /* After the insertion, the several overlays may be in incorrect | 3381 /* After the insertion, the several overlays may be in incorrect |
| 3347 order. The possibility is that, in the list `overlays_before', | 3382 order. The possibility is that, in the list `overlays_before', |
| 3348 an overlay which ends at POS appears after an overlay which ends | 3383 an overlay which ends at POS appears after an overlay which ends |
| 3352 | 3387 |
| 3353 /* At first, find a place where disordered overlays should be linked | 3388 /* At first, find a place where disordered overlays should be linked |
| 3354 in. It is where an overlay which end before POS exists. (i.e. an | 3389 in. It is where an overlay which end before POS exists. (i.e. an |
| 3355 overlay whose ending marker is after-insertion-marker if disorder | 3390 overlay whose ending marker is after-insertion-marker if disorder |
| 3356 exists). */ | 3391 exists). */ |
| 3357 while (!NILP (*tailp) | 3392 while (!NILP (tail) |
| 3358 && ((end = OVERLAY_POSITION (OVERLAY_END (XCAR (*tailp)))) | 3393 && ((end = OVERLAY_POSITION (OVERLAY_END (XCAR (tail)))) |
| 3359 >= pos)) | 3394 >= pos)) |
| 3360 tailp = &XCDR (*tailp); | 3395 { |
| 3396 parent = tail; | |
| 3397 tail = XCDR (tail); | |
| 3398 } | |
| 3361 | 3399 |
| 3362 /* If we don't find such an overlay, | 3400 /* If we don't find such an overlay, |
| 3363 or the found one ends before PREV, | 3401 or the found one ends before PREV, |
| 3364 or the found one is the last one in the list, | 3402 or the found one is the last one in the list, |
| 3365 we don't have to fix anything. */ | 3403 we don't have to fix anything. */ |
| 3366 if (NILP (*tailp) | 3404 if (NILP (tail) |
| 3367 || end < prev | 3405 || end < prev |
| 3368 || NILP (XCDR (*tailp))) | 3406 || NILP (XCDR (tail))) |
| 3369 return; | 3407 return; |
| 3370 | 3408 |
| 3371 right_place = tailp; | 3409 right_pair = parent; |
| 3372 tailp = &XCDR (*tailp); | 3410 parent = tail; |
| 3373 | 3411 tail = XCDR (tail); |
| 3374 /* Now, end position of overlays in the list *TAILP should be before | 3412 |
| 3413 /* Now, end position of overlays in the list TAIL should be before | |
| 3375 or equal to PREV. In the loop, an overlay which ends at POS is | 3414 or equal to PREV. In the loop, an overlay which ends at POS is |
| 3376 moved ahead to the place pointed by RIGHT_PLACE. If we found an | 3415 moved ahead to the place indicated by the CDR of RIGHT_PAIR. If |
| 3377 overlay which ends before PREV, the remaining overlays are in | 3416 we found an overlay which ends before PREV, the remaining |
| 3378 correct order. */ | 3417 overlays are in correct order. */ |
| 3379 while (!NILP (*tailp)) | 3418 while (!NILP (tail)) |
| 3380 { | 3419 { |
| 3381 end = OVERLAY_POSITION (OVERLAY_END (XCAR (*tailp))); | 3420 end = OVERLAY_POSITION (OVERLAY_END (XCAR (tail))); |
| 3382 | 3421 |
| 3383 if (end == pos) | 3422 if (end == pos) |
| 3384 { /* This overlay is disordered. */ | 3423 { /* This overlay is disordered. */ |
| 3385 Lisp_Object found = *tailp; | 3424 Lisp_Object found = tail; |
| 3386 | 3425 |
| 3387 /* Unlink the found overlay. */ | 3426 /* Unlink the found overlay. */ |
| 3388 *tailp = XCDR (found); | 3427 XSETCDR (parent, XCDR (found)); |
| 3389 /* Move an overlay at RIGHT_PLACE to the next of the found one. */ | 3428 /* Move an overlay at RIGHT_PLACE to the next of the found one, |
| 3390 XCDR (found) = *right_place; | 3429 and link it into the right place. */ |
| 3391 /* Link it into the right place. */ | 3430 if (NILP (right_pair)) |
| 3392 *right_place = found; | 3431 { |
| 3432 XSETCDR (found, bp->overlays_before); | |
| 3433 bp->overlays_before = found; | |
| 3434 } | |
| 3435 else | |
| 3436 { | |
| 3437 XSETCDR (found, XCDR (right_pair)); | |
| 3438 XSETCDR (right_pair, found); | |
| 3439 } | |
| 3393 } | 3440 } |
| 3394 else if (end == prev) | 3441 else if (end == prev) |
| 3395 tailp = &XCDR (*tailp); | 3442 { |
| 3443 parent = tail; | |
| 3444 tail = XCDR (tail); | |
| 3445 } | |
| 3396 else /* No more disordered overlay. */ | 3446 else /* No more disordered overlay. */ |
| 3397 break; | 3447 break; |
| 3398 } | 3448 } |
| 3399 } | 3449 } |
| 3400 | 3450 |
