Mercurial > emacs
comparison src/editfns.c @ 48094:2a8ba962e34d
(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.
author | Stefan Monnier <monnier@iro.umontreal.ca> |
---|---|
date | Wed, 30 Oct 2002 23:11:26 +0000 |
parents | 7ac7ca5ac550 |
children | 7103ad01172d |
comparison
equal
deleted
inserted
replaced
48093:b7cdece1cebf | 48094:2a8ba962e34d |
---|---|
326 { | 326 { |
327 return current_buffer->mark; | 327 return current_buffer->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. |
334 | 477 |
335 BEG_LIMIT and END_LIMIT serve to limit the ranged of the returned | 478 BEG_LIMIT and END_LIMIT serve to limit the ranged of the returned |
355 Lisp_Object beg_limit, end_limit; | 498 Lisp_Object beg_limit, end_limit; |
356 int *beg, *end; | 499 int *beg, *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. */ |
366 int at_field_end = 0; | 506 int at_field_end = 0; |
367 | 507 |
369 XSETFASTINT (pos, PT); | 509 XSETFASTINT (pos, PT); |
370 else | 510 else |
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 |
383 and POS is at beginning of a field, which can also be interpreted | 522 and POS is at beginning of a field, which can also be interpreted |
384 as the end of the previous field. Note that the case where if | 523 as the end of the previous field. Note that the case where if |
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 | 531 at_field_end = 1; |
393 into after_field, 0 means neither. */ | 532 if (!EQ (field, before_field)) |
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; | 533 at_field_start = 1; |
431 else if (stickiness < 0) | |
432 at_field_end = 1; | |
433 else | |
434 /* STICKINESS == 0 means that any inserted text will get a | |
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: |
447 | 537 |
448 Consider the case where the point (`.') is between the fields `x' and `y': | 538 Consider the case where the point (`.') is between the fields `x' and `y': |
472 the beginning of the following field. */ | 562 the beginning of the following field. */ |
473 *beg = XFASTINT (pos); | 563 *beg = XFASTINT (pos); |
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 |
488 if (end) | 579 if (end) |
489 { | 580 { |
2928 return Qnil; | 3019 return Qnil; |
2929 } | 3020 } |
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 } |
2937 } | 3028 } |
2938 | 3029 |