diff options
| author | Kenichi Handa | 2004-04-07 07:23:24 +0000 |
|---|---|---|
| committer | Kenichi Handa | 2004-04-07 07:23:24 +0000 |
| commit | f555f8cfb679efc5816a1dcb336b310135020608 (patch) | |
| tree | c7ad5f5729c096a4aeb715ae26f29b0e83a5ff2c /src | |
| parent | 350cd166ce580a8e2bd8ec1f8e0b8d27d6ece32e (diff) | |
| download | emacs-f555f8cfb679efc5816a1dcb336b310135020608.tar.gz emacs-f555f8cfb679efc5816a1dcb336b310135020608.zip | |
Sync to HEAD.
(check_translation): New function.
(Ftranslate_region_internal): Handle M:N mapping.
Diffstat (limited to 'src')
| -rw-r--r-- | src/editfns.c | 215 |
1 files changed, 167 insertions, 48 deletions
diff --git a/src/editfns.c b/src/editfns.c index 01797acbdf4..ace0f1f8835 100644 --- a/src/editfns.c +++ b/src/editfns.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* Lisp functions pertaining to editing. | 1 | /* Lisp functions pertaining to editing. |
| 2 | Copyright (C) 1985,86,87,89,93,94,95,96,97,98, 1999, 2000, 2001, 02, 2003 | 2 | Copyright (C) 1985,86,87,89,93,94,95,96,97,98,1999,2000,01,02,03,2004 |
| 3 | Free Software Foundation, Inc. | 3 | Free Software Foundation, Inc. |
| 4 | 4 | ||
| 5 | This file is part of GNU Emacs. | 5 | This file is part of GNU Emacs. |
| @@ -294,7 +294,7 @@ region_limit (beginningp) | |||
| 294 | if (NILP (m)) | 294 | if (NILP (m)) |
| 295 | error ("The mark is not set now, so there is no region"); | 295 | error ("The mark is not set now, so there is no region"); |
| 296 | 296 | ||
| 297 | if ((PT < XFASTINT (m)) == beginningp) | 297 | if ((PT < XFASTINT (m)) == (beginningp != 0)) |
| 298 | m = make_number (PT); | 298 | m = make_number (PT); |
| 299 | return m; | 299 | return m; |
| 300 | } | 300 | } |
| @@ -1133,7 +1133,7 @@ DEFUN ("eolp", Feolp, Seolp, 0, 0, 0, | |||
| 1133 | 1133 | ||
| 1134 | DEFUN ("char-after", Fchar_after, Schar_after, 0, 1, 0, | 1134 | DEFUN ("char-after", Fchar_after, Schar_after, 0, 1, 0, |
| 1135 | doc: /* Return character in current buffer at position POS. | 1135 | doc: /* Return character in current buffer at position POS. |
| 1136 | POS is an integer or a marker. | 1136 | POS is an integer or a marker and defaults to point. |
| 1137 | If POS is out of range, the value is nil. */) | 1137 | If POS is out of range, the value is nil. */) |
| 1138 | (pos) | 1138 | (pos) |
| 1139 | Lisp_Object pos; | 1139 | Lisp_Object pos; |
| @@ -1166,7 +1166,7 @@ If POS is out of range, the value is nil. */) | |||
| 1166 | 1166 | ||
| 1167 | DEFUN ("char-before", Fchar_before, Schar_before, 0, 1, 0, | 1167 | DEFUN ("char-before", Fchar_before, Schar_before, 0, 1, 0, |
| 1168 | doc: /* Return character in current buffer preceding position POS. | 1168 | doc: /* Return character in current buffer preceding position POS. |
| 1169 | POS is an integer or a marker. | 1169 | POS is an integer or a marker and defaults to point. |
| 1170 | If POS is out of range, the value is nil. */) | 1170 | If POS is out of range, the value is nil. */) |
| 1171 | (pos) | 1171 | (pos) |
| 1172 | Lisp_Object pos; | 1172 | Lisp_Object pos; |
| @@ -1660,6 +1660,9 @@ for example, a DAY of 0 means the day preceding the given month. | |||
| 1660 | Year numbers less than 100 are treated just like other year numbers. | 1660 | Year numbers less than 100 are treated just like other year numbers. |
| 1661 | If you want them to stand for years in this century, you must do that yourself. | 1661 | If you want them to stand for years in this century, you must do that yourself. |
| 1662 | 1662 | ||
| 1663 | Years before 1970 are not guaranteed to work. On some systems, | ||
| 1664 | year values as low as 1901 do work. | ||
| 1665 | |||
| 1663 | usage: (encode-time SECOND MINUTE HOUR DAY MONTH YEAR &optional ZONE) */) | 1666 | usage: (encode-time SECOND MINUTE HOUR DAY MONTH YEAR &optional ZONE) */) |
| 1664 | (nargs, args) | 1667 | (nargs, args) |
| 1665 | int nargs; | 1668 | int nargs; |
| @@ -2752,13 +2755,73 @@ Both characters must have the same length of multi-byte form. */) | |||
| 2752 | return Qnil; | 2755 | return Qnil; |
| 2753 | } | 2756 | } |
| 2754 | 2757 | ||
| 2758 | |||
| 2759 | static Lisp_Object check_translation P_ ((int, int, int, Lisp_Object)); | ||
| 2760 | |||
| 2761 | /* Helper function for Ftranslate_region_internal. | ||
| 2762 | |||
| 2763 | Check if a character sequence at POS (POS_BYTE) matches an element | ||
| 2764 | of VAL. VAL is a list (([FROM-CHAR ...] . TO) ...). If a matching | ||
| 2765 | element is found, return it. Otherwise return Qnil. */ | ||
| 2766 | |||
| 2767 | static Lisp_Object | ||
| 2768 | check_translation (pos, pos_byte, end, val) | ||
| 2769 | int pos, pos_byte, end; | ||
| 2770 | Lisp_Object val; | ||
| 2771 | { | ||
| 2772 | int buf_size = 16, buf_used = 0; | ||
| 2773 | int *buf = alloca (sizeof (int) * buf_size); | ||
| 2774 | |||
| 2775 | for (; CONSP (val); val = XCDR (val)) | ||
| 2776 | { | ||
| 2777 | Lisp_Object elt; | ||
| 2778 | int len, i; | ||
| 2779 | |||
| 2780 | elt = XCAR (val); | ||
| 2781 | if (! CONSP (elt)) | ||
| 2782 | continue; | ||
| 2783 | elt = XCAR (elt); | ||
| 2784 | if (! VECTORP (elt)) | ||
| 2785 | continue; | ||
| 2786 | len = ASIZE (elt); | ||
| 2787 | if (len <= end - pos) | ||
| 2788 | { | ||
| 2789 | for (i = 0; i < len; i++) | ||
| 2790 | { | ||
| 2791 | if (buf_used <= i) | ||
| 2792 | { | ||
| 2793 | unsigned char *p = BYTE_POS_ADDR (pos_byte); | ||
| 2794 | int len; | ||
| 2795 | |||
| 2796 | if (buf_used == buf_size) | ||
| 2797 | { | ||
| 2798 | int *newbuf; | ||
| 2799 | |||
| 2800 | buf_size += 16; | ||
| 2801 | newbuf = alloca (sizeof (int) * buf_size); | ||
| 2802 | memcpy (newbuf, buf, sizeof (int) * buf_used); | ||
| 2803 | buf = newbuf; | ||
| 2804 | } | ||
| 2805 | buf[buf_used++] = STRING_CHAR_AND_LENGTH (p, 0, len); | ||
| 2806 | pos_byte += len; | ||
| 2807 | } | ||
| 2808 | if (XINT (AREF (elt, i)) != buf[i]) | ||
| 2809 | break; | ||
| 2810 | } | ||
| 2811 | if (i == len) | ||
| 2812 | return XCAR (val); | ||
| 2813 | } | ||
| 2814 | } | ||
| 2815 | return Qnil; | ||
| 2816 | } | ||
| 2817 | |||
| 2818 | |||
| 2755 | DEFUN ("translate-region-internal", Ftranslate_region_internal, | 2819 | DEFUN ("translate-region-internal", Ftranslate_region_internal, |
| 2756 | Stranslate_region_internal, 3, 3, 0, | 2820 | Stranslate_region_internal, 3, 3, 0, |
| 2757 | doc: /* Internal use only. | 2821 | doc: /* Internal use only. |
| 2758 | From START to END, translate characters according to TABLE. | 2822 | From START to END, translate characters according to TABLE. |
| 2759 | TABLE is a string; the Nth character in it is the mapping | 2823 | TABLE is a string or a char-table; the Nth character in it is the |
| 2760 | for the character with code N. | 2824 | mapping for the character with code N. |
| 2761 | This function does not alter multibyte characters. | ||
| 2762 | It returns the number of characters changed. */) | 2825 | It returns the number of characters changed. */) |
| 2763 | (start, end, table) | 2826 | (start, end, table) |
| 2764 | Lisp_Object start; | 2827 | Lisp_Object start; |
| @@ -2769,14 +2832,18 @@ It returns the number of characters changed. */) | |||
| 2769 | register int nc; /* New character. */ | 2832 | register int nc; /* New character. */ |
| 2770 | int cnt; /* Number of changes made. */ | 2833 | int cnt; /* Number of changes made. */ |
| 2771 | int size; /* Size of translate table. */ | 2834 | int size; /* Size of translate table. */ |
| 2772 | int pos, pos_byte; | 2835 | int pos, pos_byte, end_pos; |
| 2773 | int multibyte = !NILP (current_buffer->enable_multibyte_characters); | 2836 | int multibyte = !NILP (current_buffer->enable_multibyte_characters); |
| 2774 | int string_multibyte; | 2837 | int string_multibyte; |
| 2775 | Lisp_Object val; | 2838 | Lisp_Object val; |
| 2776 | 2839 | ||
| 2777 | validate_region (&start, &end); | 2840 | validate_region (&start, &end); |
| 2778 | if (CHAR_TABLE_P (table)) | 2841 | if (CHAR_TABLE_P (table)) |
| 2779 | tt = NULL; | 2842 | { |
| 2843 | if (! EQ (XCHAR_TABLE (table)->purpose, Qtranslation_table)) | ||
| 2844 | error ("Not a translation table"); | ||
| 2845 | tt = NULL; | ||
| 2846 | } | ||
| 2780 | else | 2847 | else |
| 2781 | { | 2848 | { |
| 2782 | CHECK_STRING (table); | 2849 | CHECK_STRING (table); |
| @@ -2792,18 +2859,20 @@ It returns the number of characters changed. */) | |||
| 2792 | 2859 | ||
| 2793 | pos = XINT (start); | 2860 | pos = XINT (start); |
| 2794 | pos_byte = CHAR_TO_BYTE (pos); | 2861 | pos_byte = CHAR_TO_BYTE (pos); |
| 2795 | modify_region (current_buffer, XINT (start), XINT (end)); | 2862 | end_pos = XINT (end); |
| 2863 | modify_region (current_buffer, pos, end_pos); | ||
| 2796 | 2864 | ||
| 2797 | cnt = 0; | 2865 | cnt = 0; |
| 2798 | for (; pos < XINT (end); ) | 2866 | for (; pos < end_pos; ) |
| 2799 | { | 2867 | { |
| 2800 | register unsigned char *p = BYTE_POS_ADDR (pos_byte); | 2868 | register unsigned char *p = BYTE_POS_ADDR (pos_byte); |
| 2801 | unsigned char *str, buf[MAX_MULTIBYTE_LENGTH]; | 2869 | unsigned char *str, buf[MAX_MULTIBYTE_LENGTH]; |
| 2802 | int len, str_len; | 2870 | int len, str_len; |
| 2803 | int oc; | 2871 | int oc; |
| 2872 | Lisp_Object val; | ||
| 2804 | 2873 | ||
| 2805 | if (multibyte) | 2874 | if (multibyte) |
| 2806 | nc = oc = STRING_CHAR_AND_LENGTH (p, stop - pos_byte, len); | 2875 | nc = oc = STRING_CHAR_AND_LENGTH (p, 0, len); |
| 2807 | else | 2876 | else |
| 2808 | nc = oc = *p, len = 1; | 2877 | nc = oc = *p, len = 1; |
| 2809 | if (tt) | 2878 | if (tt) |
| @@ -2824,8 +2893,6 @@ It returns the number of characters changed. */) | |||
| 2824 | } | 2893 | } |
| 2825 | else | 2894 | else |
| 2826 | { | 2895 | { |
| 2827 | Lisp_Object val; | ||
| 2828 | |||
| 2829 | val = CHAR_TABLE_REF (table, oc); | 2896 | val = CHAR_TABLE_REF (table, oc); |
| 2830 | if (CHARACTERP (val)) | 2897 | if (CHARACTERP (val)) |
| 2831 | { | 2898 | { |
| @@ -2833,29 +2900,79 @@ It returns the number of characters changed. */) | |||
| 2833 | str_len = CHAR_STRING (nc, buf); | 2900 | str_len = CHAR_STRING (nc, buf); |
| 2834 | str = buf; | 2901 | str = buf; |
| 2835 | } | 2902 | } |
| 2903 | else if (VECTORP (val) || (CONSP (val))) | ||
| 2904 | { | ||
| 2905 | /* VAL is [TO_CHAR ...] or (([FROM-CHAR ...] . TO) ...) | ||
| 2906 | where TO is TO-CHAR or [TO-CHAR ...]. */ | ||
| 2907 | nc = -1; | ||
| 2908 | } | ||
| 2836 | } | 2909 | } |
| 2837 | 2910 | ||
| 2838 | if (nc != oc) | 2911 | if (nc != oc) |
| 2839 | { | 2912 | { |
| 2840 | if (len != str_len) | 2913 | if (nc >= 0) |
| 2841 | { | 2914 | { |
| 2842 | Lisp_Object string; | 2915 | /* Simple one char to one char translation. */ |
| 2916 | if (len != str_len) | ||
| 2917 | { | ||
| 2918 | Lisp_Object string; | ||
| 2843 | 2919 | ||
| 2844 | /* This is less efficient, because it moves the gap, | 2920 | /* This is less efficient, because it moves the gap, |
| 2845 | but it should multibyte characters correctly. */ | 2921 | but it should handle multibyte characters correctly. */ |
| 2846 | string = make_multibyte_string (str, 1, str_len); | 2922 | string = make_multibyte_string (str, 1, str_len); |
| 2847 | replace_range (pos, pos + 1, string, 1, 0, 1); | 2923 | replace_range (pos, pos + 1, string, 1, 0, 1); |
| 2848 | len = str_len; | 2924 | len = str_len; |
| 2925 | } | ||
| 2926 | else | ||
| 2927 | { | ||
| 2928 | record_change (pos, 1); | ||
| 2929 | while (str_len-- > 0) | ||
| 2930 | *p++ = *str++; | ||
| 2931 | signal_after_change (pos, 1, 1); | ||
| 2932 | update_compositions (pos, pos + 1, CHECK_BORDER); | ||
| 2933 | } | ||
| 2934 | ++cnt; | ||
| 2849 | } | 2935 | } |
| 2850 | else | 2936 | else |
| 2851 | { | 2937 | { |
| 2852 | record_change (pos, 1); | 2938 | Lisp_Object string; |
| 2853 | while (str_len-- > 0) | 2939 | |
| 2854 | *p++ = *str++; | 2940 | if (CONSP (val)) |
| 2855 | signal_after_change (pos, 1, 1); | 2941 | { |
| 2856 | update_compositions (pos, pos + 1, CHECK_BORDER); | 2942 | val = check_translation (pos, pos_byte, end_pos, val); |
| 2943 | if (NILP (val)) | ||
| 2944 | { | ||
| 2945 | pos_byte += len; | ||
| 2946 | pos++; | ||
| 2947 | continue; | ||
| 2948 | } | ||
| 2949 | /* VAL is ([FROM-CHAR ...] . TO). */ | ||
| 2950 | len = ASIZE (XCAR (val)); | ||
| 2951 | val = XCDR (val); | ||
| 2952 | } | ||
| 2953 | else | ||
| 2954 | len = 1; | ||
| 2955 | |||
| 2956 | if (VECTORP (val)) | ||
| 2957 | { | ||
| 2958 | int i; | ||
| 2959 | |||
| 2960 | string = Fmake_string (make_number (ASIZE (val)), | ||
| 2961 | AREF (val, 0)); | ||
| 2962 | for (i = 1; i < ASIZE (val); i++) | ||
| 2963 | Faset (string, make_number (i), AREF (val, i)); | ||
| 2964 | } | ||
| 2965 | else | ||
| 2966 | { | ||
| 2967 | string = Fmake_string (make_number (1), val); | ||
| 2968 | } | ||
| 2969 | replace_range (pos, pos + len, string, 1, 0, 1); | ||
| 2970 | pos_byte += SBYTES (string); | ||
| 2971 | pos += SCHARS (string); | ||
| 2972 | cnt += SCHARS (string); | ||
| 2973 | end_pos += SCHARS (string) - len; | ||
| 2974 | continue; | ||
| 2857 | } | 2975 | } |
| 2858 | ++cnt; | ||
| 2859 | } | 2976 | } |
| 2860 | pos_byte += len; | 2977 | pos_byte += len; |
| 2861 | pos++; | 2978 | pos++; |
| @@ -3231,6 +3348,10 @@ It may contain %-sequences meaning to substitute the next argument. | |||
| 3231 | The argument used for %d, %o, %x, %e, %f, %g or %c must be a number. | 3348 | The argument used for %d, %o, %x, %e, %f, %g or %c must be a number. |
| 3232 | Use %% to put a single % into the output. | 3349 | Use %% to put a single % into the output. |
| 3233 | 3350 | ||
| 3351 | The basic structure of a %-sequence is | ||
| 3352 | % <flags> <width> <precision> character | ||
| 3353 | where flags is [- #0]+, width is [0-9]+, and precision is .[0-9]+ | ||
| 3354 | |||
| 3234 | usage: (format STRING &rest OBJECTS) */) | 3355 | usage: (format STRING &rest OBJECTS) */) |
| 3235 | (nargs, args) | 3356 | (nargs, args) |
| 3236 | int nargs; | 3357 | int nargs; |
| @@ -3315,7 +3436,7 @@ usage: (format STRING &rest OBJECTS) */) | |||
| 3315 | int i; | 3436 | int i; |
| 3316 | info = (struct info *) alloca (nbytes); | 3437 | info = (struct info *) alloca (nbytes); |
| 3317 | bzero (info, nbytes); | 3438 | bzero (info, nbytes); |
| 3318 | for (i = 0; i <= nargs; i++) | 3439 | for (i = 0; i < nargs; i++) |
| 3319 | info[i].start = -1; | 3440 | info[i].start = -1; |
| 3320 | discarded = (char *) alloca (SBYTES (args[0])); | 3441 | discarded = (char *) alloca (SBYTES (args[0])); |
| 3321 | bzero (discarded, SBYTES (args[0])); | 3442 | bzero (discarded, SBYTES (args[0])); |
| @@ -3338,7 +3459,7 @@ usage: (format STRING &rest OBJECTS) */) | |||
| 3338 | 3459 | ||
| 3339 | where | 3460 | where |
| 3340 | 3461 | ||
| 3341 | flags ::= [#-* 0]+ | 3462 | flags ::= [- #0]+ |
| 3342 | field-width ::= [0-9]+ | 3463 | field-width ::= [0-9]+ |
| 3343 | precision ::= '.' [0-9]* | 3464 | precision ::= '.' [0-9]* |
| 3344 | 3465 | ||
| @@ -3350,14 +3471,7 @@ usage: (format STRING &rest OBJECTS) */) | |||
| 3350 | digits to print after the '.' for floats, or the max. | 3471 | digits to print after the '.' for floats, or the max. |
| 3351 | number of chars to print from a string. */ | 3472 | number of chars to print from a string. */ |
| 3352 | 3473 | ||
| 3353 | /* NOTE the handling of specifiers here differs in some ways | 3474 | while (index ("-0# ", *format)) |
| 3354 | from the libc model. There are bugs in this code that lead | ||
| 3355 | to incorrect formatting when flags recognized by C but | ||
| 3356 | neither parsed nor rejected here are used. Further | ||
| 3357 | revisions will be made soon. */ | ||
| 3358 | |||
| 3359 | /* incorrect list of flags to skip; will be fixed */ | ||
| 3360 | while (index ("-*# 0", *format)) | ||
| 3361 | ++format; | 3475 | ++format; |
| 3362 | 3476 | ||
| 3363 | if (*format >= '0' && *format <= '9') | 3477 | if (*format >= '0' && *format <= '9') |
| @@ -3485,7 +3599,7 @@ usage: (format STRING &rest OBJECTS) */) | |||
| 3485 | /* Anything but a string, convert to a string using princ. */ | 3599 | /* Anything but a string, convert to a string using princ. */ |
| 3486 | register Lisp_Object tem; | 3600 | register Lisp_Object tem; |
| 3487 | tem = Fprin1_to_string (args[n], Qt); | 3601 | tem = Fprin1_to_string (args[n], Qt); |
| 3488 | if (STRING_MULTIBYTE (tem) & ! multibyte) | 3602 | if (STRING_MULTIBYTE (tem) && ! multibyte) |
| 3489 | { | 3603 | { |
| 3490 | multibyte = 1; | 3604 | multibyte = 1; |
| 3491 | goto retry; | 3605 | goto retry; |
| @@ -3532,17 +3646,19 @@ usage: (format STRING &rest OBJECTS) */) | |||
| 3532 | discarded[format - format_start] = 1; | 3646 | discarded[format - format_start] = 1; |
| 3533 | format++; | 3647 | format++; |
| 3534 | 3648 | ||
| 3535 | /* Process a numeric arg and skip it. */ | 3649 | while (index("-0# ", *format)) |
| 3536 | /* NOTE atoi is the wrong thing to use here; will be fixed */ | 3650 | { |
| 3651 | if (*format == '-') | ||
| 3652 | { | ||
| 3653 | negative = 1; | ||
| 3654 | } | ||
| 3655 | discarded[format - format_start] = 1; | ||
| 3656 | ++format; | ||
| 3657 | } | ||
| 3658 | |||
| 3537 | minlen = atoi (format); | 3659 | minlen = atoi (format); |
| 3538 | if (minlen < 0) | 3660 | |
| 3539 | minlen = - minlen, negative = 1; | 3661 | while ((*format >= '0' && *format <= '9') || *format == '.') |
| 3540 | |||
| 3541 | /* NOTE the parsing here is not consistent with the first | ||
| 3542 | pass, and neither attempt is what we want to do. Will be | ||
| 3543 | fixed. */ | ||
| 3544 | while ((*format >= '0' && *format <= '9') | ||
| 3545 | || *format == '-' || *format == ' ' || *format == '.') | ||
| 3546 | { | 3662 | { |
| 3547 | discarded[format - format_start] = 1; | 3663 | discarded[format - format_start] = 1; |
| 3548 | format++; | 3664 | format++; |
| @@ -4358,3 +4474,6 @@ functions if all the text being accessed has this property. */); | |||
| 4358 | defsubr (&Ssave_restriction); | 4474 | defsubr (&Ssave_restriction); |
| 4359 | defsubr (&Stranspose_regions); | 4475 | defsubr (&Stranspose_regions); |
| 4360 | } | 4476 | } |
| 4477 | |||
| 4478 | /* arch-tag: fc3827d8-6f60-4067-b11e-c3218031b018 | ||
| 4479 | (do not change this comment) */ | ||