Mercurial > emacs
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\ |