diff options
Diffstat (limited to 'src/editfns.c')
| -rw-r--r-- | src/editfns.c | 187 |
1 files changed, 166 insertions, 21 deletions
diff --git a/src/editfns.c b/src/editfns.c index 43d4aa2aaa2..15510779603 100644 --- a/src/editfns.c +++ b/src/editfns.c | |||
| @@ -52,7 +52,7 @@ Boston, MA 02110-1301, USA. */ | |||
| 52 | 52 | ||
| 53 | #include "intervals.h" | 53 | #include "intervals.h" |
| 54 | #include "buffer.h" | 54 | #include "buffer.h" |
| 55 | #include "charset.h" | 55 | #include "character.h" |
| 56 | #include "coding.h" | 56 | #include "coding.h" |
| 57 | #include "frame.h" | 57 | #include "frame.h" |
| 58 | #include "window.h" | 58 | #include "window.h" |
| @@ -210,11 +210,9 @@ usage: (char-to-string CHAR) */) | |||
| 210 | int len; | 210 | int len; |
| 211 | unsigned char str[MAX_MULTIBYTE_LENGTH]; | 211 | unsigned char str[MAX_MULTIBYTE_LENGTH]; |
| 212 | 212 | ||
| 213 | CHECK_NUMBER (character); | 213 | CHECK_CHARACTER (character); |
| 214 | 214 | ||
| 215 | len = (SINGLE_BYTE_CHAR_P (XFASTINT (character)) | 215 | len = CHAR_STRING (XFASTINT (character), str); |
| 216 | ? (*str = (unsigned char)(XFASTINT (character)), 1) | ||
| 217 | : char_to_string (XFASTINT (character), str)); | ||
| 218 | return make_string_from_bytes (str, 1, len); | 216 | return make_string_from_bytes (str, 1, len); |
| 219 | } | 217 | } |
| 220 | 218 | ||
| @@ -2155,7 +2153,7 @@ general_insert_function (insert_func, insert_from_string_func, | |||
| 2155 | for (argnum = 0; argnum < nargs; argnum++) | 2153 | for (argnum = 0; argnum < nargs; argnum++) |
| 2156 | { | 2154 | { |
| 2157 | val = args[argnum]; | 2155 | val = args[argnum]; |
| 2158 | if (INTEGERP (val)) | 2156 | if (CHARACTERP (val)) |
| 2159 | { | 2157 | { |
| 2160 | unsigned char str[MAX_MULTIBYTE_LENGTH]; | 2158 | unsigned char str[MAX_MULTIBYTE_LENGTH]; |
| 2161 | int len; | 2159 | int len; |
| @@ -2164,7 +2162,7 @@ general_insert_function (insert_func, insert_from_string_func, | |||
| 2164 | len = CHAR_STRING (XFASTINT (val), str); | 2162 | len = CHAR_STRING (XFASTINT (val), str); |
| 2165 | else | 2163 | else |
| 2166 | { | 2164 | { |
| 2167 | str[0] = (SINGLE_BYTE_CHAR_P (XINT (val)) | 2165 | str[0] = (ASCII_CHAR_P (XINT (val)) |
| 2168 | ? XINT (val) | 2166 | ? XINT (val) |
| 2169 | : multibyte_char_to_unibyte (XINT (val), Qnil)); | 2167 | : multibyte_char_to_unibyte (XINT (val), Qnil)); |
| 2170 | len = 1; | 2168 | len = 1; |
| @@ -2331,6 +2329,29 @@ from adjoining text, if those properties are sticky. */) | |||
| 2331 | return Qnil; | 2329 | return Qnil; |
| 2332 | } | 2330 | } |
| 2333 | 2331 | ||
| 2332 | DEFUN ("insert-byte", Finsert_byte, Sinsert_byte, 2, 3, 0, | ||
| 2333 | doc: /* Insert COUNT (second arg) copies of BYTE (first arg). | ||
| 2334 | Both arguments are required. | ||
| 2335 | BYTE is a number of the range 0..255. | ||
| 2336 | |||
| 2337 | If BYTE is 128..255 and the current buffer is multibyte, the | ||
| 2338 | corresponding eight-bit character is inserted. | ||
| 2339 | |||
| 2340 | Point, and before-insertion markers, are relocated as in the function `insert'. | ||
| 2341 | The optional third arg INHERIT, if non-nil, says to inherit text properties | ||
| 2342 | from adjoining text, if those properties are sticky. */) | ||
| 2343 | (byte, count, inherit) | ||
| 2344 | Lisp_Object byte, count, inherit; | ||
| 2345 | { | ||
| 2346 | CHECK_NUMBER (byte); | ||
| 2347 | if (XINT (byte) < 0 || XINT (byte) > 255) | ||
| 2348 | args_out_of_range_3 (byte, make_number (0), make_number (255)); | ||
| 2349 | if (XINT (byte) >= 128 | ||
| 2350 | && ! NILP (current_buffer->enable_multibyte_characters)) | ||
| 2351 | XSETFASTINT (byte, BYTE8_TO_CHAR (XINT (byte))); | ||
| 2352 | return Finsert_char (byte, count, inherit); | ||
| 2353 | } | ||
| 2354 | |||
| 2334 | 2355 | ||
| 2335 | /* Making strings from buffer contents. */ | 2356 | /* Making strings from buffer contents. */ |
| 2336 | 2357 | ||
| @@ -2892,12 +2913,73 @@ Both characters must have the same length of multi-byte form. */) | |||
| 2892 | return Qnil; | 2913 | return Qnil; |
| 2893 | } | 2914 | } |
| 2894 | 2915 | ||
| 2916 | |||
| 2917 | static Lisp_Object check_translation P_ ((int, int, int, Lisp_Object)); | ||
| 2918 | |||
| 2919 | /* Helper function for Ftranslate_region_internal. | ||
| 2920 | |||
| 2921 | Check if a character sequence at POS (POS_BYTE) matches an element | ||
| 2922 | of VAL. VAL is a list (([FROM-CHAR ...] . TO) ...). If a matching | ||
| 2923 | element is found, return it. Otherwise return Qnil. */ | ||
| 2924 | |||
| 2925 | static Lisp_Object | ||
| 2926 | check_translation (pos, pos_byte, end, val) | ||
| 2927 | int pos, pos_byte, end; | ||
| 2928 | Lisp_Object val; | ||
| 2929 | { | ||
| 2930 | int buf_size = 16, buf_used = 0; | ||
| 2931 | int *buf = alloca (sizeof (int) * buf_size); | ||
| 2932 | |||
| 2933 | for (; CONSP (val); val = XCDR (val)) | ||
| 2934 | { | ||
| 2935 | Lisp_Object elt; | ||
| 2936 | int len, i; | ||
| 2937 | |||
| 2938 | elt = XCAR (val); | ||
| 2939 | if (! CONSP (elt)) | ||
| 2940 | continue; | ||
| 2941 | elt = XCAR (elt); | ||
| 2942 | if (! VECTORP (elt)) | ||
| 2943 | continue; | ||
| 2944 | len = ASIZE (elt); | ||
| 2945 | if (len <= end - pos) | ||
| 2946 | { | ||
| 2947 | for (i = 0; i < len; i++) | ||
| 2948 | { | ||
| 2949 | if (buf_used <= i) | ||
| 2950 | { | ||
| 2951 | unsigned char *p = BYTE_POS_ADDR (pos_byte); | ||
| 2952 | int len; | ||
| 2953 | |||
| 2954 | if (buf_used == buf_size) | ||
| 2955 | { | ||
| 2956 | int *newbuf; | ||
| 2957 | |||
| 2958 | buf_size += 16; | ||
| 2959 | newbuf = alloca (sizeof (int) * buf_size); | ||
| 2960 | memcpy (newbuf, buf, sizeof (int) * buf_used); | ||
| 2961 | buf = newbuf; | ||
| 2962 | } | ||
| 2963 | buf[buf_used++] = STRING_CHAR_AND_LENGTH (p, 0, len); | ||
| 2964 | pos_byte += len; | ||
| 2965 | } | ||
| 2966 | if (XINT (AREF (elt, i)) != buf[i]) | ||
| 2967 | break; | ||
| 2968 | } | ||
| 2969 | if (i == len) | ||
| 2970 | return XCAR (val); | ||
| 2971 | } | ||
| 2972 | } | ||
| 2973 | return Qnil; | ||
| 2974 | } | ||
| 2975 | |||
| 2976 | |||
| 2895 | DEFUN ("translate-region-internal", Ftranslate_region_internal, | 2977 | DEFUN ("translate-region-internal", Ftranslate_region_internal, |
| 2896 | Stranslate_region_internal, 3, 3, 0, | 2978 | Stranslate_region_internal, 3, 3, 0, |
| 2897 | doc: /* Internal use only. | 2979 | doc: /* Internal use only. |
| 2898 | From START to END, translate characters according to TABLE. | 2980 | From START to END, translate characters according to TABLE. |
| 2899 | TABLE is a string; the Nth character in it is the mapping | 2981 | TABLE is a string or a char-table; the Nth character in it is the |
| 2900 | for the character with code N. | 2982 | mapping for the character with code N. |
| 2901 | It returns the number of characters changed. */) | 2983 | It returns the number of characters changed. */) |
| 2902 | (start, end, table) | 2984 | (start, end, table) |
| 2903 | Lisp_Object start; | 2985 | Lisp_Object start; |
| @@ -2911,10 +2993,13 @@ It returns the number of characters changed. */) | |||
| 2911 | int pos, pos_byte, end_pos; | 2993 | int pos, pos_byte, end_pos; |
| 2912 | int multibyte = !NILP (current_buffer->enable_multibyte_characters); | 2994 | int multibyte = !NILP (current_buffer->enable_multibyte_characters); |
| 2913 | int string_multibyte; | 2995 | int string_multibyte; |
| 2996 | Lisp_Object val; | ||
| 2914 | 2997 | ||
| 2915 | validate_region (&start, &end); | 2998 | validate_region (&start, &end); |
| 2916 | if (CHAR_TABLE_P (table)) | 2999 | if (CHAR_TABLE_P (table)) |
| 2917 | { | 3000 | { |
| 3001 | if (! EQ (XCHAR_TABLE (table)->purpose, Qtranslation_table)) | ||
| 3002 | error ("Not a translation table"); | ||
| 2918 | size = MAX_CHAR; | 3003 | size = MAX_CHAR; |
| 2919 | tt = NULL; | 3004 | tt = NULL; |
| 2920 | } | 3005 | } |
| @@ -2925,14 +3010,14 @@ It returns the number of characters changed. */) | |||
| 2925 | if (! multibyte && (SCHARS (table) < SBYTES (table))) | 3010 | if (! multibyte && (SCHARS (table) < SBYTES (table))) |
| 2926 | table = string_make_unibyte (table); | 3011 | table = string_make_unibyte (table); |
| 2927 | string_multibyte = SCHARS (table) < SBYTES (table); | 3012 | string_multibyte = SCHARS (table) < SBYTES (table); |
| 2928 | size = SCHARS (table); | 3013 | size = SBYTES (table); |
| 2929 | tt = SDATA (table); | 3014 | tt = SDATA (table); |
| 2930 | } | 3015 | } |
| 2931 | 3016 | ||
| 2932 | pos = XINT (start); | 3017 | pos = XINT (start); |
| 2933 | pos_byte = CHAR_TO_BYTE (pos); | 3018 | pos_byte = CHAR_TO_BYTE (pos); |
| 2934 | end_pos = XINT (end); | 3019 | end_pos = XINT (end); |
| 2935 | modify_region (current_buffer, pos, XINT (end), 0); | 3020 | modify_region (current_buffer, pos, end_pos, 0); |
| 2936 | 3021 | ||
| 2937 | cnt = 0; | 3022 | cnt = 0; |
| 2938 | for (; pos < end_pos; ) | 3023 | for (; pos < end_pos; ) |
| @@ -2941,6 +3026,7 @@ It returns the number of characters changed. */) | |||
| 2941 | unsigned char *str, buf[MAX_MULTIBYTE_LENGTH]; | 3026 | unsigned char *str, buf[MAX_MULTIBYTE_LENGTH]; |
| 2942 | int len, str_len; | 3027 | int len, str_len; |
| 2943 | int oc; | 3028 | int oc; |
| 3029 | Lisp_Object val; | ||
| 2944 | 3030 | ||
| 2945 | if (multibyte) | 3031 | if (multibyte) |
| 2946 | oc = STRING_CHAR_AND_LENGTH (p, MAX_MULTIBYTE_LENGTH, len); | 3032 | oc = STRING_CHAR_AND_LENGTH (p, MAX_MULTIBYTE_LENGTH, len); |
| @@ -2955,7 +3041,7 @@ It returns the number of characters changed. */) | |||
| 2955 | if (string_multibyte) | 3041 | if (string_multibyte) |
| 2956 | { | 3042 | { |
| 2957 | str = tt + string_char_to_byte (table, oc); | 3043 | str = tt + string_char_to_byte (table, oc); |
| 2958 | nc = STRING_CHAR_AND_LENGTH (str, MAX_MULTIBYTE_LENGTH, | 3044 | nc = STRING_CHAR_AND_LENGTH (str, MAX_MULTIBYTE_LENGTH, |
| 2959 | str_len); | 3045 | str_len); |
| 2960 | } | 3046 | } |
| 2961 | else | 3047 | else |
| @@ -2963,7 +3049,7 @@ It returns the number of characters changed. */) | |||
| 2963 | nc = tt[oc]; | 3049 | nc = tt[oc]; |
| 2964 | if (! ASCII_BYTE_P (nc) && multibyte) | 3050 | if (! ASCII_BYTE_P (nc) && multibyte) |
| 2965 | { | 3051 | { |
| 2966 | str_len = CHAR_STRING (nc, buf); | 3052 | str_len = BYTE8_STRING (nc, buf); |
| 2967 | str = buf; | 3053 | str = buf; |
| 2968 | } | 3054 | } |
| 2969 | else | 3055 | else |
| @@ -2975,28 +3061,34 @@ It returns the number of characters changed. */) | |||
| 2975 | } | 3061 | } |
| 2976 | else | 3062 | else |
| 2977 | { | 3063 | { |
| 2978 | Lisp_Object val; | ||
| 2979 | int c; | 3064 | int c; |
| 2980 | 3065 | ||
| 2981 | nc = oc; | 3066 | nc = oc; |
| 2982 | val = CHAR_TABLE_REF (table, oc); | 3067 | val = CHAR_TABLE_REF (table, oc); |
| 2983 | if (INTEGERP (val) | 3068 | if (CHARACTERP (val) |
| 2984 | && (c = XINT (val), CHAR_VALID_P (c, 0))) | 3069 | && (c = XINT (val), CHAR_VALID_P (c, 0))) |
| 2985 | { | 3070 | { |
| 2986 | nc = c; | 3071 | nc = c; |
| 2987 | str_len = CHAR_STRING (nc, buf); | 3072 | str_len = CHAR_STRING (nc, buf); |
| 2988 | str = buf; | 3073 | str = buf; |
| 2989 | } | 3074 | } |
| 3075 | else if (VECTORP (val) || (CONSP (val))) | ||
| 3076 | { | ||
| 3077 | /* VAL is [TO_CHAR ...] or (([FROM-CHAR ...] . TO) ...) | ||
| 3078 | where TO is TO-CHAR or [TO-CHAR ...]. */ | ||
| 3079 | nc = -1; | ||
| 3080 | } | ||
| 2990 | } | 3081 | } |
| 2991 | 3082 | ||
| 2992 | if (nc != oc) | 3083 | if (nc != oc && nc >= 0) |
| 2993 | { | 3084 | { |
| 3085 | /* Simple one char to one char translation. */ | ||
| 2994 | if (len != str_len) | 3086 | if (len != str_len) |
| 2995 | { | 3087 | { |
| 2996 | Lisp_Object string; | 3088 | Lisp_Object string; |
| 2997 | 3089 | ||
| 2998 | /* This is less efficient, because it moves the gap, | 3090 | /* This is less efficient, because it moves the gap, |
| 2999 | but it should multibyte characters correctly. */ | 3091 | but it should handle multibyte characters correctly. */ |
| 3000 | string = make_multibyte_string (str, 1, str_len); | 3092 | string = make_multibyte_string (str, 1, str_len); |
| 3001 | replace_range (pos, pos + 1, string, 1, 0, 1); | 3093 | replace_range (pos, pos + 1, string, 1, 0, 1); |
| 3002 | len = str_len; | 3094 | len = str_len; |
| @@ -3011,6 +3103,46 @@ It returns the number of characters changed. */) | |||
| 3011 | } | 3103 | } |
| 3012 | ++cnt; | 3104 | ++cnt; |
| 3013 | } | 3105 | } |
| 3106 | else if (nc < 0) | ||
| 3107 | { | ||
| 3108 | Lisp_Object string; | ||
| 3109 | |||
| 3110 | if (CONSP (val)) | ||
| 3111 | { | ||
| 3112 | val = check_translation (pos, pos_byte, end_pos, val); | ||
| 3113 | if (NILP (val)) | ||
| 3114 | { | ||
| 3115 | pos_byte += len; | ||
| 3116 | pos++; | ||
| 3117 | continue; | ||
| 3118 | } | ||
| 3119 | /* VAL is ([FROM-CHAR ...] . TO). */ | ||
| 3120 | len = ASIZE (XCAR (val)); | ||
| 3121 | val = XCDR (val); | ||
| 3122 | } | ||
| 3123 | else | ||
| 3124 | len = 1; | ||
| 3125 | |||
| 3126 | if (VECTORP (val)) | ||
| 3127 | { | ||
| 3128 | int i; | ||
| 3129 | |||
| 3130 | string = Fmake_string (make_number (ASIZE (val)), | ||
| 3131 | AREF (val, 0)); | ||
| 3132 | for (i = 1; i < ASIZE (val); i++) | ||
| 3133 | Faset (string, make_number (i), AREF (val, i)); | ||
| 3134 | } | ||
| 3135 | else | ||
| 3136 | { | ||
| 3137 | string = Fmake_string (make_number (1), val); | ||
| 3138 | } | ||
| 3139 | replace_range (pos, pos + len, string, 1, 0, 1); | ||
| 3140 | pos_byte += SBYTES (string); | ||
| 3141 | pos += SCHARS (string); | ||
| 3142 | cnt += SCHARS (string); | ||
| 3143 | end_pos += SCHARS (string) - len; | ||
| 3144 | continue; | ||
| 3145 | } | ||
| 3014 | } | 3146 | } |
| 3015 | pos_byte += len; | 3147 | pos_byte += len; |
| 3016 | pos++; | 3148 | pos++; |
| @@ -3608,8 +3740,8 @@ usage: (format STRING &rest OBJECTS) */) | |||
| 3608 | thissize = 30 + (precision[n] > 0 ? precision[n] : 0); | 3740 | thissize = 30 + (precision[n] > 0 ? precision[n] : 0); |
| 3609 | if (*format == 'c') | 3741 | if (*format == 'c') |
| 3610 | { | 3742 | { |
| 3611 | if (! SINGLE_BYTE_CHAR_P (XINT (args[n])) | 3743 | if (! ASCII_CHAR_P (XINT (args[n])) |
| 3612 | /* Note: No one can remember why we have to treat | 3744 | /* Note: No one can remeber why we have to treat |
| 3613 | the character 0 as a multibyte character here. | 3745 | the character 0 as a multibyte character here. |
| 3614 | But, until it causes a real problem, let's | 3746 | But, until it causes a real problem, let's |
| 3615 | don't change it. */ | 3747 | don't change it. */ |
| @@ -4030,8 +4162,20 @@ Case is ignored if `case-fold-search' is non-nil in the current buffer. */) | |||
| 4030 | /* Do these in separate statements, | 4162 | /* Do these in separate statements, |
| 4031 | then compare the variables. | 4163 | then compare the variables. |
| 4032 | because of the way DOWNCASE uses temp variables. */ | 4164 | because of the way DOWNCASE uses temp variables. */ |
| 4033 | i1 = DOWNCASE (XFASTINT (c1)); | 4165 | i1 = XFASTINT (c1); |
| 4034 | i2 = DOWNCASE (XFASTINT (c2)); | 4166 | if (NILP (current_buffer->enable_multibyte_characters) |
| 4167 | && ! ASCII_CHAR_P (i1)) | ||
| 4168 | { | ||
| 4169 | MAKE_CHAR_MULTIBYTE (i1); | ||
| 4170 | } | ||
| 4171 | i2 = XFASTINT (c2); | ||
| 4172 | if (NILP (current_buffer->enable_multibyte_characters) | ||
| 4173 | && ! ASCII_CHAR_P (i2)) | ||
| 4174 | { | ||
| 4175 | MAKE_CHAR_MULTIBYTE (i2); | ||
| 4176 | } | ||
| 4177 | i1 = DOWNCASE (i1); | ||
| 4178 | i2 = DOWNCASE (i2); | ||
| 4035 | return (i1 == i2 ? Qt : Qnil); | 4179 | return (i1 == i2 ? Qt : Qnil); |
| 4036 | } | 4180 | } |
| 4037 | 4181 | ||
| @@ -4526,6 +4670,7 @@ functions if all the text being accessed has this property. */); | |||
| 4526 | defsubr (&Sinsert_and_inherit); | 4670 | defsubr (&Sinsert_and_inherit); |
| 4527 | defsubr (&Sinsert_and_inherit_before_markers); | 4671 | defsubr (&Sinsert_and_inherit_before_markers); |
| 4528 | defsubr (&Sinsert_char); | 4672 | defsubr (&Sinsert_char); |
| 4673 | defsubr (&Sinsert_byte); | ||
| 4529 | 4674 | ||
| 4530 | defsubr (&Suser_login_name); | 4675 | defsubr (&Suser_login_name); |
| 4531 | defsubr (&Suser_real_login_name); | 4676 | defsubr (&Suser_real_login_name); |