diff options
| author | Karl Heuer | 1997-02-20 06:48:37 +0000 |
|---|---|---|
| committer | Karl Heuer | 1997-02-20 06:48:37 +0000 |
| commit | fb8106e8dd74ecfe5e558d28c3393598d8805f1b (patch) | |
| tree | 69d525973c3dff2c1e65e942fcf87e542295810e | |
| parent | a0ca925c4b6ac97381007e30455f83678bb0a49c (diff) | |
| download | emacs-fb8106e8dd74ecfe5e558d28c3393598d8805f1b.tar.gz emacs-fb8106e8dd74ecfe5e558d28c3393598d8805f1b.zip | |
Include charset.h.
(Fchar_to_string, Fstring_to_char): Handle multibyte characters.
(Fsref): New function.
(Fgoto_char): Force point to be at a character boundary.
(Ffollowing_char, Fpreceding_char): Handle multibyte characters.
(Fchar_after): Handle multibyte characters.
(Fchar_before): New function.
(general_insert_function): New function.
(Finsert, Finsert_and_inherit, Finsert_before_markers): Use it.
(Finsert_char): Doc-string refer to markers of
before-insertion-type. Handle multibyte characters.
(Fsubst_char_in_region): Handle multibyte characters.
(Fchar_equal): Don't consider `case' of multibyte characters.
(syms_of_editfns): Handle the new function `char-before'.
| -rw-r--r-- | src/editfns.c | 364 |
1 files changed, 232 insertions, 132 deletions
diff --git a/src/editfns.c b/src/editfns.c index 5a2ca56ad5e..bcff8f007d3 100644 --- a/src/editfns.c +++ b/src/editfns.c | |||
| @@ -32,6 +32,7 @@ Boston, MA 02111-1307, USA. */ | |||
| 32 | #include "lisp.h" | 32 | #include "lisp.h" |
| 33 | #include "intervals.h" | 33 | #include "intervals.h" |
| 34 | #include "buffer.h" | 34 | #include "buffer.h" |
| 35 | #include "charset.h" | ||
| 35 | #include "window.h" | 36 | #include "window.h" |
| 36 | 37 | ||
| 37 | #include "systime.h" | 38 | #include "systime.h" |
| @@ -114,33 +115,61 @@ init_editfns () | |||
| 114 | } | 115 | } |
| 115 | 116 | ||
| 116 | DEFUN ("char-to-string", Fchar_to_string, Schar_to_string, 1, 1, 0, | 117 | DEFUN ("char-to-string", Fchar_to_string, Schar_to_string, 1, 1, 0, |
| 117 | "Convert arg CHARACTER to a one-character string containing that character.") | 118 | "Convert arg CHAR to a string containing multi-byte form of that character.") |
| 118 | (character) | 119 | (character) |
| 119 | Lisp_Object character; | 120 | Lisp_Object character; |
| 120 | { | 121 | { |
| 121 | char c; | 122 | int len; |
| 123 | char workbuf[4], *str; | ||
| 124 | |||
| 122 | CHECK_NUMBER (character, 0); | 125 | CHECK_NUMBER (character, 0); |
| 123 | 126 | ||
| 124 | c = XINT (character); | 127 | len = CHAR_STRING (XFASTINT (character), workbuf, str); |
| 125 | return make_string (&c, 1); | 128 | return make_string (str, len); |
| 126 | } | 129 | } |
| 127 | 130 | ||
| 128 | DEFUN ("string-to-char", Fstring_to_char, Sstring_to_char, 1, 1, 0, | 131 | DEFUN ("string-to-char", Fstring_to_char, Sstring_to_char, 1, 1, 0, |
| 129 | "Convert arg STRING to a character, the first character of that string.") | 132 | "Convert arg STRING to a character, the first character of that string.\n\ |
| 133 | A multibyte character is handled correctly.") | ||
| 130 | (string) | 134 | (string) |
| 131 | register Lisp_Object string; | 135 | register Lisp_Object string; |
| 132 | { | 136 | { |
| 133 | register Lisp_Object val; | 137 | register Lisp_Object val; |
| 134 | register struct Lisp_String *p; | 138 | register struct Lisp_String *p; |
| 135 | CHECK_STRING (string, 0); | 139 | CHECK_STRING (string, 0); |
| 136 | |||
| 137 | p = XSTRING (string); | 140 | p = XSTRING (string); |
| 138 | if (p->size) | 141 | if (p->size) |
| 139 | XSETFASTINT (val, ((unsigned char *) p->data)[0]); | 142 | XSETFASTINT (val, STRING_CHAR (p->data, p->size)); |
| 140 | else | 143 | else |
| 141 | XSETFASTINT (val, 0); | 144 | XSETFASTINT (val, 0); |
| 142 | return val; | 145 | return val; |
| 143 | } | 146 | } |
| 147 | |||
| 148 | DEFUN ("sref", Fsref, Ssref, 2, 2, 0, | ||
| 149 | "Return the character in STRING at INDEX. INDEX starts at 0.\n\ | ||
| 150 | A multibyte character is handled correctly.\n\ | ||
| 151 | INDEX not pointing at character boundary is an error.") | ||
| 152 | (str, idx) | ||
| 153 | Lisp_Object str, idx; | ||
| 154 | { | ||
| 155 | register int idxval, len; | ||
| 156 | register unsigned char *p; | ||
| 157 | register Lisp_Object val; | ||
| 158 | |||
| 159 | CHECK_STRING (str, 0); | ||
| 160 | CHECK_NUMBER (idx, 1); | ||
| 161 | idxval = XINT (idx); | ||
| 162 | if (idxval < 0 || idxval >= (len = XVECTOR (str)->size)) | ||
| 163 | args_out_of_range (str, idx); | ||
| 164 | p = XSTRING (str)->data + idxval; | ||
| 165 | if (!CHAR_HEAD_P (p)) | ||
| 166 | error ("Not character boundary"); | ||
| 167 | |||
| 168 | len = XSTRING (str)->size - idxval; | ||
| 169 | XSETFASTINT (val, STRING_CHAR (p, len)); | ||
| 170 | return val; | ||
| 171 | } | ||
| 172 | |||
| 144 | 173 | ||
| 145 | static Lisp_Object | 174 | static Lisp_Object |
| 146 | buildmark (val) | 175 | buildmark (val) |
| @@ -183,13 +212,41 @@ clip_to_bounds (lower, num, upper) | |||
| 183 | 212 | ||
| 184 | DEFUN ("goto-char", Fgoto_char, Sgoto_char, 1, 1, "NGoto char: ", | 213 | DEFUN ("goto-char", Fgoto_char, Sgoto_char, 1, 1, "NGoto char: ", |
| 185 | "Set point to POSITION, a number or marker.\n\ | 214 | "Set point to POSITION, a number or marker.\n\ |
| 186 | Beginning of buffer is position (point-min), end is (point-max).") | 215 | Beginning of buffer is position (point-min), end is (point-max).\n\ |
| 216 | If the position is in the middle of a multibyte form,\n\ | ||
| 217 | the actual point is set at the head of the multibyte form\n\ | ||
| 218 | except in the case that `enable-multibyte-characters' is nil.") | ||
| 187 | (position) | 219 | (position) |
| 188 | register Lisp_Object position; | 220 | register Lisp_Object position; |
| 189 | { | 221 | { |
| 222 | int pos; | ||
| 223 | unsigned char *p; | ||
| 224 | |||
| 190 | CHECK_NUMBER_COERCE_MARKER (position, 0); | 225 | CHECK_NUMBER_COERCE_MARKER (position, 0); |
| 191 | 226 | ||
| 192 | SET_PT (clip_to_bounds (BEGV, XINT (position), ZV)); | 227 | pos = clip_to_bounds (BEGV, XINT (position), ZV); |
| 228 | /* If POS is in a middle of multi-byte form (i.e. *P >= 0xA0), we | ||
| 229 | must decrement POS until it points the head of the multi-byte | ||
| 230 | form. */ | ||
| 231 | if (!NILP (current_buffer->enable_multibyte_characters) | ||
| 232 | && *(p = POS_ADDR (pos)) >= 0xA0 | ||
| 233 | && pos > BEGV) | ||
| 234 | { | ||
| 235 | /* Since a multi-byte form does not contain the gap, POS should | ||
| 236 | not stride over the gap while it is being decreased. So, we | ||
| 237 | set the limit as below. */ | ||
| 238 | unsigned char *p_min = pos < GPT ? BEG_ADDR : GAP_END_ADDR; | ||
| 239 | unsigned int saved_pos = pos; | ||
| 240 | |||
| 241 | do { | ||
| 242 | p--, pos--; | ||
| 243 | } while (p > p_min && *p >= 0xA0); | ||
| 244 | if (*p < 0x80) | ||
| 245 | /* This was an invalid multi-byte form. */ | ||
| 246 | pos = saved_pos; | ||
| 247 | XSETFASTINT (position, pos); | ||
| 248 | } | ||
| 249 | SET_PT (pos); | ||
| 193 | return position; | 250 | return position; |
| 194 | } | 251 | } |
| 195 | 252 | ||
| @@ -426,7 +483,10 @@ is in effect, in which case it is less.") | |||
| 426 | 483 | ||
| 427 | DEFUN ("following-char", Ffollowing_char, Sfollowing_char, 0, 0, 0, | 484 | DEFUN ("following-char", Ffollowing_char, Sfollowing_char, 0, 0, 0, |
| 428 | "Return the character following point, as a number.\n\ | 485 | "Return the character following point, as a number.\n\ |
| 429 | At the end of the buffer or accessible region, return 0.") | 486 | At the end of the buffer or accessible region, return 0.\n\ |
| 487 | If `enable-multibyte-characters' is nil or point is not\n\ | ||
| 488 | at character boundary, multibyte form is ignored,\n\ | ||
| 489 | and only one byte following point is returned as a character.") | ||
| 430 | () | 490 | () |
| 431 | { | 491 | { |
| 432 | Lisp_Object temp; | 492 | Lisp_Object temp; |
| @@ -439,14 +499,23 @@ At the end of the buffer or accessible region, return 0.") | |||
| 439 | 499 | ||
| 440 | DEFUN ("preceding-char", Fprevious_char, Sprevious_char, 0, 0, 0, | 500 | DEFUN ("preceding-char", Fprevious_char, Sprevious_char, 0, 0, 0, |
| 441 | "Return the character preceding point, as a number.\n\ | 501 | "Return the character preceding point, as a number.\n\ |
| 442 | At the beginning of the buffer or accessible region, return 0.") | 502 | At the beginning of the buffer or accessible region, return 0.\n\ |
| 503 | If `enable-multibyte-characters' is nil or point is not\n\ | ||
| 504 | at character boundary, multi-byte form is ignored,\n\ | ||
| 505 | and only one byte preceding point is returned as a character.") | ||
| 443 | () | 506 | () |
| 444 | { | 507 | { |
| 445 | Lisp_Object temp; | 508 | Lisp_Object temp; |
| 446 | if (PT <= BEGV) | 509 | if (PT <= BEGV) |
| 447 | XSETFASTINT (temp, 0); | 510 | XSETFASTINT (temp, 0); |
| 511 | else if (!NILP (current_buffer->enable_multibyte_characters)) | ||
| 512 | { | ||
| 513 | int pos = PT; | ||
| 514 | DEC_POS (pos); | ||
| 515 | XSETFASTINT (temp, FETCH_CHAR (pos)); | ||
| 516 | } | ||
| 448 | else | 517 | else |
| 449 | XSETFASTINT (temp, FETCH_CHAR (PT - 1)); | 518 | XSETFASTINT (temp, FETCH_BYTE (point - 1)); |
| 450 | return temp; | 519 | return temp; |
| 451 | } | 520 | } |
| 452 | 521 | ||
| @@ -474,7 +543,7 @@ DEFUN ("bolp", Fbolp, Sbolp, 0, 0, 0, | |||
| 474 | "Return T if point is at the beginning of a line.") | 543 | "Return T if point is at the beginning of a line.") |
| 475 | () | 544 | () |
| 476 | { | 545 | { |
| 477 | if (PT == BEGV || FETCH_CHAR (PT - 1) == '\n') | 546 | if (PT == BEGV || FETCH_BYTE (PT - 1) == '\n') |
| 478 | return Qt; | 547 | return Qt; |
| 479 | return Qnil; | 548 | return Qnil; |
| 480 | } | 549 | } |
| @@ -484,7 +553,7 @@ DEFUN ("eolp", Feolp, Seolp, 0, 0, 0, | |||
| 484 | `End of a line' includes point being at the end of the buffer.") | 553 | `End of a line' includes point being at the end of the buffer.") |
| 485 | () | 554 | () |
| 486 | { | 555 | { |
| 487 | if (PT == ZV || FETCH_CHAR (PT) == '\n') | 556 | if (PT == ZV || FETCH_BYTE (PT) == '\n') |
| 488 | return Qt; | 557 | return Qt; |
| 489 | return Qnil; | 558 | return Qnil; |
| 490 | } | 559 | } |
| @@ -492,7 +561,10 @@ DEFUN ("eolp", Feolp, Seolp, 0, 0, 0, | |||
| 492 | DEFUN ("char-after", Fchar_after, Schar_after, 1, 1, 0, | 561 | DEFUN ("char-after", Fchar_after, Schar_after, 1, 1, 0, |
| 493 | "Return character in current buffer at position POS.\n\ | 562 | "Return character in current buffer at position POS.\n\ |
| 494 | POS is an integer or a buffer pointer.\n\ | 563 | POS is an integer or a buffer pointer.\n\ |
| 495 | If POS is out of range, the value is nil.") | 564 | If POS is out of range, the value is nil.\n\ |
| 565 | If `enable-multibyte-characters' is nil or POS is not at character boundary,\n\ | ||
| 566 | multi-byte form is ignored, and only one byte at POS\n\ | ||
| 567 | is returned as a character.") | ||
| 496 | (pos) | 568 | (pos) |
| 497 | Lisp_Object pos; | 569 | Lisp_Object pos; |
| 498 | { | 570 | { |
| @@ -507,6 +579,37 @@ If POS is out of range, the value is nil.") | |||
| 507 | XSETFASTINT (val, FETCH_CHAR (n)); | 579 | XSETFASTINT (val, FETCH_CHAR (n)); |
| 508 | return val; | 580 | return val; |
| 509 | } | 581 | } |
| 582 | |||
| 583 | DEFUN ("char-before", Fchar_before, Schar_before, 1, 1, 0, | ||
| 584 | "Return character in current buffer preceding position POS.\n\ | ||
| 585 | POS is an integer or a buffer pointer.\n\ | ||
| 586 | If POS is out of range, the value is nil.\n\ | ||
| 587 | If `enable-multibyte-characters' is nil or POS is not at character boundary,\n\ | ||
| 588 | multi-byte form is ignored, and only one byte preceding POS\n\ | ||
| 589 | is returned as a character.") | ||
| 590 | (pos) | ||
| 591 | Lisp_Object pos; | ||
| 592 | { | ||
| 593 | register Lisp_Object val; | ||
| 594 | register int n; | ||
| 595 | |||
| 596 | CHECK_NUMBER_COERCE_MARKER (pos, 0); | ||
| 597 | |||
| 598 | n = XINT (pos); | ||
| 599 | if (n <= BEGV || n > ZV) return Qnil; | ||
| 600 | |||
| 601 | if (!NILP (current_buffer->enable_multibyte_characters)) | ||
| 602 | { | ||
| 603 | DEC_POS (pos); | ||
| 604 | XSETFASTINT (val, FETCH_CHAR (pos)); | ||
| 605 | } | ||
| 606 | else | ||
| 607 | { | ||
| 608 | pos--; | ||
| 609 | XSETFASTINT (val, FETCH_BYTE (pos)); | ||
| 610 | } | ||
| 611 | return val; | ||
| 612 | } | ||
| 510 | 613 | ||
| 511 | DEFUN ("user-login-name", Fuser_login_name, Suser_login_name, 0, 1, 0, | 614 | DEFUN ("user-login-name", Fuser_login_name, Suser_login_name, 0, 1, 0, |
| 512 | "Return the name under which the user logged in, as a string.\n\ | 615 | "Return the name under which the user logged in, as a string.\n\ |
| @@ -1114,6 +1217,47 @@ set_time_zone_rule (tzstring) | |||
| 1114 | #endif | 1217 | #endif |
| 1115 | } | 1218 | } |
| 1116 | 1219 | ||
| 1220 | /* Insert NARGS Lisp objects in the array ARGS by calling INSERT_FUNC | ||
| 1221 | (if a type of object is Lisp_Int) or INSERT_FROM_STRING_FUNC (if a | ||
| 1222 | type of object is Lisp_String). INHERIT is passed to | ||
| 1223 | INSERT_FROM_STRING_FUNC as the last argument. */ | ||
| 1224 | |||
| 1225 | general_insert_function (insert_func, insert_from_string_func, | ||
| 1226 | inherit, nargs, args) | ||
| 1227 | int (*insert_func)(), (*insert_from_string_func)(); | ||
| 1228 | int inherit, nargs; | ||
| 1229 | register Lisp_Object *args; | ||
| 1230 | { | ||
| 1231 | register int argnum; | ||
| 1232 | register Lisp_Object val; | ||
| 1233 | |||
| 1234 | for (argnum = 0; argnum < nargs; argnum++) | ||
| 1235 | { | ||
| 1236 | val = args[argnum]; | ||
| 1237 | retry: | ||
| 1238 | if (INTEGERP (val)) | ||
| 1239 | { | ||
| 1240 | char workbuf[4], *str; | ||
| 1241 | int len; | ||
| 1242 | |||
| 1243 | if (!NILP (current_buffer->enable_multibyte_characters)) | ||
| 1244 | len = CHAR_STRING (XFASTINT (val), workbuf, str); | ||
| 1245 | else | ||
| 1246 | workbuf[0] = XINT (val), str = workbuf, len = 1; | ||
| 1247 | (*insert_func) (str, len); | ||
| 1248 | } | ||
| 1249 | else if (STRINGP (val)) | ||
| 1250 | { | ||
| 1251 | (*insert_from_string_func) (val, 0, XSTRING (val)->size, inherit); | ||
| 1252 | } | ||
| 1253 | else | ||
| 1254 | { | ||
| 1255 | val = wrong_type_argument (Qchar_or_string_p, val); | ||
| 1256 | goto retry; | ||
| 1257 | } | ||
| 1258 | } | ||
| 1259 | } | ||
| 1260 | |||
| 1117 | void | 1261 | void |
| 1118 | insert1 (arg) | 1262 | insert1 (arg) |
| 1119 | Lisp_Object arg; | 1263 | Lisp_Object arg; |
| @@ -1129,107 +1273,44 @@ insert1 (arg) | |||
| 1129 | 1273 | ||
| 1130 | DEFUN ("insert", Finsert, Sinsert, 0, MANY, 0, | 1274 | DEFUN ("insert", Finsert, Sinsert, 0, MANY, 0, |
| 1131 | "Insert the arguments, either strings or characters, at point.\n\ | 1275 | "Insert the arguments, either strings or characters, at point.\n\ |
| 1132 | Point moves forward so that it ends up after the inserted text.\n\ | 1276 | Point and before-insertion-markers move forward so that it ends up\n\ |
| 1277 | after the inserted text.\n\ | ||
| 1133 | Any other markers at the point of insertion remain before the text.") | 1278 | Any other markers at the point of insertion remain before the text.") |
| 1134 | (nargs, args) | 1279 | (nargs, args) |
| 1135 | int nargs; | 1280 | int nargs; |
| 1136 | register Lisp_Object *args; | 1281 | register Lisp_Object *args; |
| 1137 | { | 1282 | { |
| 1138 | register int argnum; | 1283 | general_insert_function (insert, insert_from_string, 0, nargs, args); |
| 1139 | register Lisp_Object tem; | ||
| 1140 | char str[1]; | ||
| 1141 | |||
| 1142 | for (argnum = 0; argnum < nargs; argnum++) | ||
| 1143 | { | ||
| 1144 | tem = args[argnum]; | ||
| 1145 | retry: | ||
| 1146 | if (INTEGERP (tem)) | ||
| 1147 | { | ||
| 1148 | str[0] = XINT (tem); | ||
| 1149 | insert (str, 1); | ||
| 1150 | } | ||
| 1151 | else if (STRINGP (tem)) | ||
| 1152 | { | ||
| 1153 | insert_from_string (tem, 0, XSTRING (tem)->size, 0); | ||
| 1154 | } | ||
| 1155 | else | ||
| 1156 | { | ||
| 1157 | tem = wrong_type_argument (Qchar_or_string_p, tem); | ||
| 1158 | goto retry; | ||
| 1159 | } | ||
| 1160 | } | ||
| 1161 | |||
| 1162 | return Qnil; | 1284 | return Qnil; |
| 1163 | } | 1285 | } |
| 1164 | 1286 | ||
| 1165 | DEFUN ("insert-and-inherit", Finsert_and_inherit, Sinsert_and_inherit, | 1287 | DEFUN ("insert-and-inherit", Finsert_and_inherit, Sinsert_and_inherit, |
| 1166 | 0, MANY, 0, | 1288 | 0, MANY, 0, |
| 1167 | "Insert the arguments at point, inheriting properties from adjoining text.\n\ | 1289 | "Insert the arguments at point, inheriting properties from adjoining text.\n\ |
| 1168 | Point moves forward so that it ends up after the inserted text.\n\ | 1290 | Point and before-insertion-markers move forward so that it ends up\n\ |
| 1291 | after the inserted text.\n\ | ||
| 1169 | Any other markers at the point of insertion remain before the text.") | 1292 | Any other markers at the point of insertion remain before the text.") |
| 1170 | (nargs, args) | 1293 | (nargs, args) |
| 1171 | int nargs; | 1294 | int nargs; |
| 1172 | register Lisp_Object *args; | 1295 | register Lisp_Object *args; |
| 1173 | { | 1296 | { |
| 1174 | register int argnum; | 1297 | general_insert_function (insert_and_inherit, insert_from_string, 1, |
| 1175 | register Lisp_Object tem; | 1298 | nargs, args); |
| 1176 | char str[1]; | ||
| 1177 | |||
| 1178 | for (argnum = 0; argnum < nargs; argnum++) | ||
| 1179 | { | ||
| 1180 | tem = args[argnum]; | ||
| 1181 | retry: | ||
| 1182 | if (INTEGERP (tem)) | ||
| 1183 | { | ||
| 1184 | str[0] = XINT (tem); | ||
| 1185 | insert_and_inherit (str, 1); | ||
| 1186 | } | ||
| 1187 | else if (STRINGP (tem)) | ||
| 1188 | { | ||
| 1189 | insert_from_string (tem, 0, XSTRING (tem)->size, 1); | ||
| 1190 | } | ||
| 1191 | else | ||
| 1192 | { | ||
| 1193 | tem = wrong_type_argument (Qchar_or_string_p, tem); | ||
| 1194 | goto retry; | ||
| 1195 | } | ||
| 1196 | } | ||
| 1197 | |||
| 1198 | return Qnil; | 1299 | return Qnil; |
| 1199 | } | 1300 | } |
| 1200 | 1301 | ||
| 1201 | DEFUN ("insert-before-markers", Finsert_before_markers, Sinsert_before_markers, 0, MANY, 0, | 1302 | DEFUN ("insert-before-markers", Finsert_before_markers, Sinsert_before_markers, 0, MANY, 0, |
| 1202 | "Insert strings or characters at point, relocating markers after the text.\n\ | 1303 | "Insert strings or characters at point, relocating markers after the text.\n\ |
| 1203 | Point moves forward so that it ends up after the inserted text.\n\ | 1304 | Point and before-insertion-markers move forward so that it ends up\n\ |
| 1305 | after the inserted text.\n\ | ||
| 1204 | Any other markers at the point of insertion also end up after the text.") | 1306 | Any other markers at the point of insertion also end up after the text.") |
| 1205 | (nargs, args) | 1307 | (nargs, args) |
| 1206 | int nargs; | 1308 | int nargs; |
| 1207 | register Lisp_Object *args; | 1309 | register Lisp_Object *args; |
| 1208 | { | 1310 | { |
| 1209 | register int argnum; | 1311 | general_insert_function (insert_before_markers, |
| 1210 | register Lisp_Object tem; | 1312 | insert_from_string_before_markers, 0, |
| 1211 | char str[1]; | 1313 | nargs, args); |
| 1212 | |||
| 1213 | for (argnum = 0; argnum < nargs; argnum++) | ||
| 1214 | { | ||
| 1215 | tem = args[argnum]; | ||
| 1216 | retry: | ||
| 1217 | if (INTEGERP (tem)) | ||
| 1218 | { | ||
| 1219 | str[0] = XINT (tem); | ||
| 1220 | insert_before_markers (str, 1); | ||
| 1221 | } | ||
| 1222 | else if (STRINGP (tem)) | ||
| 1223 | { | ||
| 1224 | insert_from_string_before_markers (tem, 0, XSTRING (tem)->size, 0); | ||
| 1225 | } | ||
| 1226 | else | ||
| 1227 | { | ||
| 1228 | tem = wrong_type_argument (Qchar_or_string_p, tem); | ||
| 1229 | goto retry; | ||
| 1230 | } | ||
| 1231 | } | ||
| 1232 | |||
| 1233 | return Qnil; | 1314 | return Qnil; |
| 1234 | } | 1315 | } |
| 1235 | 1316 | ||
| @@ -1242,36 +1323,15 @@ Any other markers at the point of insertion also end up after the text.") | |||
| 1242 | int nargs; | 1323 | int nargs; |
| 1243 | register Lisp_Object *args; | 1324 | register Lisp_Object *args; |
| 1244 | { | 1325 | { |
| 1245 | register int argnum; | 1326 | general_insert_function (insert_before_markers_and_inherit, |
| 1246 | register Lisp_Object tem; | 1327 | insert_from_string_before_markers, 1, |
| 1247 | char str[1]; | 1328 | nargs, args); |
| 1248 | |||
| 1249 | for (argnum = 0; argnum < nargs; argnum++) | ||
| 1250 | { | ||
| 1251 | tem = args[argnum]; | ||
| 1252 | retry: | ||
| 1253 | if (INTEGERP (tem)) | ||
| 1254 | { | ||
| 1255 | str[0] = XINT (tem); | ||
| 1256 | insert_before_markers_and_inherit (str, 1); | ||
| 1257 | } | ||
| 1258 | else if (STRINGP (tem)) | ||
| 1259 | { | ||
| 1260 | insert_from_string_before_markers (tem, 0, XSTRING (tem)->size, 1); | ||
| 1261 | } | ||
| 1262 | else | ||
| 1263 | { | ||
| 1264 | tem = wrong_type_argument (Qchar_or_string_p, tem); | ||
| 1265 | goto retry; | ||
| 1266 | } | ||
| 1267 | } | ||
| 1268 | |||
| 1269 | return Qnil; | 1329 | return Qnil; |
| 1270 | } | 1330 | } |
| 1271 | 1331 | ||
| 1272 | DEFUN ("insert-char", Finsert_char, Sinsert_char, 2, 3, 0, | 1332 | DEFUN ("insert-char", Finsert_char, Sinsert_char, 2, 3, 0, |
| 1273 | "Insert COUNT (second arg) copies of CHARACTER (first arg).\n\ | 1333 | "Insert COUNT (second arg) copies of CHARACTER (first arg).\n\ |
| 1274 | Point and all markers are affected as in the function `insert'.\n\ | 1334 | Point and before-insertion-markers are affected as in the function `insert'.\n\ |
| 1275 | Both arguments are required.\n\ | 1335 | Both arguments are required.\n\ |
| 1276 | The optional third arg INHERIT, if non-nil, says to inherit text properties\n\ | 1336 | The optional third arg INHERIT, if non-nil, says to inherit text properties\n\ |
| 1277 | from adjoining text, if those properties are sticky.") | 1337 | from adjoining text, if those properties are sticky.") |
| @@ -1281,17 +1341,23 @@ from adjoining text, if those properties are sticky.") | |||
| 1281 | register unsigned char *string; | 1341 | register unsigned char *string; |
| 1282 | register int strlen; | 1342 | register int strlen; |
| 1283 | register int i, n; | 1343 | register int i, n; |
| 1344 | int len; | ||
| 1345 | unsigned char workbuf[4], *str; | ||
| 1284 | 1346 | ||
| 1285 | CHECK_NUMBER (character, 0); | 1347 | CHECK_NUMBER (character, 0); |
| 1286 | CHECK_NUMBER (count, 1); | 1348 | CHECK_NUMBER (count, 1); |
| 1287 | 1349 | ||
| 1288 | n = XINT (count); | 1350 | if (!NILP (current_buffer->enable_multibyte_characters)) |
| 1351 | len = CHAR_STRING (XFASTINT (character), workbuf, str); | ||
| 1352 | else | ||
| 1353 | workbuf[0] = XFASTINT (character), str = workbuf, len = 1; | ||
| 1354 | n = XINT (count) * len; | ||
| 1289 | if (n <= 0) | 1355 | if (n <= 0) |
| 1290 | return Qnil; | 1356 | return Qnil; |
| 1291 | strlen = min (n, 256); | 1357 | strlen = min (n, 256 * len); |
| 1292 | string = (unsigned char *) alloca (strlen); | 1358 | string = (unsigned char *) alloca (strlen); |
| 1293 | for (i = 0; i < strlen; i++) | 1359 | for (i = 0; i < strlen; i++) |
| 1294 | string[i] = XFASTINT (character); | 1360 | string[i] = str[i % len]; |
| 1295 | while (n >= strlen) | 1361 | while (n >= strlen) |
| 1296 | { | 1362 | { |
| 1297 | if (!NILP (inherit)) | 1363 | if (!NILP (inherit)) |
| @@ -1337,7 +1403,7 @@ make_buffer_string (start, end, props) | |||
| 1337 | move_gap (start); | 1403 | move_gap (start); |
| 1338 | 1404 | ||
| 1339 | result = make_uninit_string (end - start); | 1405 | result = make_uninit_string (end - start); |
| 1340 | bcopy (&FETCH_CHAR (start), XSTRING (result)->data, end - start); | 1406 | bcopy (POS_ADDR (start), XSTRING (result)->data, end - start); |
| 1341 | 1407 | ||
| 1342 | /* If desired, update and copy the text properties. */ | 1408 | /* If desired, update and copy the text properties. */ |
| 1343 | #ifdef USE_TEXT_PROPERTIES | 1409 | #ifdef USE_TEXT_PROPERTIES |
| @@ -1627,21 +1693,35 @@ DEFUN ("subst-char-in-region", Fsubst_char_in_region, | |||
| 1627 | Ssubst_char_in_region, 4, 5, 0, | 1693 | Ssubst_char_in_region, 4, 5, 0, |
| 1628 | "From START to END, replace FROMCHAR with TOCHAR each time it occurs.\n\ | 1694 | "From START to END, replace FROMCHAR with TOCHAR each time it occurs.\n\ |
| 1629 | If optional arg NOUNDO is non-nil, don't record this change for undo\n\ | 1695 | If optional arg NOUNDO is non-nil, don't record this change for undo\n\ |
| 1630 | and don't mark the buffer as really changed.") | 1696 | and don't mark the buffer as really changed.\n\ |
| 1697 | Both characters must have the same length of multi-byte form.") | ||
| 1631 | (start, end, fromchar, tochar, noundo) | 1698 | (start, end, fromchar, tochar, noundo) |
| 1632 | Lisp_Object start, end, fromchar, tochar, noundo; | 1699 | Lisp_Object start, end, fromchar, tochar, noundo; |
| 1633 | { | 1700 | { |
| 1634 | register int pos, stop, look; | 1701 | register int pos, stop, i, len; |
| 1635 | int changed = 0; | 1702 | int changed = 0; |
| 1703 | unsigned char fromwork[4], *fromstr, towork[4], *tostr, *p; | ||
| 1636 | int count = specpdl_ptr - specpdl; | 1704 | int count = specpdl_ptr - specpdl; |
| 1637 | 1705 | ||
| 1638 | validate_region (&start, &end); | 1706 | validate_region (&start, &end); |
| 1639 | CHECK_NUMBER (fromchar, 2); | 1707 | CHECK_NUMBER (fromchar, 2); |
| 1640 | CHECK_NUMBER (tochar, 3); | 1708 | CHECK_NUMBER (tochar, 3); |
| 1641 | 1709 | ||
| 1710 | if (! NILP (current_buffer->enable_multibyte_characters)) | ||
| 1711 | { | ||
| 1712 | len = CHAR_STRING (XFASTINT (fromchar), fromwork, fromstr); | ||
| 1713 | if (CHAR_STRING (XFASTINT (tochar), towork, tostr) != len) | ||
| 1714 | error ("Characters in subst-char-in-region have different byte-lengths"); | ||
| 1715 | } | ||
| 1716 | else | ||
| 1717 | { | ||
| 1718 | len = 1; | ||
| 1719 | fromwork[0] = XFASTINT (fromchar), fromstr = fromwork; | ||
| 1720 | towork[0] = XFASTINT (tochar), tostr = towork; | ||
| 1721 | } | ||
| 1722 | |||
| 1642 | pos = XINT (start); | 1723 | pos = XINT (start); |
| 1643 | stop = XINT (end); | 1724 | stop = XINT (end); |
| 1644 | look = XINT (fromchar); | ||
| 1645 | 1725 | ||
| 1646 | /* If we don't want undo, turn off putting stuff on the list. | 1726 | /* If we don't want undo, turn off putting stuff on the list. |
| 1647 | That's faster than getting rid of things, | 1727 | That's faster than getting rid of things, |
| @@ -1658,13 +1738,26 @@ and don't mark the buffer as really changed.") | |||
| 1658 | current_buffer->filename = Qnil; | 1738 | current_buffer->filename = Qnil; |
| 1659 | } | 1739 | } |
| 1660 | 1740 | ||
| 1661 | while (pos < stop) | 1741 | if (pos < GPT) |
| 1742 | stop = min(stop, GPT); | ||
| 1743 | p = POS_ADDR (pos); | ||
| 1744 | while (1) | ||
| 1662 | { | 1745 | { |
| 1663 | if (FETCH_CHAR (pos) == look) | 1746 | if (pos >= stop) |
| 1747 | { | ||
| 1748 | if (pos >= XINT (end)) break; | ||
| 1749 | stop = XINT (end); | ||
| 1750 | p = POS_ADDR (pos); | ||
| 1751 | } | ||
| 1752 | if (p[0] == fromstr[0] | ||
| 1753 | && (len == 1 | ||
| 1754 | || (p[1] == fromstr[1] | ||
| 1755 | && (len == 2 || (p[2] == fromstr[2] | ||
| 1756 | && (len == 3 || p[3] == fromstr[3])))))) | ||
| 1664 | { | 1757 | { |
| 1665 | if (! changed) | 1758 | if (! changed) |
| 1666 | { | 1759 | { |
| 1667 | modify_region (current_buffer, XINT (start), stop); | 1760 | modify_region (current_buffer, XINT (start), XINT (end)); |
| 1668 | 1761 | ||
| 1669 | if (! NILP (noundo)) | 1762 | if (! NILP (noundo)) |
| 1670 | { | 1763 | { |
| @@ -1674,14 +1767,16 @@ and don't mark the buffer as really changed.") | |||
| 1674 | current_buffer->auto_save_modified++; | 1767 | current_buffer->auto_save_modified++; |
| 1675 | } | 1768 | } |
| 1676 | 1769 | ||
| 1677 | changed = 1; | 1770 | changed = 1; |
| 1678 | } | 1771 | } |
| 1679 | 1772 | ||
| 1680 | if (NILP (noundo)) | 1773 | if (NILP (noundo)) |
| 1681 | record_change (pos, 1); | 1774 | record_change (pos, len); |
| 1682 | FETCH_CHAR (pos) = XINT (tochar); | 1775 | for (i = 0; i < len; i++) *p++ = tostr[i]; |
| 1776 | pos += len; | ||
| 1683 | } | 1777 | } |
| 1684 | pos++; | 1778 | else |
| 1779 | pos++, p++; | ||
| 1685 | } | 1780 | } |
| 1686 | 1781 | ||
| 1687 | if (changed) | 1782 | if (changed) |
| @@ -1722,14 +1817,14 @@ for the character with code N. Returns the number of characters changed.") | |||
| 1722 | cnt = 0; | 1817 | cnt = 0; |
| 1723 | for (; pos < stop; ++pos) | 1818 | for (; pos < stop; ++pos) |
| 1724 | { | 1819 | { |
| 1725 | oc = FETCH_CHAR (pos); | 1820 | oc = FETCH_BYTE (pos); |
| 1726 | if (oc < size) | 1821 | if (oc < size) |
| 1727 | { | 1822 | { |
| 1728 | nc = tt[oc]; | 1823 | nc = tt[oc]; |
| 1729 | if (nc != oc) | 1824 | if (nc != oc) |
| 1730 | { | 1825 | { |
| 1731 | record_change (pos, 1); | 1826 | record_change (pos, 1); |
| 1732 | FETCH_CHAR (pos) = nc; | 1827 | *(POS_ADDR (pos)) = nc; |
| 1733 | signal_after_change (pos, 1, 1); | 1828 | signal_after_change (pos, 1, 1); |
| 1734 | ++cnt; | 1829 | ++cnt; |
| 1735 | } | 1830 | } |
| @@ -2200,7 +2295,10 @@ Case is ignored if `case-fold-search' is non-nil in the current buffer.") | |||
| 2200 | CHECK_NUMBER (c1, 0); | 2295 | CHECK_NUMBER (c1, 0); |
| 2201 | CHECK_NUMBER (c2, 1); | 2296 | CHECK_NUMBER (c2, 1); |
| 2202 | 2297 | ||
| 2203 | if (!NILP (current_buffer->case_fold_search) | 2298 | if ((!NILP (current_buffer->case_fold_search) |
| 2299 | && SINGLE_BYTE_CHAR_P (c1) /* For the moment, downcase table is */ | ||
| 2300 | && SINGLE_BYTE_CHAR_P (c2) /* implemented only for ASCII characters. */ | ||
| 2301 | ) | ||
| 2204 | ? ((XINT (downcase[0xff & XFASTINT (c1)]) | 2302 | ? ((XINT (downcase[0xff & XFASTINT (c1)]) |
| 2205 | == XINT (downcase[0xff & XFASTINT (c2)])) | 2303 | == XINT (downcase[0xff & XFASTINT (c2)])) |
| 2206 | && (XFASTINT (c1) & ~0xff) == (XFASTINT (c2) & ~0xff)) | 2304 | && (XFASTINT (c1) & ~0xff) == (XFASTINT (c2) & ~0xff)) |
| @@ -2591,6 +2689,7 @@ functions if all the text being accessed has this property."); | |||
| 2591 | defsubr (&Sgoto_char); | 2689 | defsubr (&Sgoto_char); |
| 2592 | defsubr (&Sstring_to_char); | 2690 | defsubr (&Sstring_to_char); |
| 2593 | defsubr (&Schar_to_string); | 2691 | defsubr (&Schar_to_string); |
| 2692 | defsubr (&Ssref); | ||
| 2594 | defsubr (&Sbuffer_substring); | 2693 | defsubr (&Sbuffer_substring); |
| 2595 | defsubr (&Sbuffer_substring_no_properties); | 2694 | defsubr (&Sbuffer_substring_no_properties); |
| 2596 | defsubr (&Sbuffer_string); | 2695 | defsubr (&Sbuffer_string); |
| @@ -2621,6 +2720,7 @@ functions if all the text being accessed has this property."); | |||
| 2621 | defsubr (&Sfollowing_char); | 2720 | defsubr (&Sfollowing_char); |
| 2622 | defsubr (&Sprevious_char); | 2721 | defsubr (&Sprevious_char); |
| 2623 | defsubr (&Schar_after); | 2722 | defsubr (&Schar_after); |
| 2723 | defsubr (&Schar_before); | ||
| 2624 | defsubr (&Sinsert); | 2724 | defsubr (&Sinsert); |
| 2625 | defsubr (&Sinsert_before_markers); | 2725 | defsubr (&Sinsert_before_markers); |
| 2626 | defsubr (&Sinsert_and_inherit); | 2726 | defsubr (&Sinsert_and_inherit); |