diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/editfns.c | 200 |
1 files changed, 85 insertions, 115 deletions
diff --git a/src/editfns.c b/src/editfns.c index 0e1b0c8f01d..8ac0ef16999 100644 --- a/src/editfns.c +++ b/src/editfns.c | |||
| @@ -3800,9 +3800,8 @@ DEFUN ("format", Fformat, Sformat, 1, MANY, 0, | |||
| 3800 | The first argument is a format control string. | 3800 | The first argument is a format control string. |
| 3801 | The other arguments are substituted into it to make the result, a string. | 3801 | The other arguments are substituted into it to make the result, a string. |
| 3802 | 3802 | ||
| 3803 | The format control string may contain ordinary characters, | 3803 | The format control string may contain %-sequences meaning to substitute |
| 3804 | %-sequences meaning to substitute the next available argument, | 3804 | the next available argument: |
| 3805 | and curved single quotation marks meaning to substitute quotes. | ||
| 3806 | 3805 | ||
| 3807 | %s means print a string argument. Actually, prints any object, with `princ'. | 3806 | %s means print a string argument. Actually, prints any object, with `princ'. |
| 3808 | %d means print as number in decimal (%o octal, %x hex). | 3807 | %d means print as number in decimal (%o octal, %x hex). |
| @@ -3850,12 +3849,6 @@ precision specifier says how many decimal places to show; if zero, the | |||
| 3850 | decimal point itself is omitted. For %s and %S, the precision | 3849 | decimal point itself is omitted. For %s and %S, the precision |
| 3851 | specifier truncates the string to the given width. | 3850 | specifier truncates the string to the given width. |
| 3852 | 3851 | ||
| 3853 | \\=‘ and \\=’ means print left and right quotes as per | ||
| 3854 | ‘text-quoting-style’. | ||
| 3855 | |||
| 3856 | Return the first argument if it contains no format directives. | ||
| 3857 | Otherwise, return a new string. | ||
| 3858 | |||
| 3859 | usage: (format STRING &rest OBJECTS) */) | 3852 | usage: (format STRING &rest OBJECTS) */) |
| 3860 | (ptrdiff_t nargs, Lisp_Object *args) | 3853 | (ptrdiff_t nargs, Lisp_Object *args) |
| 3861 | { | 3854 | { |
| @@ -3868,7 +3861,6 @@ usage: (format STRING &rest OBJECTS) */) | |||
| 3868 | ptrdiff_t buf_save_value_index IF_LINT (= 0); | 3861 | ptrdiff_t buf_save_value_index IF_LINT (= 0); |
| 3869 | char *format, *end, *format_start; | 3862 | char *format, *end, *format_start; |
| 3870 | ptrdiff_t formatlen, nchars; | 3863 | ptrdiff_t formatlen, nchars; |
| 3871 | bool changed = false; | ||
| 3872 | /* True if the format is multibyte. */ | 3864 | /* True if the format is multibyte. */ |
| 3873 | bool multibyte_format = 0; | 3865 | bool multibyte_format = 0; |
| 3874 | /* True if the output should be a multibyte string, | 3866 | /* True if the output should be a multibyte string, |
| @@ -4020,7 +4012,6 @@ usage: (format STRING &rest OBJECTS) */) | |||
| 4020 | if (format == end) | 4012 | if (format == end) |
| 4021 | error ("Format string ends in middle of format specifier"); | 4013 | error ("Format string ends in middle of format specifier"); |
| 4022 | 4014 | ||
| 4023 | changed = true; | ||
| 4024 | memset (&discarded[format0 - format_start], 1, format - format0); | 4015 | memset (&discarded[format0 - format_start], 1, format - format0); |
| 4025 | conversion = *format; | 4016 | conversion = *format; |
| 4026 | if (conversion == '%') | 4017 | if (conversion == '%') |
| @@ -4493,20 +4484,6 @@ usage: (format STRING &rest OBJECTS) */) | |||
| 4493 | 4484 | ||
| 4494 | convbytes = format - src; | 4485 | convbytes = format - src; |
| 4495 | memset (&discarded[src + 1 - format_start], 2, convbytes - 1); | 4486 | memset (&discarded[src + 1 - format_start], 2, convbytes - 1); |
| 4496 | |||
| 4497 | if (quoting_style != CURVE_QUOTING_STYLE && convbytes == 3 | ||
| 4498 | && (unsigned char) src[0] == uLSQM0 | ||
| 4499 | && (unsigned char) src[1] == uLSQM1 | ||
| 4500 | && ((unsigned char) src[2] == uLSQM2 | ||
| 4501 | || (unsigned char) src[2] == uRSQM2)) | ||
| 4502 | { | ||
| 4503 | convbytes = 1; | ||
| 4504 | str[0] = (((unsigned char) src[2] == uLSQM2 | ||
| 4505 | && quoting_style == GRAVE_QUOTING_STYLE) | ||
| 4506 | ? '`' : '\''); | ||
| 4507 | src = (char *) str; | ||
| 4508 | changed = true; | ||
| 4509 | } | ||
| 4510 | } | 4487 | } |
| 4511 | else | 4488 | else |
| 4512 | { | 4489 | { |
| @@ -4518,7 +4495,6 @@ usage: (format STRING &rest OBJECTS) */) | |||
| 4518 | int c = BYTE8_TO_CHAR (uc); | 4495 | int c = BYTE8_TO_CHAR (uc); |
| 4519 | convbytes = CHAR_STRING (c, str); | 4496 | convbytes = CHAR_STRING (c, str); |
| 4520 | src = (char *) str; | 4497 | src = (char *) str; |
| 4521 | changed = true; | ||
| 4522 | } | 4498 | } |
| 4523 | } | 4499 | } |
| 4524 | 4500 | ||
| @@ -4566,119 +4542,113 @@ usage: (format STRING &rest OBJECTS) */) | |||
| 4566 | if (bufsize < p - buf) | 4542 | if (bufsize < p - buf) |
| 4567 | emacs_abort (); | 4543 | emacs_abort (); |
| 4568 | 4544 | ||
| 4569 | if (!changed) | 4545 | if (maybe_combine_byte) |
| 4570 | val = args[0]; | 4546 | nchars = multibyte_chars_in_text ((unsigned char *) buf, p - buf); |
| 4571 | else | 4547 | val = make_specified_string (buf, nchars, p - buf, multibyte); |
| 4572 | { | ||
| 4573 | if (maybe_combine_byte) | ||
| 4574 | nchars = multibyte_chars_in_text ((unsigned char *) buf, p - buf); | ||
| 4575 | val = make_specified_string (buf, nchars, p - buf, multibyte); | ||
| 4576 | 4548 | ||
| 4577 | /* If the format string has text properties, or any of the string | 4549 | /* If the format string has text properties, or any of the string |
| 4578 | arguments has text properties, set up text properties of the | 4550 | arguments has text properties, set up text properties of the |
| 4579 | result string. */ | 4551 | result string. */ |
| 4580 | 4552 | ||
| 4581 | if (string_intervals (args[0]) || arg_intervals) | 4553 | if (string_intervals (args[0]) || arg_intervals) |
| 4582 | { | 4554 | { |
| 4583 | Lisp_Object len, new_len, props; | 4555 | Lisp_Object len, new_len, props; |
| 4584 | struct gcpro gcpro1; | 4556 | struct gcpro gcpro1; |
| 4585 | 4557 | ||
| 4586 | /* Add text properties from the format string. */ | 4558 | /* Add text properties from the format string. */ |
| 4587 | len = make_number (SCHARS (args[0])); | 4559 | len = make_number (SCHARS (args[0])); |
| 4588 | props = text_property_list (args[0], make_number (0), len, Qnil); | 4560 | props = text_property_list (args[0], make_number (0), len, Qnil); |
| 4589 | GCPRO1 (props); | 4561 | GCPRO1 (props); |
| 4590 | 4562 | ||
| 4591 | if (CONSP (props)) | 4563 | if (CONSP (props)) |
| 4564 | { | ||
| 4565 | ptrdiff_t bytepos = 0, position = 0, translated = 0; | ||
| 4566 | ptrdiff_t argn = 1; | ||
| 4567 | Lisp_Object list; | ||
| 4568 | |||
| 4569 | /* Adjust the bounds of each text property | ||
| 4570 | to the proper start and end in the output string. */ | ||
| 4571 | |||
| 4572 | /* Put the positions in PROPS in increasing order, so that | ||
| 4573 | we can do (effectively) one scan through the position | ||
| 4574 | space of the format string. */ | ||
| 4575 | props = Fnreverse (props); | ||
| 4576 | |||
| 4577 | /* BYTEPOS is the byte position in the format string, | ||
| 4578 | POSITION is the untranslated char position in it, | ||
| 4579 | TRANSLATED is the translated char position in BUF, | ||
| 4580 | and ARGN is the number of the next arg we will come to. */ | ||
| 4581 | for (list = props; CONSP (list); list = XCDR (list)) | ||
| 4592 | { | 4582 | { |
| 4593 | ptrdiff_t bytepos = 0, position = 0, translated = 0; | 4583 | Lisp_Object item; |
| 4594 | ptrdiff_t argn = 1; | 4584 | ptrdiff_t pos; |
| 4595 | Lisp_Object list; | ||
| 4596 | |||
| 4597 | /* Adjust the bounds of each text property | ||
| 4598 | to the proper start and end in the output string. */ | ||
| 4599 | |||
| 4600 | /* Put the positions in PROPS in increasing order, so that | ||
| 4601 | we can do (effectively) one scan through the position | ||
| 4602 | space of the format string. */ | ||
| 4603 | props = Fnreverse (props); | ||
| 4604 | |||
| 4605 | /* BYTEPOS is the byte position in the format string, | ||
| 4606 | POSITION is the untranslated char position in it, | ||
| 4607 | TRANSLATED is the translated char position in BUF, | ||
| 4608 | and ARGN is the number of the next arg we will come to. */ | ||
| 4609 | for (list = props; CONSP (list); list = XCDR (list)) | ||
| 4610 | { | ||
| 4611 | Lisp_Object item; | ||
| 4612 | ptrdiff_t pos; | ||
| 4613 | 4585 | ||
| 4614 | item = XCAR (list); | 4586 | item = XCAR (list); |
| 4615 | 4587 | ||
| 4616 | /* First adjust the property start position. */ | 4588 | /* First adjust the property start position. */ |
| 4617 | pos = XINT (XCAR (item)); | 4589 | pos = XINT (XCAR (item)); |
| 4618 | 4590 | ||
| 4619 | /* Advance BYTEPOS, POSITION, TRANSLATED and ARGN | 4591 | /* Advance BYTEPOS, POSITION, TRANSLATED and ARGN |
| 4620 | up to this position. */ | 4592 | up to this position. */ |
| 4621 | for (; position < pos; bytepos++) | 4593 | for (; position < pos; bytepos++) |
| 4594 | { | ||
| 4595 | if (! discarded[bytepos]) | ||
| 4596 | position++, translated++; | ||
| 4597 | else if (discarded[bytepos] == 1) | ||
| 4622 | { | 4598 | { |
| 4623 | if (! discarded[bytepos]) | 4599 | position++; |
| 4624 | position++, translated++; | 4600 | if (translated == info[argn].start) |
| 4625 | else if (discarded[bytepos] == 1) | ||
| 4626 | { | 4601 | { |
| 4627 | position++; | 4602 | translated += info[argn].end - info[argn].start; |
| 4628 | if (translated == info[argn].start) | 4603 | argn++; |
| 4629 | { | ||
| 4630 | translated += info[argn].end - info[argn].start; | ||
| 4631 | argn++; | ||
| 4632 | } | ||
| 4633 | } | 4604 | } |
| 4634 | } | 4605 | } |
| 4606 | } | ||
| 4635 | 4607 | ||
| 4636 | XSETCAR (item, make_number (translated)); | 4608 | XSETCAR (item, make_number (translated)); |
| 4637 | 4609 | ||
| 4638 | /* Likewise adjust the property end position. */ | 4610 | /* Likewise adjust the property end position. */ |
| 4639 | pos = XINT (XCAR (XCDR (item))); | 4611 | pos = XINT (XCAR (XCDR (item))); |
| 4640 | 4612 | ||
| 4641 | for (; position < pos; bytepos++) | 4613 | for (; position < pos; bytepos++) |
| 4614 | { | ||
| 4615 | if (! discarded[bytepos]) | ||
| 4616 | position++, translated++; | ||
| 4617 | else if (discarded[bytepos] == 1) | ||
| 4642 | { | 4618 | { |
| 4643 | if (! discarded[bytepos]) | 4619 | position++; |
| 4644 | position++, translated++; | 4620 | if (translated == info[argn].start) |
| 4645 | else if (discarded[bytepos] == 1) | ||
| 4646 | { | 4621 | { |
| 4647 | position++; | 4622 | translated += info[argn].end - info[argn].start; |
| 4648 | if (translated == info[argn].start) | 4623 | argn++; |
| 4649 | { | ||
| 4650 | translated += info[argn].end - info[argn].start; | ||
| 4651 | argn++; | ||
| 4652 | } | ||
| 4653 | } | 4624 | } |
| 4654 | } | 4625 | } |
| 4655 | |||
| 4656 | XSETCAR (XCDR (item), make_number (translated)); | ||
| 4657 | } | 4626 | } |
| 4658 | 4627 | ||
| 4659 | add_text_properties_from_list (val, props, make_number (0)); | 4628 | XSETCAR (XCDR (item), make_number (translated)); |
| 4660 | } | 4629 | } |
| 4661 | 4630 | ||
| 4662 | /* Add text properties from arguments. */ | 4631 | add_text_properties_from_list (val, props, make_number (0)); |
| 4663 | if (arg_intervals) | ||
| 4664 | for (n = 1; n < nargs; ++n) | ||
| 4665 | if (info[n].intervals) | ||
| 4666 | { | ||
| 4667 | len = make_number (SCHARS (args[n])); | ||
| 4668 | new_len = make_number (info[n].end - info[n].start); | ||
| 4669 | props = text_property_list (args[n], make_number (0), | ||
| 4670 | len, Qnil); | ||
| 4671 | props = extend_property_ranges (props, new_len); | ||
| 4672 | /* If successive arguments have properties, be sure that | ||
| 4673 | the value of `composition' property be the copy. */ | ||
| 4674 | if (n > 1 && info[n - 1].end) | ||
| 4675 | make_composition_value_copy (props); | ||
| 4676 | add_text_properties_from_list (val, props, | ||
| 4677 | make_number (info[n].start)); | ||
| 4678 | } | ||
| 4679 | |||
| 4680 | UNGCPRO; | ||
| 4681 | } | 4632 | } |
| 4633 | |||
| 4634 | /* Add text properties from arguments. */ | ||
| 4635 | if (arg_intervals) | ||
| 4636 | for (n = 1; n < nargs; ++n) | ||
| 4637 | if (info[n].intervals) | ||
| 4638 | { | ||
| 4639 | len = make_number (SCHARS (args[n])); | ||
| 4640 | new_len = make_number (info[n].end - info[n].start); | ||
| 4641 | props = text_property_list (args[n], make_number (0), len, Qnil); | ||
| 4642 | props = extend_property_ranges (props, new_len); | ||
| 4643 | /* If successive arguments have properties, be sure that | ||
| 4644 | the value of `composition' property be the copy. */ | ||
| 4645 | if (n > 1 && info[n - 1].end) | ||
| 4646 | make_composition_value_copy (props); | ||
| 4647 | add_text_properties_from_list (val, props, | ||
| 4648 | make_number (info[n].start)); | ||
| 4649 | } | ||
| 4650 | |||
| 4651 | UNGCPRO; | ||
| 4682 | } | 4652 | } |
| 4683 | 4653 | ||
| 4684 | /* If we allocated BUF or INFO with malloc, free it too. */ | 4654 | /* If we allocated BUF or INFO with malloc, free it too. */ |