diff options
| author | Kenichi Handa | 2013-03-16 01:03:54 +0900 |
|---|---|---|
| committer | Kenichi Handa | 2013-03-16 01:03:54 +0900 |
| commit | 8a44e6d176989d8eef140314098c76a70248ba61 (patch) | |
| tree | 096ee4a0f9a15f2f300ba68d2dd1dd28b88e18a0 /src | |
| parent | 9b5939800615a4e08ac389813a70faf4b9e57bba (diff) | |
| download | emacs-8a44e6d176989d8eef140314098c76a70248ba61.tar.gz emacs-8a44e6d176989d8eef140314098c76a70248ba61.zip | |
Optimize ASCII file reading with EOL format detection and decoding.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 28 | ||||
| -rw-r--r-- | src/coding.c | 197 | ||||
| -rw-r--r-- | src/coding.h | 6 | ||||
| -rw-r--r-- | src/insdel.c | 33 | ||||
| -rw-r--r-- | src/lisp.h | 4 |
5 files changed, 209 insertions, 59 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 8ae25e6e612..44e2ff1a1f1 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,31 @@ | |||
| 1 | 2013-03-15 handa <handa@gnu.org> | ||
| 2 | |||
| 3 | * insdel.c (insert_from_gap): New arg text_at_gap_tail. | ||
| 4 | (adjust_after_replace): Make it back to static. Delete the third | ||
| 5 | arg text_at_gap_tail. Cancel the code for handling it. | ||
| 6 | |||
| 7 | * coding.h (struct coding_system): New member eol_seen. | ||
| 8 | |||
| 9 | * coding.c (detect_ascii): New function. | ||
| 10 | (detect_coding): Set coding->head_ascii and coding->eol_seen only | ||
| 11 | when the source bytes are actually scanned. On detecting for | ||
| 12 | coding_category_utf_8_auto, call detect_ascii instead of scanning | ||
| 13 | source bytes directly. | ||
| 14 | (produce_chars): Call insert_from_gap with the new arg 0. | ||
| 15 | (encode_coding): Likewise. | ||
| 16 | (decode_coding_gap): Control ASCII optimization by the variable | ||
| 17 | disable_ascii_optimization instead of #ifndef .. #endif. | ||
| 18 | Deccode EOL format according to coding->eol_seen. | ||
| 19 | (syms_of_coding): Declare disable-ascii-optimization as a Lisp | ||
| 20 | variable. | ||
| 21 | |||
| 22 | * global.h (struct emacs_globals): New member | ||
| 23 | f_disable_ascii_optimization. | ||
| 24 | (disable_ascii_optimization): New macro. | ||
| 25 | |||
| 26 | * lisp.h (adjust_after_replace): Cancel externing it. | ||
| 27 | (insert_from_gap): Adjust prototype. | ||
| 28 | |||
| 1 | 2013-03-11 Paul Eggert <eggert@cs.ucla.edu> | 29 | 2013-03-11 Paul Eggert <eggert@cs.ucla.edu> |
| 2 | 30 | ||
| 3 | * insdel.c (adjust_after_replace): Use bool for boolean. | 31 | * insdel.c (adjust_after_replace): Use bool for boolean. |
diff --git a/src/coding.c b/src/coding.c index c18632f301b..5047e1149bc 100644 --- a/src/coding.c +++ b/src/coding.c | |||
| @@ -6071,6 +6071,93 @@ complement_process_encoding_system (Lisp_Object coding_system) | |||
| 6071 | #define EOL_SEEN_CR 2 | 6071 | #define EOL_SEEN_CR 2 |
| 6072 | #define EOL_SEEN_CRLF 4 | 6072 | #define EOL_SEEN_CRLF 4 |
| 6073 | 6073 | ||
| 6074 | |||
| 6075 | static Lisp_Object adjust_coding_eol_type (struct coding_system *coding, int eol_seen); | ||
| 6076 | |||
| 6077 | |||
| 6078 | /* Return 1 if all the source bytes are ASCII, and return 0 otherwize. | ||
| 6079 | By side effects, set coding->head_ascii and coding->eol_seen. The | ||
| 6080 | value of coding->eol_seen is "logical or" of EOL_SEEN_LF, | ||
| 6081 | EOL_SEEN_CR, and EOL_SEEN_CRLF, but the value is reliable only when | ||
| 6082 | all the source bytes are ASCII. */ | ||
| 6083 | |||
| 6084 | static bool | ||
| 6085 | detect_ascii (struct coding_system *coding) | ||
| 6086 | { | ||
| 6087 | const unsigned char *src, *end; | ||
| 6088 | Lisp_Object eol_type = CODING_ID_EOL_TYPE (coding->id); | ||
| 6089 | int eol_seen; | ||
| 6090 | |||
| 6091 | eol_seen = (VECTORP (eol_type) ? EOL_SEEN_NONE | ||
| 6092 | : EQ (eol_type, Qunix) ? EOL_SEEN_LF | ||
| 6093 | : EQ (eol_type, Qdos) ? EOL_SEEN_CRLF | ||
| 6094 | : EOL_SEEN_CR); | ||
| 6095 | coding_set_source (coding); | ||
| 6096 | src = coding->source; | ||
| 6097 | end = src + coding->src_bytes; | ||
| 6098 | |||
| 6099 | if (inhibit_eol_conversion) | ||
| 6100 | { | ||
| 6101 | /* We don't have to check EOL format. */ | ||
| 6102 | while (src < end && !( *src & 0x80)) src++; | ||
| 6103 | eol_seen = EOL_SEEN_LF; | ||
| 6104 | adjust_coding_eol_type (coding, eol_seen); | ||
| 6105 | } | ||
| 6106 | else if (eol_seen != EOL_SEEN_NONE) | ||
| 6107 | { | ||
| 6108 | /* We don't have to check EOL format either. */ | ||
| 6109 | while (src < end && !(*src & 0x80)) src++; | ||
| 6110 | } | ||
| 6111 | else | ||
| 6112 | { | ||
| 6113 | end--; /* We look ahead one byte. */ | ||
| 6114 | while (src < end) | ||
| 6115 | { | ||
| 6116 | int c = *src; | ||
| 6117 | |||
| 6118 | if (c & 0x80) | ||
| 6119 | break; | ||
| 6120 | src++; | ||
| 6121 | if (c < 0x20) | ||
| 6122 | { | ||
| 6123 | if (c == '\r') | ||
| 6124 | { | ||
| 6125 | if (*src == '\n') | ||
| 6126 | { | ||
| 6127 | eol_seen |= EOL_SEEN_CRLF; | ||
| 6128 | src++; | ||
| 6129 | } | ||
| 6130 | else | ||
| 6131 | eol_seen |= EOL_SEEN_CR; | ||
| 6132 | } | ||
| 6133 | else if (c == '\n') | ||
| 6134 | eol_seen |= EOL_SEEN_LF; | ||
| 6135 | } | ||
| 6136 | } | ||
| 6137 | if (src > end) | ||
| 6138 | /* The last two bytes are CR LF, which means that we have | ||
| 6139 | scanned all bytes. */ | ||
| 6140 | end++; | ||
| 6141 | else if (src == end) | ||
| 6142 | { | ||
| 6143 | end++; | ||
| 6144 | if (! (*src & 0x80)) | ||
| 6145 | { | ||
| 6146 | if (*src == '\r') | ||
| 6147 | eol_seen |= EOL_SEEN_CR; | ||
| 6148 | else if (*src == '\n') | ||
| 6149 | eol_seen |= EOL_SEEN_LF; | ||
| 6150 | src++; | ||
| 6151 | } | ||
| 6152 | } | ||
| 6153 | adjust_coding_eol_type (coding, eol_seen); | ||
| 6154 | } | ||
| 6155 | coding->head_ascii = src - coding->source; | ||
| 6156 | coding->eol_seen = eol_seen; | ||
| 6157 | return (src == end); | ||
| 6158 | } | ||
| 6159 | |||
| 6160 | |||
| 6074 | /* Detect how end-of-line of a text of length SRC_BYTES pointed by | 6161 | /* Detect how end-of-line of a text of length SRC_BYTES pointed by |
| 6075 | SOURCE is encoded. If CATEGORY is one of | 6162 | SOURCE is encoded. If CATEGORY is one of |
| 6076 | coding_category_utf_16_XXXX, assume that CR and LF are encoded by | 6163 | coding_category_utf_16_XXXX, assume that CR and LF are encoded by |
| @@ -6215,7 +6302,6 @@ detect_coding (struct coding_system *coding) | |||
| 6215 | coding_set_source (coding); | 6302 | coding_set_source (coding); |
| 6216 | 6303 | ||
| 6217 | src_end = coding->source + coding->src_bytes; | 6304 | src_end = coding->source + coding->src_bytes; |
| 6218 | coding->head_ascii = 0; | ||
| 6219 | 6305 | ||
| 6220 | /* If we have not yet decided the text encoding type, detect it | 6306 | /* If we have not yet decided the text encoding type, detect it |
| 6221 | now. */ | 6307 | now. */ |
| @@ -6225,6 +6311,8 @@ detect_coding (struct coding_system *coding) | |||
| 6225 | struct coding_detection_info detect_info; | 6311 | struct coding_detection_info detect_info; |
| 6226 | bool null_byte_found = 0, eight_bit_found = 0; | 6312 | bool null_byte_found = 0, eight_bit_found = 0; |
| 6227 | 6313 | ||
| 6314 | coding->head_ascii = 0; | ||
| 6315 | coding->eol_seen = EOL_SEEN_NONE; | ||
| 6228 | detect_info.checked = detect_info.found = detect_info.rejected = 0; | 6316 | detect_info.checked = detect_info.found = detect_info.rejected = 0; |
| 6229 | for (src = coding->source; src < src_end; src++) | 6317 | for (src = coding->source; src < src_end; src++) |
| 6230 | { | 6318 | { |
| @@ -6263,6 +6351,26 @@ detect_coding (struct coding_system *coding) | |||
| 6263 | if (eight_bit_found) | 6351 | if (eight_bit_found) |
| 6264 | break; | 6352 | break; |
| 6265 | } | 6353 | } |
| 6354 | else if (! disable_ascii_optimization | ||
| 6355 | && ! inhibit_eol_conversion) | ||
| 6356 | { | ||
| 6357 | if (c == '\r') | ||
| 6358 | { | ||
| 6359 | if (src < src_end && src[1] == '\n') | ||
| 6360 | { | ||
| 6361 | coding->eol_seen |= EOL_SEEN_CRLF; | ||
| 6362 | src++; | ||
| 6363 | coding->head_ascii++; | ||
| 6364 | } | ||
| 6365 | else | ||
| 6366 | coding->eol_seen |= EOL_SEEN_CR; | ||
| 6367 | } | ||
| 6368 | else if (c == '\n') | ||
| 6369 | { | ||
| 6370 | coding->eol_seen |= EOL_SEEN_LF; | ||
| 6371 | } | ||
| 6372 | } | ||
| 6373 | |||
| 6266 | if (! eight_bit_found) | 6374 | if (! eight_bit_found) |
| 6267 | coding->head_ascii++; | 6375 | coding->head_ascii++; |
| 6268 | } | 6376 | } |
| @@ -6353,19 +6461,20 @@ detect_coding (struct coding_system *coding) | |||
| 6353 | coding_systems | 6461 | coding_systems |
| 6354 | = AREF (CODING_ID_ATTRS (coding->id), coding_attr_utf_bom); | 6462 | = AREF (CODING_ID_ATTRS (coding->id), coding_attr_utf_bom); |
| 6355 | detect_info.found = detect_info.rejected = 0; | 6463 | detect_info.found = detect_info.rejected = 0; |
| 6356 | for (src = coding->source; src < src_end; src++) | 6464 | if (detect_ascii (coding)) |
| 6357 | { | 6465 | { |
| 6358 | if (*src & 0x80) | 6466 | setup_coding_system (XCDR (coding_systems), coding); |
| 6359 | break; | ||
| 6360 | } | 6467 | } |
| 6361 | coding->head_ascii = src - coding->source; | 6468 | else |
| 6362 | if (CONSP (coding_systems) | ||
| 6363 | && detect_coding_utf_8 (coding, &detect_info)) | ||
| 6364 | { | 6469 | { |
| 6365 | if (detect_info.found & CATEGORY_MASK_UTF_8_SIG) | 6470 | if (CONSP (coding_systems) |
| 6366 | setup_coding_system (XCAR (coding_systems), coding); | 6471 | && detect_coding_utf_8 (coding, &detect_info)) |
| 6367 | else | 6472 | { |
| 6368 | setup_coding_system (XCDR (coding_systems), coding); | 6473 | if (detect_info.found & CATEGORY_MASK_UTF_8_SIG) |
| 6474 | setup_coding_system (XCAR (coding_systems), coding); | ||
| 6475 | else | ||
| 6476 | setup_coding_system (XCDR (coding_systems), coding); | ||
| 6477 | } | ||
| 6369 | } | 6478 | } |
| 6370 | } | 6479 | } |
| 6371 | else if (XINT (CODING_ATTR_CATEGORY (CODING_ID_ATTRS (coding->id))) | 6480 | else if (XINT (CODING_ATTR_CATEGORY (CODING_ID_ATTRS (coding->id))) |
| @@ -6378,6 +6487,7 @@ detect_coding (struct coding_system *coding) | |||
| 6378 | = AREF (CODING_ID_ATTRS (coding->id), coding_attr_utf_bom); | 6487 | = AREF (CODING_ID_ATTRS (coding->id), coding_attr_utf_bom); |
| 6379 | detect_info.found = detect_info.rejected = 0; | 6488 | detect_info.found = detect_info.rejected = 0; |
| 6380 | coding->head_ascii = 0; | 6489 | coding->head_ascii = 0; |
| 6490 | coding->eol_seen = EOL_SEEN_NONE; | ||
| 6381 | if (CONSP (coding_systems) | 6491 | if (CONSP (coding_systems) |
| 6382 | && detect_coding_utf_16 (coding, &detect_info)) | 6492 | && detect_coding_utf_16 (coding, &detect_info)) |
| 6383 | { | 6493 | { |
| @@ -6815,7 +6925,7 @@ produce_chars (struct coding_system *coding, Lisp_Object translation_table, | |||
| 6815 | 6925 | ||
| 6816 | produced = dst - (coding->destination + coding->produced); | 6926 | produced = dst - (coding->destination + coding->produced); |
| 6817 | if (BUFFERP (coding->dst_object) && produced_chars > 0) | 6927 | if (BUFFERP (coding->dst_object) && produced_chars > 0) |
| 6818 | insert_from_gap (produced_chars, produced); | 6928 | insert_from_gap (produced_chars, produced, 0); |
| 6819 | coding->produced += produced; | 6929 | coding->produced += produced; |
| 6820 | coding->produced_char += produced_chars; | 6930 | coding->produced_char += produced_chars; |
| 6821 | return carryover; | 6931 | return carryover; |
| @@ -7400,7 +7510,7 @@ encode_coding (struct coding_system *coding) | |||
| 7400 | } while (coding->consumed_char < coding->src_chars); | 7510 | } while (coding->consumed_char < coding->src_chars); |
| 7401 | 7511 | ||
| 7402 | if (BUFFERP (coding->dst_object) && coding->produced_char > 0) | 7512 | if (BUFFERP (coding->dst_object) && coding->produced_char > 0) |
| 7403 | insert_from_gap (coding->produced_char, coding->produced); | 7513 | insert_from_gap (coding->produced_char, coding->produced, 0); |
| 7404 | 7514 | ||
| 7405 | SAFE_FREE (); | 7515 | SAFE_FREE (); |
| 7406 | } | 7516 | } |
| @@ -7510,39 +7620,45 @@ decode_coding_gap (struct coding_system *coding, | |||
| 7510 | if (CODING_REQUIRE_DETECTION (coding)) | 7620 | if (CODING_REQUIRE_DETECTION (coding)) |
| 7511 | detect_coding (coding); | 7621 | detect_coding (coding); |
| 7512 | attrs = CODING_ID_ATTRS (coding->id); | 7622 | attrs = CODING_ID_ATTRS (coding->id); |
| 7513 | #ifndef CODING_DISABLE_ASCII_OPTIMIZATION | 7623 | if (! disable_ascii_optimization) |
| 7514 | if (! NILP (CODING_ATTR_ASCII_COMPAT (attrs)) | ||
| 7515 | && NILP (CODING_ATTR_POST_READ (attrs)) | ||
| 7516 | && NILP (get_translation_table (attrs, 0, NULL)) | ||
| 7517 | && (inhibit_eol_conversion | ||
| 7518 | || EQ (CODING_ID_EOL_TYPE (coding->id), Qunix))) | ||
| 7519 | { | 7624 | { |
| 7520 | /* We can skip the conversion if all source bytes are ASCII. */ | 7625 | if (! NILP (CODING_ATTR_ASCII_COMPAT (attrs)) |
| 7521 | if (coding->head_ascii < 0) | 7626 | && NILP (CODING_ATTR_POST_READ (attrs)) |
| 7627 | && NILP (get_translation_table (attrs, 0, NULL)) | ||
| 7628 | && (coding->head_ascii >= 0 /* We've already called detect_coding */ | ||
| 7629 | ? coding->head_ascii == bytes | ||
| 7630 | : detect_ascii (coding))) | ||
| 7522 | { | 7631 | { |
| 7523 | /* We have not yet counted the number of ASCII bytes at the | 7632 | if (coding->eol_seen == EOL_SEEN_CR) |
| 7524 | head of the source. Do it now. */ | 7633 | { |
| 7525 | const unsigned char *src, *src_end; | 7634 | unsigned char *src_end = GAP_END_ADDR; |
| 7635 | unsigned char *src = src - coding->src_bytes; | ||
| 7526 | 7636 | ||
| 7527 | coding_set_source (coding); | 7637 | while (src < src_end) |
| 7528 | src_end = coding->source + coding->src_bytes; | 7638 | { |
| 7529 | for (src = coding->source; src < src_end; src++) | 7639 | if (*src++ == '\r') |
| 7640 | src[-1] = '\n'; | ||
| 7641 | } | ||
| 7642 | } | ||
| 7643 | else if (coding->eol_seen == EOL_SEEN_CRLF) | ||
| 7530 | { | 7644 | { |
| 7531 | if (*src & 0x80) | 7645 | unsigned char *src = GAP_END_ADDR; |
| 7532 | break; | 7646 | unsigned char *src_beg = src - coding->src_bytes; |
| 7647 | unsigned char *dst = src; | ||
| 7648 | |||
| 7649 | while (src_beg < src) | ||
| 7650 | { | ||
| 7651 | *--dst = *--src; | ||
| 7652 | if (*src == '\n') | ||
| 7653 | src--; | ||
| 7654 | } | ||
| 7655 | bytes -= dst - src; | ||
| 7533 | } | 7656 | } |
| 7534 | coding->head_ascii = src - coding->source; | 7657 | coding->produced_char = coding->produced = bytes; |
| 7535 | } | 7658 | insert_from_gap (bytes, bytes, 1); |
| 7536 | if (coding->src_bytes == coding->head_ascii) | ||
| 7537 | { | ||
| 7538 | /* No need of conversion. Use the data in the gap as is. */ | ||
| 7539 | coding->produced_char = chars; | ||
| 7540 | coding->produced = bytes; | ||
| 7541 | adjust_after_replace (PT, PT_BYTE, Qnil, chars, bytes, 1); | ||
| 7542 | return; | 7659 | return; |
| 7543 | } | 7660 | } |
| 7544 | } | 7661 | } |
| 7545 | #endif /* not CODING_DISABLE_ASCII_OPTIMIZATION */ | ||
| 7546 | code_conversion_save (0, 0); | 7662 | code_conversion_save (0, 0); |
| 7547 | 7663 | ||
| 7548 | coding->mode |= CODING_MODE_LAST_BLOCK; | 7664 | coding->mode |= CODING_MODE_LAST_BLOCK; |
| @@ -10758,6 +10874,11 @@ from GNU Find and GNU Grep. Emacs will then ignore the null bytes and | |||
| 10758 | decode text as usual. */); | 10874 | decode text as usual. */); |
| 10759 | inhibit_null_byte_detection = 0; | 10875 | inhibit_null_byte_detection = 0; |
| 10760 | 10876 | ||
| 10877 | DEFVAR_BOOL ("disable-ascii-optimization", disable_ascii_optimization, | ||
| 10878 | doc: /* If non-nil, Emacs does not optimize code decoder for ASCII files. | ||
| 10879 | Internal use only. Removed after the experimental optimizer gets stable. */); | ||
| 10880 | disable_ascii_optimization = 0; | ||
| 10881 | |||
| 10761 | DEFVAR_LISP ("translation-table-for-input", Vtranslation_table_for_input, | 10882 | DEFVAR_LISP ("translation-table-for-input", Vtranslation_table_for_input, |
| 10762 | doc: /* Char table for translating self-inserting characters. | 10883 | doc: /* Char table for translating self-inserting characters. |
| 10763 | This is applied to the result of input methods, not their input. | 10884 | This is applied to the result of input methods, not their input. |
diff --git a/src/coding.h b/src/coding.h index c13567c3d53..d40209be68f 100644 --- a/src/coding.h +++ b/src/coding.h | |||
| @@ -440,9 +440,13 @@ struct coding_system | |||
| 440 | /* How may heading bytes we can skip for decoding. This is set to | 440 | /* How may heading bytes we can skip for decoding. This is set to |
| 441 | -1 in setup_coding_system, and updated by detect_coding. So, | 441 | -1 in setup_coding_system, and updated by detect_coding. So, |
| 442 | when this is equal to the byte length of the text being | 442 | when this is equal to the byte length of the text being |
| 443 | converted, we can skip the actual conversion process. */ | 443 | converted, we can skip the actual conversion process except for |
| 444 | the eol format. */ | ||
| 444 | ptrdiff_t head_ascii; | 445 | ptrdiff_t head_ascii; |
| 445 | 446 | ||
| 447 | /* Used internally in coding.c. See the comment of detect_ascii. */ | ||
| 448 | int eol_seen; | ||
| 449 | |||
| 446 | /* The following members are set by encoding/decoding routine. */ | 450 | /* The following members are set by encoding/decoding routine. */ |
| 447 | ptrdiff_t produced, produced_char, consumed, consumed_char; | 451 | ptrdiff_t produced, produced_char, consumed, consumed_char; |
| 448 | 452 | ||
diff --git a/src/insdel.c b/src/insdel.c index c0afa80d5e8..a60fed0c32e 100644 --- a/src/insdel.c +++ b/src/insdel.c | |||
| @@ -977,10 +977,11 @@ insert_from_string_1 (Lisp_Object string, ptrdiff_t pos, ptrdiff_t pos_byte, | |||
| 977 | } | 977 | } |
| 978 | 978 | ||
| 979 | /* Insert a sequence of NCHARS chars which occupy NBYTES bytes | 979 | /* Insert a sequence of NCHARS chars which occupy NBYTES bytes |
| 980 | starting at GPT_ADDR. */ | 980 | starting at GAP_END_ADDR - NBYTES (if text_at_gap_tail) and at |
| 981 | GPT_ADDR (if not text_at_gap_tail). */ | ||
| 981 | 982 | ||
| 982 | void | 983 | void |
| 983 | insert_from_gap (ptrdiff_t nchars, ptrdiff_t nbytes) | 984 | insert_from_gap (ptrdiff_t nchars, ptrdiff_t nbytes, bool text_at_gap_tail) |
| 984 | { | 985 | { |
| 985 | if (NILP (BVAR (current_buffer, enable_multibyte_characters))) | 986 | if (NILP (BVAR (current_buffer, enable_multibyte_characters))) |
| 986 | nchars = nbytes; | 987 | nchars = nbytes; |
| @@ -989,10 +990,13 @@ insert_from_gap (ptrdiff_t nchars, ptrdiff_t nbytes) | |||
| 989 | MODIFF++; | 990 | MODIFF++; |
| 990 | 991 | ||
| 991 | GAP_SIZE -= nbytes; | 992 | GAP_SIZE -= nbytes; |
| 992 | GPT += nchars; | 993 | if (! text_at_gap_tail) |
| 994 | { | ||
| 995 | GPT += nchars; | ||
| 996 | GPT_BYTE += nbytes; | ||
| 997 | } | ||
| 993 | ZV += nchars; | 998 | ZV += nchars; |
| 994 | Z += nchars; | 999 | Z += nchars; |
| 995 | GPT_BYTE += nbytes; | ||
| 996 | ZV_BYTE += nbytes; | 1000 | ZV_BYTE += nbytes; |
| 997 | Z_BYTE += nbytes; | 1001 | Z_BYTE += nbytes; |
| 998 | if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */ | 1002 | if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */ |
| @@ -1010,7 +1014,7 @@ insert_from_gap (ptrdiff_t nchars, ptrdiff_t nbytes) | |||
| 1010 | current_buffer, 0); | 1014 | current_buffer, 0); |
| 1011 | } | 1015 | } |
| 1012 | 1016 | ||
| 1013 | if (GPT - nchars < PT) | 1017 | if (! text_at_gap_tail && GPT - nchars < PT) |
| 1014 | adjust_point (nchars, nbytes); | 1018 | adjust_point (nchars, nbytes); |
| 1015 | 1019 | ||
| 1016 | check_markers (); | 1020 | check_markers (); |
| @@ -1162,16 +1166,14 @@ insert_from_buffer_1 (struct buffer *buf, | |||
| 1162 | 1166 | ||
| 1163 | /* Record undo information and adjust markers and position keepers for | 1167 | /* Record undo information and adjust markers and position keepers for |
| 1164 | a replacement of a text PREV_TEXT at FROM to a new text of LEN | 1168 | a replacement of a text PREV_TEXT at FROM to a new text of LEN |
| 1165 | chars (LEN_BYTE bytes). If TEXT_AT_GAP_TAIL, the new text | 1169 | chars (LEN_BYTE bytes) which resides in the gap just after |
| 1166 | resides at the gap tail; i.e. at (GAP_END_ADDR - LEN_BYTE) | 1170 | GPT_ADDR. |
| 1167 | Otherwise, the text resides in the gap just after GPT_BYTE. | ||
| 1168 | 1171 | ||
| 1169 | PREV_TEXT nil means the new text was just inserted. */ | 1172 | PREV_TEXT nil means the new text was just inserted. */ |
| 1170 | 1173 | ||
| 1171 | void | 1174 | static void |
| 1172 | adjust_after_replace (ptrdiff_t from, ptrdiff_t from_byte, | 1175 | adjust_after_replace (ptrdiff_t from, ptrdiff_t from_byte, |
| 1173 | Lisp_Object prev_text, ptrdiff_t len, ptrdiff_t len_byte, | 1176 | Lisp_Object prev_text, ptrdiff_t len, ptrdiff_t len_byte) |
| 1174 | bool text_at_gap_tail) | ||
| 1175 | { | 1177 | { |
| 1176 | ptrdiff_t nchars_del = 0, nbytes_del = 0; | 1178 | ptrdiff_t nchars_del = 0, nbytes_del = 0; |
| 1177 | 1179 | ||
| @@ -1191,11 +1193,8 @@ adjust_after_replace (ptrdiff_t from, ptrdiff_t from_byte, | |||
| 1191 | GAP_SIZE -= len_byte; | 1193 | GAP_SIZE -= len_byte; |
| 1192 | ZV += len; Z+= len; | 1194 | ZV += len; Z+= len; |
| 1193 | ZV_BYTE += len_byte; Z_BYTE += len_byte; | 1195 | ZV_BYTE += len_byte; Z_BYTE += len_byte; |
| 1194 | if (! text_at_gap_tail) | 1196 | GPT += len; GPT_BYTE += len_byte; |
| 1195 | { | 1197 | if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */ |
| 1196 | GPT += len; GPT_BYTE += len_byte; | ||
| 1197 | if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */ | ||
| 1198 | } | ||
| 1199 | 1198 | ||
| 1200 | if (nchars_del > 0) | 1199 | if (nchars_del > 0) |
| 1201 | adjust_markers_for_replace (from, from_byte, nchars_del, nbytes_del, | 1200 | adjust_markers_for_replace (from, from_byte, nchars_del, nbytes_del, |
| @@ -1250,7 +1249,7 @@ adjust_after_insert (ptrdiff_t from, ptrdiff_t from_byte, | |||
| 1250 | GPT -= len; GPT_BYTE -= len_byte; | 1249 | GPT -= len; GPT_BYTE -= len_byte; |
| 1251 | ZV -= len; ZV_BYTE -= len_byte; | 1250 | ZV -= len; ZV_BYTE -= len_byte; |
| 1252 | Z -= len; Z_BYTE -= len_byte; | 1251 | Z -= len; Z_BYTE -= len_byte; |
| 1253 | adjust_after_replace (from, from_byte, Qnil, newlen, len_byte, 0); | 1252 | adjust_after_replace (from, from_byte, Qnil, newlen, len_byte); |
| 1254 | } | 1253 | } |
| 1255 | 1254 | ||
| 1256 | /* Replace the text from character positions FROM to TO with NEW, | 1255 | /* Replace the text from character positions FROM to TO with NEW, |
diff --git a/src/lisp.h b/src/lisp.h index bb9f60b29f9..b2ab5684d4d 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -2880,7 +2880,7 @@ extern void insert (const char *, ptrdiff_t); | |||
| 2880 | extern void insert_and_inherit (const char *, ptrdiff_t); | 2880 | extern void insert_and_inherit (const char *, ptrdiff_t); |
| 2881 | extern void insert_1_both (const char *, ptrdiff_t, ptrdiff_t, | 2881 | extern void insert_1_both (const char *, ptrdiff_t, ptrdiff_t, |
| 2882 | bool, bool, bool); | 2882 | bool, bool, bool); |
| 2883 | extern void insert_from_gap (ptrdiff_t, ptrdiff_t); | 2883 | extern void insert_from_gap (ptrdiff_t, ptrdiff_t, bool text_at_gap_tail); |
| 2884 | extern void insert_from_string (Lisp_Object, ptrdiff_t, ptrdiff_t, | 2884 | extern void insert_from_string (Lisp_Object, ptrdiff_t, ptrdiff_t, |
| 2885 | ptrdiff_t, ptrdiff_t, bool); | 2885 | ptrdiff_t, ptrdiff_t, bool); |
| 2886 | extern void insert_from_buffer (struct buffer *, ptrdiff_t, ptrdiff_t, bool); | 2886 | extern void insert_from_buffer (struct buffer *, ptrdiff_t, ptrdiff_t, bool); |
| @@ -2900,8 +2900,6 @@ extern Lisp_Object del_range_2 (ptrdiff_t, ptrdiff_t, | |||
| 2900 | extern void modify_region_1 (ptrdiff_t, ptrdiff_t, bool); | 2900 | extern void modify_region_1 (ptrdiff_t, ptrdiff_t, bool); |
| 2901 | extern void prepare_to_modify_buffer (ptrdiff_t, ptrdiff_t, ptrdiff_t *); | 2901 | extern void prepare_to_modify_buffer (ptrdiff_t, ptrdiff_t, ptrdiff_t *); |
| 2902 | extern void signal_after_change (ptrdiff_t, ptrdiff_t, ptrdiff_t); | 2902 | extern void signal_after_change (ptrdiff_t, ptrdiff_t, ptrdiff_t); |
| 2903 | extern void adjust_after_replace (ptrdiff_t, ptrdiff_t, Lisp_Object, | ||
| 2904 | ptrdiff_t, ptrdiff_t, bool); | ||
| 2905 | extern void adjust_after_insert (ptrdiff_t, ptrdiff_t, ptrdiff_t, | 2903 | extern void adjust_after_insert (ptrdiff_t, ptrdiff_t, ptrdiff_t, |
| 2906 | ptrdiff_t, ptrdiff_t); | 2904 | ptrdiff_t, ptrdiff_t); |
| 2907 | extern void adjust_markers_for_delete (ptrdiff_t, ptrdiff_t, | 2905 | extern void adjust_markers_for_delete (ptrdiff_t, ptrdiff_t, |