diff options
| author | Stefan Monnier | 2002-10-30 23:11:26 +0000 |
|---|---|---|
| committer | Stefan Monnier | 2002-10-30 23:11:26 +0000 |
| commit | 58401a3476a31efdf8481293bcf58e220313bdd4 (patch) | |
| tree | cfec7fbaced3d8193771f3a4e11ed44735b22378 /src | |
| parent | 2baf1bfa5498425f0df6e899e554e8e91427969e (diff) | |
| download | emacs-58401a3476a31efdf8481293bcf58e220313bdd4.tar.gz emacs-58401a3476a31efdf8481293bcf58e220313bdd4.zip | |
(overlays_around, get_pos_property): New funs.
(find_field): Use them.
Also be careful not to modify POS before its last use.
(Fmessage): Don't Fformat if there's nothing to format.
Diffstat (limited to 'src')
| -rw-r--r-- | src/editfns.c | 225 |
1 files changed, 158 insertions, 67 deletions
diff --git a/src/editfns.c b/src/editfns.c index 51cf0c0b789..bf4976273aa 100644 --- a/src/editfns.c +++ b/src/editfns.c | |||
| @@ -328,6 +328,149 @@ If you set the marker not to point anywhere, the buffer will have no mark. */) | |||
| 328 | } | 328 | } |
| 329 | 329 | ||
| 330 | 330 | ||
| 331 | /* Find all the overlays in the current buffer that touch position POS. | ||
| 332 | Return the number found, and store them in a vector in VEC | ||
| 333 | of length LEN. */ | ||
| 334 | |||
| 335 | static int | ||
| 336 | overlays_around (pos, vec, len) | ||
| 337 | int pos; | ||
| 338 | Lisp_Object *vec; | ||
| 339 | int len; | ||
| 340 | { | ||
| 341 | Lisp_Object tail, overlay, start, end; | ||
| 342 | int startpos, endpos; | ||
| 343 | int idx = 0; | ||
| 344 | |||
| 345 | for (tail = current_buffer->overlays_before; | ||
| 346 | GC_CONSP (tail); | ||
| 347 | tail = XCDR (tail)) | ||
| 348 | { | ||
| 349 | overlay = XCAR (tail); | ||
| 350 | |||
| 351 | end = OVERLAY_END (overlay); | ||
| 352 | endpos = OVERLAY_POSITION (end); | ||
| 353 | if (endpos < pos) | ||
| 354 | break; | ||
| 355 | start = OVERLAY_START (overlay); | ||
| 356 | startpos = OVERLAY_POSITION (start); | ||
| 357 | if (startpos <= pos) | ||
| 358 | { | ||
| 359 | if (idx < len) | ||
| 360 | vec[idx] = overlay; | ||
| 361 | /* Keep counting overlays even if we can't return them all. */ | ||
| 362 | idx++; | ||
| 363 | } | ||
| 364 | } | ||
| 365 | |||
| 366 | for (tail = current_buffer->overlays_after; | ||
| 367 | GC_CONSP (tail); | ||
| 368 | tail = XCDR (tail)) | ||
| 369 | { | ||
| 370 | overlay = XCAR (tail); | ||
| 371 | |||
| 372 | start = OVERLAY_START (overlay); | ||
| 373 | startpos = OVERLAY_POSITION (start); | ||
| 374 | if (pos < startpos) | ||
| 375 | break; | ||
| 376 | end = OVERLAY_END (overlay); | ||
| 377 | endpos = OVERLAY_POSITION (end); | ||
| 378 | if (pos <= endpos) | ||
| 379 | { | ||
| 380 | if (idx < len) | ||
| 381 | vec[idx] = overlay; | ||
| 382 | idx++; | ||
| 383 | } | ||
| 384 | } | ||
| 385 | |||
| 386 | return idx; | ||
| 387 | } | ||
| 388 | |||
| 389 | /* Return the value of property PROP, in OBJECT at POSITION. | ||
| 390 | It's the value of PROP that a char inserted at POSITION would get. | ||
| 391 | OBJECT is optional and defaults to the current buffer. | ||
| 392 | If OBJECT is a buffer, then overlay properties are considered as well as | ||
| 393 | text properties. | ||
| 394 | If OBJECT is a window, then that window's buffer is used, but | ||
| 395 | window-specific overlays are considered only if they are associated | ||
| 396 | with OBJECT. */ | ||
| 397 | static Lisp_Object | ||
| 398 | get_pos_property (position, prop, object) | ||
| 399 | Lisp_Object position, object; | ||
| 400 | register Lisp_Object prop; | ||
| 401 | { | ||
| 402 | struct window *w = 0; | ||
| 403 | |||
| 404 | CHECK_NUMBER_COERCE_MARKER (position); | ||
| 405 | |||
| 406 | if (NILP (object)) | ||
| 407 | XSETBUFFER (object, current_buffer); | ||
| 408 | |||
| 409 | if (WINDOWP (object)) | ||
| 410 | { | ||
| 411 | w = XWINDOW (object); | ||
| 412 | object = w->buffer; | ||
| 413 | } | ||
| 414 | if (BUFFERP (object)) | ||
| 415 | { | ||
| 416 | int posn = XINT (position); | ||
| 417 | int noverlays; | ||
| 418 | Lisp_Object *overlay_vec, tem; | ||
| 419 | struct buffer *obuf = current_buffer; | ||
| 420 | |||
| 421 | set_buffer_temp (XBUFFER (object)); | ||
| 422 | |||
| 423 | /* First try with room for 40 overlays. */ | ||
| 424 | noverlays = 40; | ||
| 425 | overlay_vec = (Lisp_Object *) alloca (noverlays * sizeof (Lisp_Object)); | ||
| 426 | noverlays = overlays_around (posn, overlay_vec, noverlays); | ||
| 427 | |||
| 428 | /* If there are more than 40, | ||
| 429 | make enough space for all, and try again. */ | ||
| 430 | if (noverlays > 40) | ||
| 431 | { | ||
| 432 | overlay_vec = (Lisp_Object *) alloca (noverlays * sizeof (Lisp_Object)); | ||
| 433 | noverlays = overlays_around (posn, overlay_vec, noverlays); | ||
| 434 | } | ||
| 435 | noverlays = sort_overlays (overlay_vec, noverlays, NULL); | ||
| 436 | |||
| 437 | set_buffer_temp (obuf); | ||
| 438 | |||
| 439 | /* Now check the overlays in order of decreasing priority. */ | ||
| 440 | while (--noverlays >= 0) | ||
| 441 | { | ||
| 442 | Lisp_Object ol = overlay_vec[noverlays]; | ||
| 443 | tem = Foverlay_get (ol, prop); | ||
| 444 | if (!NILP (tem)) | ||
| 445 | { | ||
| 446 | /* Check the overlay is indeed active at point. */ | ||
| 447 | Lisp_Object start = OVERLAY_START (ol), finish = OVERLAY_END (ol); | ||
| 448 | if ((OVERLAY_POSITION (start) == posn | ||
| 449 | && XMARKER (start)->insertion_type == 1) | ||
| 450 | || (OVERLAY_POSITION (finish) == posn | ||
| 451 | && XMARKER (finish)->insertion_type == 0)) | ||
| 452 | ; /* The overlay will not cover a char inserted at point. */ | ||
| 453 | else | ||
| 454 | { | ||
| 455 | return tem; | ||
| 456 | } | ||
| 457 | } | ||
| 458 | } | ||
| 459 | |||
| 460 | } | ||
| 461 | |||
| 462 | { /* Now check the text-properties. */ | ||
| 463 | int stickiness = text_property_stickiness (Qfield, position); | ||
| 464 | if (stickiness > 0) | ||
| 465 | return Fget_text_property (position, Qfield, Qnil); | ||
| 466 | else if (stickiness < 0 && XINT (position) > BEGV) | ||
| 467 | return Fget_text_property (make_number (XINT (position) - 1), | ||
| 468 | Qfield, Qnil); | ||
| 469 | else | ||
| 470 | return Qnil; | ||
| 471 | } | ||
| 472 | } | ||
| 473 | |||
| 331 | /* Find the field surrounding POS in *BEG and *END. If POS is nil, | 474 | /* Find the field surrounding POS in *BEG and *END. If POS is nil, |
| 332 | the value of point is used instead. If BEG or END null, | 475 | the value of point is used instead. If BEG or END null, |
| 333 | means don't store the beginning or end of the field. | 476 | means don't store the beginning or end of the field. |
| @@ -357,9 +500,6 @@ find_field (pos, merge_at_boundary, beg_limit, beg, end_limit, end) | |||
| 357 | { | 500 | { |
| 358 | /* Fields right before and after the point. */ | 501 | /* Fields right before and after the point. */ |
| 359 | Lisp_Object before_field, after_field; | 502 | Lisp_Object before_field, after_field; |
| 360 | /* If the fields came from overlays, the associated overlays. | ||
| 361 | Qnil means they came from text-properties. */ | ||
| 362 | Lisp_Object before_overlay = Qnil, after_overlay = Qnil; | ||
| 363 | /* 1 if POS counts as the start of a field. */ | 503 | /* 1 if POS counts as the start of a field. */ |
| 364 | int at_field_start = 0; | 504 | int at_field_start = 0; |
| 365 | /* 1 if POS counts as the end of a field. */ | 505 | /* 1 if POS counts as the end of a field. */ |
| @@ -371,12 +511,11 @@ find_field (pos, merge_at_boundary, beg_limit, beg, end_limit, end) | |||
| 371 | CHECK_NUMBER_COERCE_MARKER (pos); | 511 | CHECK_NUMBER_COERCE_MARKER (pos); |
| 372 | 512 | ||
| 373 | after_field | 513 | after_field |
| 374 | = get_char_property_and_overlay (pos, Qfield, Qnil, &after_overlay); | 514 | = get_char_property_and_overlay (pos, Qfield, Qnil, NULL); |
| 375 | before_field | 515 | before_field |
| 376 | = (XFASTINT (pos) > BEGV | 516 | = (XFASTINT (pos) > BEGV |
| 377 | ? get_char_property_and_overlay (make_number (XINT (pos) - 1), | 517 | ? get_char_property_and_overlay (make_number (XINT (pos) - 1), |
| 378 | Qfield, Qnil, | 518 | Qfield, Qnil, NULL) |
| 379 | &before_overlay) | ||
| 380 | : Qnil); | 519 | : Qnil); |
| 381 | 520 | ||
| 382 | /* See if we need to handle the case where MERGE_AT_BOUNDARY is nil | 521 | /* See if we need to handle the case where MERGE_AT_BOUNDARY is nil |
| @@ -385,62 +524,13 @@ find_field (pos, merge_at_boundary, beg_limit, beg, end_limit, end) | |||
| 385 | MERGE_AT_BOUNDARY is non-nil (see function comment) is actually the | 524 | MERGE_AT_BOUNDARY is non-nil (see function comment) is actually the |
| 386 | more natural one; then we avoid treating the beginning of a field | 525 | more natural one; then we avoid treating the beginning of a field |
| 387 | specially. */ | 526 | specially. */ |
| 388 | if (NILP (merge_at_boundary) && !EQ (after_field, before_field)) | 527 | if (NILP (merge_at_boundary)) |
| 389 | /* We are at a boundary, see which direction is inclusive. We | 528 | { |
| 390 | decide by seeing which field the `field' property sticks to. */ | 529 | Lisp_Object field = get_pos_property (pos, Qfield, Qnil); |
| 391 | { | 530 | if (!EQ (field, after_field)) |
| 392 | /* -1 means insertions go into before_field, 1 means they go | ||
| 393 | into after_field, 0 means neither. */ | ||
| 394 | int stickiness; | ||
| 395 | /* Whether the before/after_field come from overlays. */ | ||
| 396 | int bop = !NILP (before_overlay); | ||
| 397 | int aop = !NILP (after_overlay); | ||
| 398 | |||
| 399 | if (bop && XMARKER (OVERLAY_END (before_overlay))->insertion_type == 1) | ||
| 400 | /* before_field is from an overlay, which expands upon | ||
| 401 | end-insertions. Note that it's possible for after_overlay to | ||
| 402 | also eat insertions here, but then they will overlap, and | ||
| 403 | there's not much we can do. */ | ||
| 404 | stickiness = -1; | ||
| 405 | else if (aop | ||
| 406 | && XMARKER (OVERLAY_START (after_overlay))->insertion_type == 0) | ||
| 407 | /* after_field is from an overlay, which expand to contain | ||
| 408 | start-insertions. */ | ||
| 409 | stickiness = 1; | ||
| 410 | else if (bop && aop) | ||
| 411 | /* Both fields come from overlays, but neither will contain any | ||
| 412 | insertion here. */ | ||
| 413 | stickiness = 0; | ||
| 414 | else if (bop) | ||
| 415 | /* before_field is an overlay that won't eat any insertion, but | ||
| 416 | after_field is from a text-property. Assume that the | ||
| 417 | text-property continues underneath the overlay, and so will | ||
| 418 | be inherited by any insertion, regardless of any stickiness | ||
| 419 | settings. */ | ||
| 420 | stickiness = 1; | ||
| 421 | else if (aop) | ||
| 422 | /* Similarly, when after_field is the overlay. */ | ||
| 423 | stickiness = -1; | ||
| 424 | else | ||
| 425 | /* Both fields come from text-properties. Look for explicit | ||
| 426 | stickiness properties. */ | ||
| 427 | stickiness = text_property_stickiness (Qfield, pos); | ||
| 428 | |||
| 429 | if (stickiness > 0) | ||
| 430 | at_field_start = 1; | ||
| 431 | else if (stickiness < 0) | ||
| 432 | at_field_end = 1; | 531 | at_field_end = 1; |
| 433 | else | 532 | if (!EQ (field, before_field)) |
| 434 | /* STICKINESS == 0 means that any inserted text will get a | 533 | at_field_start = 1; |
| 435 | `field' char-property of nil, so check to see if that | ||
| 436 | matches either of the adjacent characters (this being a | ||
| 437 | kind of "stickiness by default"). */ | ||
| 438 | { | ||
| 439 | if (NILP (before_field)) | ||
| 440 | at_field_end = 1; /* Sticks to the left. */ | ||
| 441 | else if (NILP (after_field)) | ||
| 442 | at_field_start = 1; /* Sticks to the right. */ | ||
| 443 | } | ||
| 444 | } | 534 | } |
| 445 | 535 | ||
| 446 | /* Note about special `boundary' fields: | 536 | /* Note about special `boundary' fields: |
| @@ -474,14 +564,15 @@ find_field (pos, merge_at_boundary, beg_limit, beg, end_limit, end) | |||
| 474 | else | 564 | else |
| 475 | /* Find the previous field boundary. */ | 565 | /* Find the previous field boundary. */ |
| 476 | { | 566 | { |
| 567 | Lisp_Object p = pos; | ||
| 477 | if (!NILP (merge_at_boundary) && EQ (before_field, Qboundary)) | 568 | if (!NILP (merge_at_boundary) && EQ (before_field, Qboundary)) |
| 478 | /* Skip a `boundary' field. */ | 569 | /* Skip a `boundary' field. */ |
| 479 | pos = Fprevious_single_char_property_change (pos, Qfield, Qnil, | 570 | p = Fprevious_single_char_property_change (p, Qfield, Qnil, |
| 480 | beg_limit); | ||
| 481 | |||
| 482 | pos = Fprevious_single_char_property_change (pos, Qfield, Qnil, | ||
| 483 | beg_limit); | 571 | beg_limit); |
| 484 | *beg = NILP (pos) ? BEGV : XFASTINT (pos); | 572 | |
| 573 | p = Fprevious_single_char_property_change (p, Qfield, Qnil, | ||
| 574 | beg_limit); | ||
| 575 | *beg = NILP (p) ? BEGV : XFASTINT (p); | ||
| 485 | } | 576 | } |
| 486 | } | 577 | } |
| 487 | 578 | ||
| @@ -2930,7 +3021,7 @@ usage: (message STRING &rest ARGS) */) | |||
| 2930 | else | 3021 | else |
| 2931 | { | 3022 | { |
| 2932 | register Lisp_Object val; | 3023 | register Lisp_Object val; |
| 2933 | val = Fformat (nargs, args); | 3024 | val = nargs < 2 && STRINGP (args[0]) ? args[0] : Fformat (nargs, args); |
| 2934 | message3 (val, SBYTES (val), STRING_MULTIBYTE (val)); | 3025 | message3 (val, SBYTES (val), STRING_MULTIBYTE (val)); |
| 2935 | return val; | 3026 | return val; |
| 2936 | } | 3027 | } |