comparison src/editfns.c @ 26389:e2acf63b5403

(Fline_beginning_position): If N is not 1, pass t to Fconstrain_to_field for ESCAPE-FROM-EDGE. (preceding_pos): Function deleted. (text_property_stickiness): Decrement POS directly. Fix a confusion that used PT instead of POS. (find_field): Properly handle the case of a field boundary where `field' inherits from neither side. (Ffield_beginning, Ffield_end): Doc fixes. (Ferase_field, Ffield_string, Ffield_string_no_properties): Doc fixes.
author Richard M. Stallman <rms@gnu.org>
date Tue, 09 Nov 1999 18:42:28 +0000
parents f35140f031b4
children bda6a3a2bf96
comparison
equal deleted inserted replaced
26388:4577ed337157 26389:e2acf63b5403
270 () 270 ()
271 { 271 {
272 return current_buffer->mark; 272 return current_buffer->mark;
273 } 273 }
274 274
275 /* Returns the position before POS in the current buffer. POS must not 275 /* Return nonzero if POS1 and POS2 have the same value
276 be at the beginning of the buffer. */ 276 for the text property PROP. */
277 static Lisp_Object 277
278 preceding_pos (int pos)
279 {
280 int pos_byte = CHAR_TO_BYTE (pos);
281
282 /* Decrement POS_BYTE (is all this cruft really necessary?). */
283 if (NILP (current_buffer->enable_multibyte_characters))
284 pos_byte--;
285 else
286 DEC_POS (pos_byte);
287
288 return make_number (BYTE_TO_CHAR (pos_byte));
289 }
290
291 /* Returns true if POS1 and POS2 have the same value for text property PROP. */
292 static int 278 static int
293 text_property_eq (prop, pos1, pos2) 279 text_property_eq (prop, pos1, pos2)
294 Lisp_Object prop; 280 Lisp_Object prop;
295 Lisp_Object pos1, pos2; 281 Lisp_Object pos1, pos2;
296 { 282 {
300 pval2 = Fget_text_property (pos2, prop, Qnil); 286 pval2 = Fget_text_property (pos2, prop, Qnil);
301 287
302 return EQ (pval1, pval2); 288 return EQ (pval1, pval2);
303 } 289 }
304 290
305 /* Returns the direction that the text-property PROP would be inherited 291 /* Return the direction from which the text-property PROP would be
306 by any new text inserted at POS: 1 if it would be inherited from POS, 292 inherited by any new text inserted at POS: 1 if it would be
307 -1 if it would be inherited from POS-1, and 0 if from neither. */ 293 inherited from the char after POS, -1 if it would be inherited from
294 the char before POS, and 0 if from neither. */
295
308 static int 296 static int
309 text_property_stickiness (prop, pos) 297 text_property_stickiness (prop, pos)
310 Lisp_Object prop; 298 Lisp_Object prop;
311 Lisp_Object pos; 299 Lisp_Object pos;
312 { 300 {
313 Lisp_Object front_sticky; 301 Lisp_Object front_sticky;
314 302
315 if (PT > BEGV) 303 if (XINT (pos) > BEGV)
316 /* Consider previous position. */ 304 /* Consider previous character. */
317 { 305 {
318 Lisp_Object prev_pos, rear_non_sticky; 306 Lisp_Object prev_pos, rear_non_sticky;
319 307
320 prev_pos = preceding_pos (pos); 308 prev_pos = make_number (XINT (pos) - 1);
321 rear_non_sticky = Fget_text_property (prev_pos, Qrear_nonsticky, Qnil); 309 rear_non_sticky = Fget_text_property (prev_pos, Qrear_nonsticky, Qnil);
322 310
323 if (EQ (rear_non_sticky, Qnil) 311 if (EQ (rear_non_sticky, Qnil)
324 || (CONSP (rear_non_sticky) 312 || (CONSP (rear_non_sticky)
325 && !Fmemq (prop, rear_non_sticky))) 313 && !Fmemq (prop, rear_non_sticky)))
326 /* PROP is not rear-non-sticky, and since this takes precedence over 314 /* PROP is not rear-non-sticky, and since this takes precedence over
327 any front-stickiness, that must be the answer. */ 315 any front-stickiness, PROP is inherited from before. */
328 return -1; 316 return -1;
329 } 317 }
330 318
331 /* Consider current position. */ 319 /* Consider following character. */
332 front_sticky = Fget_text_property (pos, Qfront_sticky, Qnil); 320 front_sticky = Fget_text_property (pos, Qfront_sticky, Qnil);
333 321
334 if (EQ (front_sticky, Qt) 322 if (EQ (front_sticky, Qt)
335 || (CONSP (front_sticky) 323 || (CONSP (front_sticky)
336 && Fmemq (prop, front_sticky))) 324 && Fmemq (prop, front_sticky)))
337 /* PROP is front-sticky. */ 325 /* PROP is inherited from after. */
338 return 1; 326 return 1;
339 327
340 /* PROP is not sticky at all. */ 328 /* PROP is not inherited from either side. */
341 return 0; 329 return 0;
342 } 330 }
343 331
344 /* Name for the text property we use to distinguish fields. */ 332 /* Symbol for the text property used to mark fields. */
345 Lisp_Object Qfield; 333 Lisp_Object Qfield;
346 334
347 /* Returns the field surrounding POS in *BEG and *END; an 335 /* Find the field surrounding POS in *BEG and *END. If POS is nil,
348 `field' is a region of text with the same `field' property. 336 the value of point is used instead.
349 If POS is nil, the position of the current buffer's point is used. 337
350 If MERGE_AT_BOUNDARY is true, then if POS is at the very first 338 If MERGE_AT_BOUNDARY is nonzero, then if POS is at the very first
351 position of a field, then the beginning of the previous field 339 position of a field, then the beginning of the previous field
352 is returned instead of the beginning of POS's field (since the end of 340 is returned instead of the beginning of POS's field (since the end of
353 a field is actually also the beginning of the next input 341 a field is actually also the beginning of the next input
354 field, this behavior is sometimes useful). BEG or END may be 0, in 342 field, this behavior is sometimes useful).
355 which case the corresponding value is not returned. */ 343
344 Either BEG or END may be 0, in which case the corresponding value
345 is not stored. */
346
356 void 347 void
357 find_field (pos, merge_at_boundary, beg, end) 348 find_field (pos, merge_at_boundary, beg, end)
358 Lisp_Object pos; 349 Lisp_Object pos;
359 Lisp_Object merge_at_boundary; 350 Lisp_Object merge_at_boundary;
360 int *beg, *end; 351 int *beg, *end;
361 { 352 {
362 /* If POS is at the edge of a field, then -1 or 1 depending on 353 /* 1 if POS counts as the start of a field. */
363 whether it should be considered as the beginning of the following 354 int at_field_start = 0;
364 field, or the end of the previous field, respectively. If POS is 355 /* 1 if POS counts as the end of a field. */
365 not at a field-boundary, then STICKINESS is 0. */ 356 int at_field_end = 0;
366 int stickiness = 0;
367 357
368 if (NILP (pos)) 358 if (NILP (pos))
369 XSETFASTINT (pos, PT); 359 XSETFASTINT (pos, PT);
370 else 360 else
371 CHECK_NUMBER_COERCE_MARKER (pos, 0); 361 CHECK_NUMBER_COERCE_MARKER (pos, 0);
380 { 370 {
381 /* First see if POS is actually *at* a boundary. */ 371 /* First see if POS is actually *at* a boundary. */
382 Lisp_Object after_field, before_field; 372 Lisp_Object after_field, before_field;
383 373
384 after_field = Fget_text_property (pos, Qfield, Qnil); 374 after_field = Fget_text_property (pos, Qfield, Qnil);
385 before_field = Fget_text_property (preceding_pos (pos), Qfield, Qnil); 375 before_field = Fget_text_property (make_number (XINT (pos) - 1),
376 Qfield, Qnil);
386 377
387 if (! EQ (after_field, before_field)) 378 if (! EQ (after_field, before_field))
388 /* We are at a boundary, see which direction is inclusive. */ 379 /* We are at a boundary, see which direction is inclusive. */
389 { 380 {
390 stickiness = text_property_stickiness (Qfield, pos); 381 int stickiness = text_property_stickiness (Qfield, pos);
391 382
392 if (stickiness == 0) 383 if (stickiness > 0)
384 at_field_start = 1;
385 else if (stickiness < 0)
386 at_field_end = 1;
387 else
393 /* STICKINESS == 0 means that any inserted text will get a 388 /* STICKINESS == 0 means that any inserted text will get a
394 `field' text-property of nil, so check to see if that 389 `field' text-property of nil, so check to see if that
395 matches either of the adjacent characters (this being a 390 matches either of the adjacent characters (this being a
396 kind of `stickiness by default'). */ 391 kind of "stickiness by default"). */
397 { 392 {
398 if (NILP (before_field)) 393 if (NILP (before_field))
399 stickiness = -1; /* Sticks to the left. */ 394 at_field_end = 1; /* Sticks to the left. */
400 else if (NILP (after_field)) 395 else if (NILP (after_field))
401 stickiness = 1; /* Sticks to the right. */ 396 at_field_start = 1; /* Sticks to the right. */
402 } 397 }
403 } 398 }
404 } 399 }
405 400
406 if (beg) 401 if (beg)
407 { 402 {
408 if (stickiness > 0) 403 if (at_field_start)
409 /* POS is at the edge of a field, and we should consider it as 404 /* POS is at the edge of a field, and we should consider it as
410 the beginning of the following field. */ 405 the beginning of the following field. */
411 *beg = XFASTINT (pos); 406 *beg = XFASTINT (pos);
412 else 407 else
413 /* Find the previous field boundary. */ 408 /* Find the previous field boundary. */
414 { 409 {
415 Lisp_Object prev; 410 Lisp_Object prev;
416 prev = Fprevious_single_property_change (pos, Qfield, Qnil, Qnil); 411 prev = Fprevious_single_property_change (pos, Qfield, Qnil, Qnil);
417 *beg = NILP(prev) ? BEGV : XFASTINT (prev); 412 *beg = NILP (prev) ? BEGV : XFASTINT (prev);
418 } 413 }
419 } 414 }
420 415
421 if (end) 416 if (end)
422 { 417 {
423 if (stickiness < 0) 418 if (at_field_end)
424 /* POS is at the edge of a field, and we should consider it as 419 /* POS is at the edge of a field, and we should consider it as
425 the end of the previous field. */ 420 the end of the previous field. */
426 *end = XFASTINT (pos); 421 *end = XFASTINT (pos);
427 else 422 else
428 /* Find the next field boundary. */ 423 /* Find the next field boundary. */
429 { 424 {
430 Lisp_Object next; 425 Lisp_Object next;
431 next = Fnext_single_property_change (pos, Qfield, Qnil, Qnil); 426 next = Fnext_single_property_change (pos, Qfield, Qnil, Qnil);
432 *end = NILP(next) ? ZV : XFASTINT (next); 427 *end = NILP (next) ? ZV : XFASTINT (next);
433 } 428 }
434 } 429 }
435 } 430 }
436 431
437 DEFUN ("delete-field", Fdelete_field, Sdelete_field, 0, 1, "d", 432 DEFUN ("delete-field", Fdelete_field, Sdelete_field, 0, 1, "d",
438 "Delete the field surrounding POS.\n\ 433 "Delete the field surrounding POS.\n\
439 A field is a region of text with the same `field' property.\n\ 434 A field is a region of text with the same `field' property.\n\
440 If POS is nil, the position of the current buffer's point is used.") 435 If POS is nil, the value of point is used for POS.")
441 (pos) 436 (pos)
442 Lisp_Object pos; 437 Lisp_Object pos;
443 { 438 {
444 int beg, end; 439 int beg, end;
445 find_field (pos, Qnil, &beg, &end); 440 find_field (pos, Qnil, &beg, &end);
448 } 443 }
449 444
450 DEFUN ("field-string", Ffield_string, Sfield_string, 0, 1, 0, 445 DEFUN ("field-string", Ffield_string, Sfield_string, 0, 1, 0,
451 "Return the contents of the field surrounding POS as a string.\n\ 446 "Return the contents of the field surrounding POS as a string.\n\
452 A field is a region of text with the same `field' property.\n\ 447 A field is a region of text with the same `field' property.\n\
453 If POS is nil, the position of the current buffer's point is used.") 448 If POS is nil, the value of point is used for POS.")
454 (pos) 449 (pos)
455 Lisp_Object pos; 450 Lisp_Object pos;
456 { 451 {
457 int beg, end; 452 int beg, end;
458 find_field (pos, Qnil, &beg, &end); 453 find_field (pos, Qnil, &beg, &end);
460 } 455 }
461 456
462 DEFUN ("field-string-no-properties", Ffield_string_no_properties, Sfield_string_no_properties, 0, 1, 0, 457 DEFUN ("field-string-no-properties", Ffield_string_no_properties, Sfield_string_no_properties, 0, 1, 0,
463 "Return the contents of the field around POS, without text-properties.\n\ 458 "Return the contents of the field around POS, without text-properties.\n\
464 A field is a region of text with the same `field' property.\n\ 459 A field is a region of text with the same `field' property.\n\
465 If POS is nil, the position of the current buffer's point is used.") 460 If POS is nil, the value of point is used for POS.")
466 (pos) 461 (pos)
467 Lisp_Object pos; 462 Lisp_Object pos;
468 { 463 {
469 int beg, end; 464 int beg, end;
470 find_field (pos, Qnil, &beg, &end); 465 find_field (pos, Qnil, &beg, &end);
472 } 467 }
473 468
474 DEFUN ("field-beginning", Ffield_beginning, Sfield_beginning, 0, 2, 0, 469 DEFUN ("field-beginning", Ffield_beginning, Sfield_beginning, 0, 2, 0,
475 "Return the beginning of the field surrounding POS.\n\ 470 "Return the beginning of the field surrounding POS.\n\
476 A field is a region of text with the same `field' property.\n\ 471 A field is a region of text with the same `field' property.\n\
477 If POS is nil, the position of the current buffer's point is used.\n\ 472 If POS is nil, the value of point is used for POS.\n\
478 If ESCAPE-FROM-EDGE is non-nil and POS is already at beginning of an\n\ 473 If ESCAPE-FROM-EDGE is non-nil and POS is at the beginning of its\n\
479 field, then the beginning of the *previous* field is returned.") 474 field, then the beginning of the *previous* field is returned.")
480 (pos, escape_from_edge) 475 (pos, escape_from_edge)
481 Lisp_Object pos, escape_from_edge; 476 Lisp_Object pos, escape_from_edge;
482 { 477 {
483 int beg; 478 int beg;
486 } 481 }
487 482
488 DEFUN ("field-end", Ffield_end, Sfield_end, 0, 2, 0, 483 DEFUN ("field-end", Ffield_end, Sfield_end, 0, 2, 0,
489 "Return the end of the field surrounding POS.\n\ 484 "Return the end of the field surrounding POS.\n\
490 A field is a region of text with the same `field' property.\n\ 485 A field is a region of text with the same `field' property.\n\
491 If POS is nil, the position of the current buffer's point is used.\n\ 486 If POS is nil, the value of point is used for POS.\n\
492 If ESCAPE-FROM-EDGE is non-nil and POS is already at end of a field,\n\ 487 If ESCAPE-FROM-EDGE is non-nil and POS is at the end of its field,\n\
493 then the end of the *following* field is returned.") 488 then the end of the *following* field is returned.")
494 (pos, escape_from_edge) 489 (pos, escape_from_edge)
495 Lisp_Object pos, escape_from_edge; 490 Lisp_Object pos, escape_from_edge;
496 { 491 {
497 int end; 492 int end;
576 DEFUN ("line-beginning-position", Fline_beginning_position, Sline_beginning_position, 571 DEFUN ("line-beginning-position", Fline_beginning_position, Sline_beginning_position,
577 0, 1, 0, 572 0, 1, 0,
578 "Return the character position of the first character on the current line.\n\ 573 "Return the character position of the first character on the current line.\n\
579 With argument N not nil or 1, move forward N - 1 lines first.\n\ 574 With argument N not nil or 1, move forward N - 1 lines first.\n\
580 If scan reaches end of buffer, return that position.\n\ 575 If scan reaches end of buffer, return that position.\n\
581 This function does not move point.\n\n\ 576 The scan does not cross a field boundary unless it would move\n\
582 In the minibuffer, if point is not within the prompt,\n\ 577 beyond there to a different line. And if N is nil or 1,\n\
583 the return value is never within the prompt either.") 578 and scan starts at a field boundary, the scan stops as soon as it starts.\n\n\
584 579 This function does not move point.")
585 (n) 580 (n)
586 Lisp_Object n; 581 Lisp_Object n;
587 { 582 {
588 register int orig, orig_byte, end; 583 register int orig, orig_byte, end;
589 584
598 end = PT; 593 end = PT;
599 594
600 SET_PT_BOTH (orig, orig_byte); 595 SET_PT_BOTH (orig, orig_byte);
601 596
602 /* Return END constrained to the current input field. */ 597 /* Return END constrained to the current input field. */
603 return Fconstrain_to_field (make_number (end), make_number (orig), Qnil, Qt); 598 return Fconstrain_to_field (make_number (end), make_number (orig),
599 XINT (n) != 1 ? Qt : Qnil,
600 Qt);
604 } 601 }
605 602
606 DEFUN ("line-end-position", Fline_end_position, Sline_end_position, 603 DEFUN ("line-end-position", Fline_end_position, Sline_end_position,
607 0, 1, 0, 604 0, 1, 0,
608 "Return the character position of the last character on the current line.\n\ 605 "Return the character position of the last character on the current line.\n\