# HG changeset patch # User Kenichi Handa # Date 1101802772 0 # Node ID 67bea14002c35890ffb4de80bad9ede1f02a1f4b # Parent ff8a37b5299b2eb1757884e3cc9b8f31d9be6d20 (encode_terminal_buf, encode_terminal_bufsize): New variables. (encode_terminal_code): Argument changed. Encode all characters at once, and return a pointer to the result of encoding. (write_glyphs): Decide coding here. Adjusted for the above change. (insert_glyphs): Likewise. (term_init): Initialize encode_terminal_bufsize to 0. diff -r ff8a37b5299b -r 67bea14002c3 src/term.c --- a/src/term.c Tue Nov 30 08:07:11 2004 +0000 +++ b/src/term.c Tue Nov 30 08:19:32 2004 +0000 @@ -791,39 +791,43 @@ } } -/* Encode SRC_LEN glyphs starting at SRC to terminal output codes and - store them at DST. Do not write more than DST_LEN bytes. That may - require stopping before all SRC_LEN input glyphs have been - converted. - - We store the number of glyphs actually converted in *CONSUMED. The - return value is the number of bytes store in DST. */ - -int -encode_terminal_code (src, dst, src_len, dst_len, consumed) +/* Buffer to store the source and result of code conversion for terminal. */ +static unsigned char *encode_terminal_buf; +/* Allocated size of the above buffer. */ +static int encode_terminal_bufsize; + +/* Encode SRC_LEN glyphs starting at SRC to terminal output codes. + Set CODING->produced to the byte-length of the resulting byte + sequence, and return a pointer to that byte sequence. */ + +static unsigned char * +encode_terminal_code (src, src_len, coding) struct glyph *src; int src_len; - unsigned char *dst; - int dst_len, *consumed; + struct coding_system *coding; { struct glyph *src_start = src, *src_end = src + src_len; - unsigned char *dst_start = dst, *dst_end = dst + dst_len; register GLYPH g; - unsigned char workbuf[MAX_MULTIBYTE_LENGTH]; - const unsigned char *buf; - int len; + unsigned char *buf; + int nchars, nbytes, required; register int tlen = GLYPH_TABLE_LENGTH; register Lisp_Object *tbase = GLYPH_TABLE_BASE; - int result; - struct coding_system *coding; - - /* If terminal_coding does any conversion, use it, otherwise use - safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here - because it always return 1 if the member src_multibyte is 1. */ - coding = (terminal_coding.common_flags & CODING_REQUIRE_ENCODING_MASK - ? &terminal_coding - : &safe_terminal_coding); - + + /* Allocate sufficient size of buffer to store all characters in + multibyte-form. But, it may be enlarged on demand if + Vglyph_table contains a string. */ + required = MAX_MULTIBYTE_LENGTH * src_len; + if (encode_terminal_bufsize < required) + { + encode_terminal_bufsize = required; + if (encode_terminal_bufsize == 0) + encode_terminal_buf = xmalloc (required); + else + encode_terminal_buf = xrealloc (encode_terminal_buf, required); + } + + buf = encode_terminal_buf; + nchars = 0; while (src < src_end) { /* We must skip glyphs to be padded for a wide character. */ @@ -834,18 +838,11 @@ if (g < 0 || g >= tlen) { /* This glyph doesn't has an entry in Vglyph_table. */ - if (! CHAR_VALID_P (src->u.ch, 0)) - { - len = 1; - buf = " "; - coding->src_multibyte = 0; - } + if (CHAR_VALID_P (src->u.ch, 0)) + buf += CHAR_STRING (src->u.ch, buf); else - { - len = CHAR_STRING (src->u.ch, workbuf); - buf = workbuf; - coding->src_multibyte = 1; - } + *buf++ = SPACEGLYPH; + nchars++; } else { @@ -855,61 +852,72 @@ if (GLYPH_SIMPLE_P (tbase, tlen, g)) { - /* We set the multi-byte form of a character in G - (that should be an ASCII character) at - WORKBUF. */ - workbuf[0] = FAST_GLYPH_CHAR (g); - len = 1; - buf = workbuf; - coding->src_multibyte = 0; + int c = FAST_GLYPH_CHAR (g); + + if (CHAR_VALID_P (c, 0)) + buf += CHAR_STRING (c, buf); + else + *buf++ = SPACEGLYPH; + nchars++; } else { /* We have a string in Vglyph_table. */ - len = GLYPH_LENGTH (tbase, g); - buf = GLYPH_STRING (tbase, g); - coding->src_multibyte = STRING_MULTIBYTE (tbase[g]); + Lisp_Object string; + + string = tbase[g]; + if (! STRING_MULTIBYTE (string)) + string = string_to_multibyte (string); + nbytes = buf - encode_terminal_buf; + if (nbytes + SBYTES (string) < encode_terminal_bufsize) + { + encode_terminal_bufsize = nbytes + SBYTES (string); + encode_terminal_buf = xrealloc (encode_terminal_buf, + encode_terminal_bufsize); + buf = encode_terminal_buf + nbytes; + } + bcopy (SDATA (string), buf, SBYTES (string)); + buf += SBYTES (string); + nchars += SCHARS (string); } } - - result = encode_coding (coding, buf, dst, len, dst_end - dst); - len -= coding->consumed; - dst += coding->produced; - if (result == CODING_FINISH_INSUFFICIENT_DST - || (result == CODING_FINISH_INSUFFICIENT_SRC - && len > dst_end - dst)) - /* The remaining output buffer is too short. We must - break the loop here without increasing SRC so that the - next call of this function starts from the same glyph. */ - break; - - if (len > 0) - { - /* This is the case that a code of the range 0200..0237 - exists in buf. We must just write out such a code. */ - buf += coding->consumed; - while (len--) - *dst++ = *buf++; - } } src++; } - *consumed = src - src_start; - return (dst - dst_start); + nbytes = buf - encode_terminal_buf; + coding->src_multibyte = 1; + coding->dst_multibyte = 0; + if (SYMBOLP (coding->pre_write_conversion) + && ! NILP (Ffboundp (coding->pre_write_conversion))) + { + run_pre_write_conversin_on_c_str (&encode_terminal_buf, + &encode_terminal_bufsize, + nchars, nbytes, coding); + nchars = coding->produced_char; + nbytes = coding->produced; + } + required = nbytes + encoding_buffer_size (coding, nbytes); + if (encode_terminal_bufsize < required) + { + encode_terminal_bufsize = required; + encode_terminal_buf = xrealloc (encode_terminal_buf, required); + } + + encode_coding (coding, encode_terminal_buf, encode_terminal_buf + nbytes, + nbytes, encode_terminal_bufsize - nbytes); + return encode_terminal_buf + nbytes; } - void write_glyphs (string, len) register struct glyph *string; register int len; { - int produced, consumed; struct frame *sf = XFRAME (selected_frame); struct frame *f = updating_frame ? updating_frame : sf; - unsigned char conversion_buffer[1024]; - int conversion_buffer_size = sizeof conversion_buffer; + unsigned char *conversion_buffer; + struct coding_system *coding; if (write_glyphs_hook && ! FRAME_TERMCAP_P (f)) @@ -933,9 +941,14 @@ cmplus (len); + /* If terminal_coding does any conversion, use it, otherwise use + safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here + because it always return 1 if the member src_multibyte is 1. */ + coding = (terminal_coding.common_flags & CODING_REQUIRE_ENCODING_MASK + ? &terminal_coding : &safe_terminal_coding); /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at the tail. */ - terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK; + coding->mode &= ~CODING_MODE_LAST_BLOCK; while (len > 0) { @@ -951,49 +964,26 @@ highlight_if_desired (); turn_on_face (f, face_id); - while (n > 0) + if (n == len) + /* This is the last run. */ + coding->mode |= CODING_MODE_LAST_BLOCK; + conversion_buffer = encode_terminal_code (string, n, coding); + if (coding->produced > 0) { - /* We use a fixed size (1024 bytes) of conversion buffer. - Usually it is sufficient, but if not, we just repeat the - loop. */ - produced = encode_terminal_code (string, conversion_buffer, - n, conversion_buffer_size, - &consumed); - if (produced > 0) - { - fwrite (conversion_buffer, 1, produced, stdout); - if (ferror (stdout)) - clearerr (stdout); - if (termscript) - fwrite (conversion_buffer, 1, produced, termscript); - } - len -= consumed; - n -= consumed; - string += consumed; + fwrite (conversion_buffer, 1, coding->produced, stdout); + if (ferror (stdout)) + clearerr (stdout); + if (termscript) + fwrite (conversion_buffer, 1, coding->produced, termscript); } + len -= n; + string += n; /* Turn appearance modes off. */ turn_off_face (f, face_id); turn_off_highlight (); } - /* We may have to output some codes to terminate the writing. */ - if (CODING_REQUIRE_FLUSHING (&terminal_coding)) - { - terminal_coding.mode |= CODING_MODE_LAST_BLOCK; - encode_coding (&terminal_coding, "", conversion_buffer, - 0, conversion_buffer_size); - if (terminal_coding.produced > 0) - { - fwrite (conversion_buffer, 1, terminal_coding.produced, stdout); - if (ferror (stdout)) - clearerr (stdout); - if (termscript) - fwrite (conversion_buffer, 1, terminal_coding.produced, - termscript); - } - } - cmcheckmagic (); } @@ -1007,6 +997,9 @@ char *buf; struct glyph *glyph = NULL; struct frame *f, *sf; + unsigned char *conversion_buffer; + unsigned char space[1]; + struct coding_system *coding; if (len <= 0) return; @@ -1032,19 +1025,26 @@ turn_on_insert (); cmplus (len); - /* The bit CODING_MODE_LAST_BLOCK should be set to 1 only at the tail. */ - terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK; + + if (! start) + space[0] = SPACEGLYPH; + + /* If terminal_coding does any conversion, use it, otherwise use + safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here + because it always return 1 if the member src_multibyte is 1. */ + coding = (terminal_coding.common_flags & CODING_REQUIRE_ENCODING_MASK + ? &terminal_coding : &safe_terminal_coding); + /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at + the tail. */ + coding->mode &= ~CODING_MODE_LAST_BLOCK; + while (len-- > 0) { - int produced, consumed; - unsigned char conversion_buffer[1024]; - int conversion_buffer_size = sizeof conversion_buffer; - OUTPUT1_IF (TS_ins_char); if (!start) { - conversion_buffer[0] = SPACEGLYPH; - produced = 1; + conversion_buffer = space; + coding->produced = 1; } else { @@ -1062,21 +1062,18 @@ if (len <= 0) /* This is the last glyph. */ - terminal_coding.mode |= CODING_MODE_LAST_BLOCK; - - /* The size of conversion buffer (1024 bytes) is surely - sufficient for just one glyph. */ - produced = encode_terminal_code (glyph, conversion_buffer, 1, - conversion_buffer_size, &consumed); + coding->mode |= CODING_MODE_LAST_BLOCK; + + conversion_buffer = encode_terminal_code (glyph, 1, coding); } - if (produced > 0) + if (coding->produced > 0) { - fwrite (conversion_buffer, 1, produced, stdout); + fwrite (conversion_buffer, 1, coding->produced, stdout); if (ferror (stdout)) clearerr (stdout); if (termscript) - fwrite (conversion_buffer, 1, produced, termscript); + fwrite (conversion_buffer, 1, coding->produced, termscript); } OUTPUT1_IF (TS_pad_inserted_char); @@ -2257,6 +2254,8 @@ int status; struct frame *sf = XFRAME (selected_frame); + encode_terminal_bufsize = 0; + #ifdef WINDOWSNT initialize_w32_display ();