diff src/term.c @ 58638:67bea14002c3

(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.
author Kenichi Handa <handa@m17n.org>
date Tue, 30 Nov 2004 08:19:32 +0000
parents 3a86bc69c0e3
children 24c51e9d8586
line wrap: on
line diff
--- 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 ();