aboutsummaryrefslogtreecommitdiffstats
path: root/src/casefiddle.c
diff options
context:
space:
mode:
authorPaul Eggert2019-09-22 10:43:21 -0700
committerPaul Eggert2019-09-22 10:45:14 -0700
commit2f600e97e7ca43965f55f019759582d93d8bca73 (patch)
treed885dcef77f04a60da6cec56a2750b19a8e64192 /src/casefiddle.c
parentdddff96a585531608d5e8d27375a6363679a9fb5 (diff)
downloademacs-2f600e97e7ca43965f55f019759582d93d8bca73.tar.gz
emacs-2f600e97e7ca43965f55f019759582d93d8bca73.zip
Avoid crashes when casifying noncontiguous regions
This is a followon fix for Bug#37477. * lisp/simple.el (region-extract-function): Use setq here, since the var is now defined in C code. * src/casefiddle.c (casify_pnc_region): New function. (Fupcase_region, Fdowncase_region, Fcapitalize_region) (Fupcase_initials_region): Use it. (Fupcase_initials_region): Add region-noncontiguous-p flag for consistency with the others. All uses changed. (syms_of_casefiddle): Define Qbounds, Vregion_extract_function. * src/insdel.c (prepare_to_modify_buffer_1): * src/keyboard.c (command_loop_1): Use Vregion_extraction_function. * src/insdel.c (syms_of_insdel): No need to define Qregion_extract_function. * test/src/casefiddle-tests.el (casefiddle-oldfunc): New var. (casefiddle-loopfunc, casefiddle-badfunc): New functions. (casefiddle-invalid-region-extract-function): New test.
Diffstat (limited to 'src/casefiddle.c')
-rw-r--r--src/casefiddle.c104
1 files changed, 49 insertions, 55 deletions
diff --git a/src/casefiddle.c b/src/casefiddle.c
index 3a1724b306d..774906df04d 100644
--- a/src/casefiddle.c
+++ b/src/casefiddle.c
@@ -516,34 +516,43 @@ casify_region (enum case_action flag, Lisp_Object b, Lisp_Object e)
516 return orig_end + added; 516 return orig_end + added;
517} 517}
518 518
519DEFUN ("upcase-region", Fupcase_region, Supcase_region, 2, 3, 519/* Casify a possibly noncontiguous region according to FLAG. BEG and
520 "(list (region-beginning) (region-end) (region-noncontiguous-p))", 520 END specify the bounds, except that if REGION_NONCONTIGUOUS_P is
521 doc: /* Convert the region to upper case. In programs, wants two arguments. 521 non-nil, the region's bounds are specified by (funcall
522These arguments specify the starting and ending character numbers of 522 region-extract-function 'bounds) instead. */
523the region to operate on. When used as a command, the text between
524point and the mark is operated on.
525See also `capitalize-region'. */)
526 (Lisp_Object beg, Lisp_Object end, Lisp_Object region_noncontiguous_p)
527{
528 Lisp_Object bounds = Qnil;
529 523
524static Lisp_Object
525casify_pnc_region (enum case_action flag, Lisp_Object beg, Lisp_Object end,
526 Lisp_Object region_noncontiguous_p)
527{
530 if (!NILP (region_noncontiguous_p)) 528 if (!NILP (region_noncontiguous_p))
531 { 529 {
532 bounds = call1 (Fsymbol_value (Qregion_extract_function), 530 Lisp_Object bounds = call1 (Vregion_extract_function, Qbounds);
533 intern ("bounds")); 531 FOR_EACH_TAIL (bounds)
534
535 while (CONSP (bounds))
536 { 532 {
537 casify_region (CASE_UP, XCAR (XCAR (bounds)), XCDR (XCAR (bounds))); 533 CHECK_CONS (XCAR (bounds));
538 bounds = XCDR (bounds); 534 casify_region (flag, XCAR (XCAR (bounds)), XCDR (XCAR (bounds)));
539 } 535 }
536 CHECK_LIST_END (bounds, bounds);
540 } 537 }
541 else 538 else
542 casify_region (CASE_UP, beg, end); 539 casify_region (flag, beg, end);
543 540
544 return Qnil; 541 return Qnil;
545} 542}
546 543
544DEFUN ("upcase-region", Fupcase_region, Supcase_region, 2, 3,
545 "(list (region-beginning) (region-end) (region-noncontiguous-p))",
546 doc: /* Convert the region to upper case. In programs, wants two arguments.
547These arguments specify the starting and ending character numbers of
548the region to operate on. When used as a command, the text between
549point and the mark is operated on.
550See also `capitalize-region'. */)
551 (Lisp_Object beg, Lisp_Object end, Lisp_Object region_noncontiguous_p)
552{
553 return casify_pnc_region (CASE_UP, beg, end, region_noncontiguous_p);
554}
555
547DEFUN ("downcase-region", Fdowncase_region, Sdowncase_region, 2, 3, 556DEFUN ("downcase-region", Fdowncase_region, Sdowncase_region, 2, 3,
548 "(list (region-beginning) (region-end) (region-noncontiguous-p))", 557 "(list (region-beginning) (region-end) (region-noncontiguous-p))",
549 doc: /* Convert the region to lower case. In programs, wants two arguments. 558 doc: /* Convert the region to lower case. In programs, wants two arguments.
@@ -552,23 +561,7 @@ the region to operate on. When used as a command, the text between
552point and the mark is operated on. */) 561point and the mark is operated on. */)
553 (Lisp_Object beg, Lisp_Object end, Lisp_Object region_noncontiguous_p) 562 (Lisp_Object beg, Lisp_Object end, Lisp_Object region_noncontiguous_p)
554{ 563{
555 Lisp_Object bounds = Qnil; 564 return casify_pnc_region (CASE_DOWN, beg, end, region_noncontiguous_p);
556
557 if (!NILP (region_noncontiguous_p))
558 {
559 bounds = call1 (Fsymbol_value (Qregion_extract_function),
560 intern ("bounds"));
561
562 while (CONSP (bounds))
563 {
564 casify_region (CASE_DOWN, XCAR (XCAR (bounds)), XCDR (XCAR (bounds)));
565 bounds = XCDR (bounds);
566 }
567 }
568 else
569 casify_region (CASE_DOWN, beg, end);
570
571 return Qnil;
572} 565}
573 566
574DEFUN ("capitalize-region", Fcapitalize_region, Scapitalize_region, 2, 3, 567DEFUN ("capitalize-region", Fcapitalize_region, Scapitalize_region, 2, 3,
@@ -580,38 +573,23 @@ In programs, give two arguments, the starting and ending
580character positions to operate on. */) 573character positions to operate on. */)
581 (Lisp_Object beg, Lisp_Object end, Lisp_Object region_noncontiguous_p) 574 (Lisp_Object beg, Lisp_Object end, Lisp_Object region_noncontiguous_p)
582{ 575{
583 Lisp_Object bounds = Qnil; 576 return casify_pnc_region (CASE_CAPITALIZE, beg, end, region_noncontiguous_p);
584
585 if (!NILP (region_noncontiguous_p))
586 {
587 bounds = call1 (Fsymbol_value (Qregion_extract_function),
588 intern ("bounds"));
589
590 while (CONSP (bounds))
591 {
592 casify_region (CASE_CAPITALIZE, XCAR (XCAR (bounds)), XCDR (XCAR (bounds)));
593 bounds = XCDR (bounds);
594 }
595 }
596 else
597 casify_region (CASE_CAPITALIZE, beg, end);
598
599 return Qnil;
600} 577}
601 578
602/* Like Fcapitalize_region but change only the initials. */ 579/* Like Fcapitalize_region but change only the initials. */
603 580
604DEFUN ("upcase-initials-region", Fupcase_initials_region, 581DEFUN ("upcase-initials-region", Fupcase_initials_region,
605 Supcase_initials_region, 2, 2, "r", 582 Supcase_initials_region, 2, 3,
583 "(list (region-beginning) (region-end) (region-noncontiguous-p))",
606 doc: /* Upcase the initial of each word in the region. 584 doc: /* Upcase the initial of each word in the region.
607This means that each word's first character is converted to either 585This means that each word's first character is converted to either
608title case or upper case, and the rest are left unchanged. 586title case or upper case, and the rest are left unchanged.
609In programs, give two arguments, the starting and ending 587In programs, give two arguments, the starting and ending
610character positions to operate on. */) 588character positions to operate on. */)
611 (Lisp_Object beg, Lisp_Object end) 589 (Lisp_Object beg, Lisp_Object end, Lisp_Object region_noncontiguous_p)
612{ 590{
613 casify_region (CASE_CAPITALIZE_UP, beg, end); 591 return casify_pnc_region (CASE_CAPITALIZE_UP, beg, end,
614 return Qnil; 592 region_noncontiguous_p);
615} 593}
616 594
617static Lisp_Object 595static Lisp_Object
@@ -668,12 +646,28 @@ With negative argument, capitalize previous words but do not move. */)
668void 646void
669syms_of_casefiddle (void) 647syms_of_casefiddle (void)
670{ 648{
649 DEFSYM (Qbounds, "bounds");
671 DEFSYM (Qidentity, "identity"); 650 DEFSYM (Qidentity, "identity");
672 DEFSYM (Qtitlecase, "titlecase"); 651 DEFSYM (Qtitlecase, "titlecase");
673 DEFSYM (Qspecial_uppercase, "special-uppercase"); 652 DEFSYM (Qspecial_uppercase, "special-uppercase");
674 DEFSYM (Qspecial_lowercase, "special-lowercase"); 653 DEFSYM (Qspecial_lowercase, "special-lowercase");
675 DEFSYM (Qspecial_titlecase, "special-titlecase"); 654 DEFSYM (Qspecial_titlecase, "special-titlecase");
676 655
656 DEFVAR_LISP ("region-extract-function", Vregion_extract_function,
657 doc: /* Function to get the region's content.
658Called with one argument METHOD which can be:
659- nil: return the content as a string (list of strings for
660 non-contiguous regions).
661- `delete-only': delete the region; the return value is undefined.
662- `bounds': return the boundaries of the region as a list of one
663 or more cons cells of the form (START . END).
664- anything else: delete the region and return its content
665 as a string (or list of strings for non-contiguous regions),
666 after filtering it with `filter-buffer-substring', which
667 is called, for each contiguous sub-region, with METHOD as its
668 3rd argument. */);
669 Vregion_extract_function = Qnil; /* simple.el sets this. */
670
677 defsubr (&Supcase); 671 defsubr (&Supcase);
678 defsubr (&Sdowncase); 672 defsubr (&Sdowncase);
679 defsubr (&Scapitalize); 673 defsubr (&Scapitalize);