Mercurial > emacs
comparison src/editfns.c @ 17031:c612a2cdd83b
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'.
author | Karl Heuer <kwzh@gnu.org> |
---|---|
date | Thu, 20 Feb 1997 06:48:37 +0000 |
parents | ab49512bcdff |
children | dd39f3c57b3e |
comparison
equal
deleted
inserted
replaced
17030:42d758739319 | 17031:c612a2cdd83b |
---|---|
30 #endif | 30 #endif |
31 | 31 |
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" |
38 | 39 |
39 #define min(a, b) ((a) < (b) ? (a) : (b)) | 40 #define min(a, b) ((a) < (b) ? (a) : (b)) |
112 else if (NILP (Vuser_full_name)) | 113 else if (NILP (Vuser_full_name)) |
113 Vuser_full_name = build_string ("unknown"); | 114 Vuser_full_name = build_string ("unknown"); |
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) |
147 int val; | 176 int val; |
148 { | 177 { |
181 return num; | 210 return num; |
182 } | 211 } |
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 |
196 static Lisp_Object | 253 static Lisp_Object |
197 region_limit (beginningp) | 254 region_limit (beginningp) |
424 return buildmark (ZV); | 481 return buildmark (ZV); |
425 } | 482 } |
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; |
433 if (PT >= ZV) | 493 if (PT >= ZV) |
434 XSETFASTINT (temp, 0); | 494 XSETFASTINT (temp, 0); |
437 return temp; | 497 return temp; |
438 } | 498 } |
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 |
453 DEFUN ("bobp", Fbobp, Sbobp, 0, 0, 0, | 522 DEFUN ("bobp", Fbobp, Sbobp, 0, 0, 0, |
454 "Return T if point is at the beginning of the buffer.\n\ | 523 "Return T if point is at the beginning of the buffer.\n\ |
472 | 541 |
473 DEFUN ("bolp", Fbolp, Sbolp, 0, 0, 0, | 542 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 } |
481 | 550 |
482 DEFUN ("eolp", Feolp, Seolp, 0, 0, 0, | 551 DEFUN ("eolp", Feolp, Seolp, 0, 0, 0, |
483 "Return T if point is at the end of a line.\n\ | 552 "Return T if point is at the end of a line.\n\ |
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 } |
491 | 560 |
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 { |
499 register Lisp_Object val; | 571 register Lisp_Object val; |
500 register int n; | 572 register int n; |
504 n = XINT (pos); | 576 n = XINT (pos); |
505 if (n < BEGV || n >= ZV) return Qnil; | 577 if (n < BEGV || n >= ZV) return Qnil; |
506 | 578 |
507 XSETFASTINT (val, FETCH_CHAR (n)); | 579 XSETFASTINT (val, FETCH_CHAR (n)); |
508 return val; | 580 return val; |
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; | |
509 } | 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\ |
513 This is based on the effective uid, not the real uid.\n\ | 616 This is based on the effective uid, not the real uid.\n\ |
1112 | 1215 |
1113 tzset (); | 1216 tzset (); |
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; |
1120 { | 1264 { |
1121 Finsert (1, &arg); | 1265 Finsert (1, &arg); |
1127 not be used after calling insert or insert_from_string, so | 1271 not be used after calling insert or insert_from_string, so |
1128 we don't care if it gets trashed. */ | 1272 we don't care if it gets trashed. */ |
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 |
1236 DEFUN ("insert-before-markers-and-inherit", Finsert_and_inherit_before_markers, | 1317 DEFUN ("insert-before-markers-and-inherit", Finsert_and_inherit_before_markers, |
1237 Sinsert_and_inherit_before_markers, 0, MANY, 0, | 1318 Sinsert_and_inherit_before_markers, 0, MANY, 0, |
1240 Any other markers at the point of insertion also end up after the text.") | 1321 Any other markers at the point of insertion also end up after the text.") |
1241 (nargs, args) | 1322 (nargs, args) |
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.") |
1278 (character, count, inherit) | 1338 (character, count, inherit) |
1279 Lisp_Object character, count, inherit; | 1339 Lisp_Object character, count, inherit; |
1280 { | 1340 { |
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)) |
1298 insert_and_inherit (string, strlen); | 1364 insert_and_inherit (string, strlen); |
1299 else | 1365 else |
1335 | 1401 |
1336 if (start < GPT && GPT < end) | 1402 if (start < GPT && GPT < end) |
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 |
1344 if (props) | 1410 if (props) |
1345 { | 1411 { |
1625 | 1691 |
1626 DEFUN ("subst-char-in-region", Fsubst_char_in_region, | 1692 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, |
1648 and it prevents even the entry for a first change. | 1728 and it prevents even the entry for a first change. |
1649 Also inhibit locking the file. */ | 1729 Also inhibit locking the file. */ |
1656 record_unwind_protect (subst_char_in_region_unwind_1, | 1736 record_unwind_protect (subst_char_in_region_unwind_1, |
1657 current_buffer->filename); | 1737 current_buffer->filename); |
1658 current_buffer->filename = Qnil; | 1738 current_buffer->filename = Qnil; |
1659 } | 1739 } |
1660 | 1740 |
1661 while (pos < stop) | 1741 if (pos < GPT) |
1662 { | 1742 stop = min(stop, GPT); |
1663 if (FETCH_CHAR (pos) == look) | 1743 p = POS_ADDR (pos); |
1744 while (1) | |
1745 { | |
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 { |
1671 if (MODIFF - 1 == SAVE_MODIFF) | 1764 if (MODIFF - 1 == SAVE_MODIFF) |
1672 SAVE_MODIFF++; | 1765 SAVE_MODIFF++; |
1673 if (MODIFF - 1 == current_buffer->auto_save_modified) | 1766 if (MODIFF - 1 == current_buffer->auto_save_modified) |
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) |
1688 signal_after_change (XINT (start), | 1783 signal_after_change (XINT (start), |
1689 stop - XINT (start), stop - XINT (start)); | 1784 stop - XINT (start), stop - XINT (start)); |
1720 modify_region (current_buffer, pos, stop); | 1815 modify_region (current_buffer, pos, stop); |
1721 | 1816 |
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 } |
1736 } | 1831 } |
1737 } | 1832 } |
2198 { | 2293 { |
2199 Lisp_Object *downcase = DOWNCASE_TABLE; | 2294 Lisp_Object *downcase = DOWNCASE_TABLE; |
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)) |
2207 : XINT (c1) == XINT (c2)) | 2305 : XINT (c1) == XINT (c2)) |
2208 return Qt; | 2306 return Qt; |
2589 | 2687 |
2590 defsubr (&Schar_equal); | 2688 defsubr (&Schar_equal); |
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); |
2597 | 2696 |
2598 defsubr (&Spoint_marker); | 2697 defsubr (&Spoint_marker); |
2619 defsubr (&Sbolp); | 2718 defsubr (&Sbolp); |
2620 defsubr (&Seolp); | 2719 defsubr (&Seolp); |
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); |
2627 defsubr (&Sinsert_and_inherit_before_markers); | 2727 defsubr (&Sinsert_and_inherit_before_markers); |
2628 defsubr (&Sinsert_char); | 2728 defsubr (&Sinsert_char); |