changeset 23825:085b163b6115

(Vdos_unsupported_char_glyph): New variable. (syms_of_msdos): DEFVAR_LISP it. (IT_insert_glyphs, IT_delete_glyphs): New functions which abort Emacs. (internal_terminal_init): Set up insert_glyphs_hook and delete_glyphs_hook to call them. Explicitly set char_ins_del_ok to 0. (unibyte_display_via_language_environment): New variable. (syms_of_msdos): Devfar it. (IT_write_glyphs): Honor glyph aliasing via Vglyph_table. Encode the character codes of the glyphs according to the terminal_coding in effect.
author Eli Zaretskii <eliz@gnu.org>
date Sun, 06 Dec 1998 15:57:48 +0000
parents ac5d1cd520fa
children f4646c30800a
files src/msdos.c
diffstat 1 files changed, 236 insertions(+), 22 deletions(-) [+]
line wrap: on
line diff
--- a/src/msdos.c	Sun Dec 06 15:55:59 1998 +0000
+++ b/src/msdos.c	Sun Dec 06 15:57:48 1998 +0000
@@ -50,8 +50,12 @@
 #include "msdos.h"
 #include "systime.h"
 #include "termhooks.h"
+#include "termchar.h"
 #include "dispextern.h"
 #include "termopts.h"
+#include "charset.h"
+#include "coding.h"
+#include "disptab.h"
 #include "frame.h"
 #include "window.h"
 #include "buffer.h"
@@ -352,6 +356,9 @@
 static unsigned short screen_virtual_segment = 0;
 static unsigned short screen_virtual_offset = 0;
 
+/* A flag to control how to display unibyte 8-bit character.  */
+int unibyte_display_via_language_environment;
+
 #if __DJGPP__ > 1
 /* Update the screen from a part of relocated DOS/V screen buffer which
    begins at OFFSET and includes COUNT characters.  */
@@ -671,37 +678,203 @@
   ScreenAttrib = (FACE_BACKGROUND (fp) << 4) | FACE_FOREGROUND (fp);
 }
 
+Lisp_Object Vdos_unsupported_char_glyph;
+
 static void
-IT_write_glyphs (GLYPH *str, int len)
+IT_write_glyphs (GLYPH *str, int str_len)
 {
-  int newface;
-  int ch, l = len;
-  unsigned char *buf, *bp;
+  unsigned char *screen_buf, *screen_bp, *screen_buf_end, *bp;
+  int unsupported_face = FAST_GLYPH_FACE (Vdos_unsupported_char_glyph);
+  unsigned unsupported_char= FAST_GLYPH_CHAR (Vdos_unsupported_char_glyph);
   int offset = 2 * (new_pos_X + screen_size_X * new_pos_Y);
-
-  if (len == 0) return;
+  register int sl = str_len;
+  register int tlen = GLYPH_TABLE_LENGTH;
+  register Lisp_Object *tbase = GLYPH_TABLE_BASE;
+
+  struct coding_system *coding = CODING_REQUIRE_ENCODING (&terminal_coding)
+    ? &terminal_coding
+    : &safe_terminal_coding;
+
+  if (str_len == 0) return;
   
-  buf = bp = alloca (len * 2);
+  screen_buf = screen_bp = alloca (str_len * 2);
+  screen_buf_end = screen_buf + str_len * 2;
   
-  while (--l >= 0)
+  /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
+     the tail.  */
+  terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK;
+  while (sl)
     {
-      newface = FAST_GLYPH_FACE (*str);
-      if (newface != screen_face)
-	IT_set_face (newface);
-      ch = FAST_GLYPH_CHAR (*str);
-      *bp++ = (unsigned char)ch;
-      *bp++ = ScreenAttrib;
-      
-      if (termscript)
-	fputc (ch, termscript);
-      str++;
+      int cf, ch, chlen, enclen;
+      unsigned char workbuf[4], *buf;
+      register GLYPH g = *str;
+
+      /* Find the actual glyph to display by traversing the entire
+	 aliases chain for this glyph.  */
+      GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
+
+      /* Glyphs with GLYPH_MASK_PADDING bit set are actually there
+	 only for the redisplay code to know how many columns does
+         this character occupy on the screen.  Skip padding glyphs.  */
+      if ((g & GLYPH_MASK_PADDING))
+	{
+	  str++;
+	  sl--;
+	}
+      else
+	{
+	  /* Convert the character code to multibyte, if they
+	     requested display via language environment.  */
+	  ch = FAST_GLYPH_CHAR (g);
+	  if (unibyte_display_via_language_environment
+	      && SINGLE_BYTE_CHAR_P (ch)
+	      && (ch >= 0240 || !NILP (Vnonascii_translation_table)))
+	    ch = unibyte_char_to_multibyte (ch);
+
+	  /* Invalid characters are displayed with a special glyph.  */
+	  if (ch > MAX_CHAR)
+	    {
+	      g = !NILP (Vdos_unsupported_char_glyph)
+		? Vdos_unsupported_char_glyph
+		: MAKE_GLYPH (selected_frame, '\177',
+			      GLYPH_FACE (selected_frame, g));
+	      ch = FAST_GLYPH_CHAR (g);
+	    }
+	  if (COMPOSITE_CHAR_P (ch))
+	    {
+	      /* If CH is a composite character, we can display
+		 only the first component.  */
+	      g = cmpchar_table[COMPOSITE_CHAR_ID (ch)]->glyph[0],
+	      ch = GLYPH_CHAR (selected_frame, g);
+	      cf = FAST_GLYPH_FACE (g);
+	    }
+
+	  /* If the face of this glyph is different from the current
+	     screen face, update the screen attribute byte.  */
+	  cf = FAST_GLYPH_FACE (g);
+	  if (cf != screen_face)
+	    IT_set_face (cf);	/* handles invalid faces gracefully */
+
+	  if (GLYPH_SIMPLE_P (tbase, tlen, g))
+	    /* We generate the multi-byte form of CH in BUF.  */
+	    chlen = CHAR_STRING (ch, workbuf, buf);
+	  else
+	    {
+	      /* We have a string in Vglyph_table.  */
+	      chlen = GLYPH_LENGTH (tbase, g);
+	      buf = GLYPH_STRING (tbase, g);
+	    }
+
+	  /* If the character is not multibyte, don't bother converting it.
+	     FIXME: what about "emacs --unibyte"  */
+	  if (chlen == 1)
+	    {
+	      *conversion_buffer = (unsigned char)ch;
+	      chlen = 0;
+	      enclen = 1;
+	    }
+	  else
+	    {
+	      encode_coding (coding, buf, conversion_buffer, chlen,
+			     conversion_buffer_size);
+	      chlen -= coding->consumed;
+	      enclen = coding->produced;
+
+	      /* Replace glyph codes that cannot be converted by
+		 terminal_coding with Vdos_unsupported_char_glyph.  */
+	      if (*conversion_buffer == '?')
+		{
+		  char *cbp = conversion_buffer;
+
+		  while (cbp < conversion_buffer + enclen && *cbp == '?')
+		    *cbp++ = unsupported_char;
+		  if (unsupported_face != screen_face)
+		    IT_set_face (unsupported_face);
+		}
+	    }
+
+	  if (enclen + chlen > screen_buf_end - screen_bp)
+	    {
+	      /* The allocated buffer for screen writes is too small.
+		 Flush it and loop again without incrementing STR, so
+		 that the next loop will begin with the same glyph.  */
+	      int nbytes = screen_bp - screen_buf;
+
+	      mouse_off_maybe ();
+	      dosmemput (screen_buf, nbytes, (int)ScreenPrimary + offset);
+	      if (screen_virtual_segment)
+		dosv_refresh_virtual_screen (offset, nbytes / 2);
+	      new_pos_X += nbytes / 2;
+	      offset += nbytes;
+
+	      /* Prepare to reuse the same buffer again.  */
+	      screen_bp = screen_buf;
+	    }
+	  else
+	    {
+	      /* There's enough place in the allocated buffer to add
+		 the encoding of this glyph.  */
+
+	      /* First, copy the encoded bytes.  */
+	      for (bp = conversion_buffer; enclen--; bp++)
+		{
+		  *screen_bp++ = (unsigned char)*bp;
+		  *screen_bp++ = ScreenAttrib;
+		  if (termscript)
+		    fputc (*bp, termscript);
+		}
+
+	      /* Now copy the bytes not consumed by the encoding.  */
+	      if (chlen > 0)
+		{
+		  buf += coding->consumed;
+		  while (chlen--)
+		    {
+		      if (termscript)
+			fputc (*buf, termscript);
+		      *screen_bp++ = (unsigned char)*buf++;
+		      *screen_bp++ = ScreenAttrib;
+		    }
+		}
+
+	      /* Update STR and its remaining length.  */
+	      str++;
+	      sl--;
+	    }
+	}
     }
 
+  /* Dump whatever is left in the screen buffer.  */
   mouse_off_maybe ();
-  dosmemput (buf, 2 * len, (int)ScreenPrimary + offset);
+  dosmemput (screen_buf, screen_bp - screen_buf, (int)ScreenPrimary + offset);
   if (screen_virtual_segment)
-    dosv_refresh_virtual_screen (offset, len);
-  new_pos_X += len;
+    dosv_refresh_virtual_screen (offset, (screen_bp - screen_buf) / 2);
+  new_pos_X += (screen_bp - screen_buf) / 2;
+
+  /* We may have to output some codes to terminate the writing.  */
+  if (CODING_REQUIRE_FLUSHING (coding))
+    {
+      coding->mode |= CODING_MODE_LAST_BLOCK;
+      encode_coding (coding, "", conversion_buffer, 0, conversion_buffer_size);
+      if (coding->produced > 0)
+	{
+	  for (screen_bp = screen_buf, bp = conversion_buffer;
+	       coding->produced--; bp++)
+	    {
+	      *screen_bp++ = (unsigned char)*bp;
+	      *screen_bp++ = ScreenAttrib;
+	      if (termscript)
+		fputc (*bp, termscript);
+	    }
+	  offset += screen_bp - screen_buf;
+	  mouse_off_maybe ();
+	  dosmemput (screen_buf, screen_bp - screen_buf,
+		     (int)ScreenPrimary + offset);
+	  if (screen_virtual_segment)
+	    dosv_refresh_virtual_screen (offset, (screen_bp - screen_buf) / 2);
+	  new_pos_X += (screen_bp - screen_buf) / 2;
+	}
+    }
 }
 
 static void
@@ -710,6 +883,10 @@
   char *spaces, *sp;
   int i, j;
   int offset = 2 * (new_pos_X + screen_size_X * new_pos_Y);
+  extern int fatal_error_in_progress;
+
+  if (fatal_error_in_progress)
+    return;
 
   IT_set_face (0);
   if (termscript)
@@ -890,6 +1067,24 @@
 {
 }
 
+/* Insert and delete characters.  These are not supposed to be used
+   because we are supposed to turn off the feature of using them by
+   setting char_ins_del_ok to zero (see internal_terminal_init).  */
+static void
+IT_insert_glyphs (start, len)
+     register char *start;
+     register int len;
+{
+  abort ();
+}
+
+static void
+IT_delete_glyphs (n)
+     register int n;
+{
+  abort ();
+}
+
 /* set-window-configuration on window.c needs this.  */
 void
 x_set_menu_bar_lines (f, value, oldval)
@@ -1208,6 +1403,8 @@
   init_frame_faces (selected_frame);
 
   ring_bell_hook = IT_ring_bell;
+  insert_glyphs_hook = IT_insert_glyphs;
+  delete_glyphs_hook = IT_delete_glyphs;
   write_glyphs_hook = IT_write_glyphs;
   cursor_to_hook = raw_cursor_to_hook = IT_cursor_to;
   clear_to_end_hook = IT_clear_to_end;
@@ -1223,6 +1420,8 @@
   set_terminal_modes_hook = IT_set_terminal_modes;
   reset_terminal_modes_hook = IT_reset_terminal_modes;
   set_terminal_window_hook = IT_set_terminal_window;
+
+  char_ins_del_ok = 0;		/* just as fast to write the line */
 #endif
 }
 
@@ -3729,11 +3928,26 @@
     "List of directories to search for bitmap files for X.");
   Vx_bitmap_file_path = decode_env_path ((char *) 0, ".");
 
-  /* The following two are from xfns.c:  */
+  /* The following three are from xfns.c:  */
   Qbackground_color = intern ("background-color");
   staticpro (&Qbackground_color);
   Qforeground_color = intern ("foreground-color");
   staticpro (&Qforeground_color);
+
+  DEFVAR_BOOL ("unibyte-display-via-language-environment",
+	       &unibyte_display_via_language_environment,
+   "*Non-nil means display unibyte text according to language environment.\n\
+Specifically this means that unibyte non-ASCII characters\n\
+are displayed by converting them to the equivalent multibyte characters\n\
+according to the current language environment.  As a result, they are\n\
+displayed according to the current codepage and display table.");
+  unibyte_display_via_language_environment = 0;
+
+  DEFVAR_LISP ("dos-unsupported-char-glyph", &Vdos_unsupported_char_glyph,
+   "*Glyph to display instead of chars not supported by current codepage.\n\
+
+This variable is used only by MSDOS terminals.");
+    Vdos_unsupported_char_glyph = '\177';
 #endif
 #ifndef subprocesses
   DEFVAR_BOOL ("delete-exited-processes", &delete_exited_processes,