changeset 27395:fe54558f20d8

(turn_on_face, turn_off_face): New functions. (change_line_highlight): New prototype for new redisplay. (write_glyphs): Support multibyte text. Support faces.
author Jason Rumney <jasonr@gnu.org>
date Sun, 23 Jan 2000 03:16:02 +0000
parents 06b36e62c2b8
children 323eb9ca333f
files src/w32console.c
diffstat 1 files changed, 160 insertions(+), 83 deletions(-) [+]
line wrap: on
line diff
--- a/src/w32console.c	Sun Jan 23 03:14:51 2000 +0000
+++ b/src/w32console.c	Sun Jan 23 03:16:02 2000 +0000
@@ -1,5 +1,5 @@
 /* Terminal hooks for GNU Emacs on the Microsoft W32 API.
-   Copyright (C) 1992 Free Software Foundation, Inc.
+   Copyright (C) 1992, 1999 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -29,12 +29,18 @@
 #include <stdio.h>
 #include <windows.h>
 
+/* Disable features in headers that require a Window System for
+   console mode.  */
+#undef HAVE_WINDOW_SYSTEM
+
 #include "lisp.h"
 #include "charset.h"
+#include "coding.h"
 #include "frame.h"
 #include "disptab.h"
 #include "termhooks.h"
 #include "w32inevt.h"
+#include "dispextern.h"
 
 /* from window.c */
 extern Lisp_Object Frecenter ();
@@ -45,7 +51,7 @@
 /* from sysdep.c */
 extern int read_input_pending ();
 
-extern FRAME_PTR updating_frame;
+extern struct frame * updating_frame;
 extern int meta_key;
 
 static void move_cursor (int row, int col);
@@ -53,18 +59,20 @@
 static void clear_frame (void);
 static void clear_end_of_line (int);
 static void ins_del_lines (int vpos, int n);
-static void change_line_highlight (int, int, int);
+static void change_line_highlight (int, int, int, int);
 static void reassert_line_highlight (int, int);
-static void insert_glyphs (GLYPH *start, int len);
-static void write_glyphs (GLYPH *string, int len);
+static void insert_glyphs (struct glyph *start, int len);
+static void write_glyphs (struct glyph *string, int len);
 static void delete_glyphs (int n);
 void w32_sys_ring_bell (void);
 static void reset_terminal_modes (void);
 static void set_terminal_modes (void);
 static void set_terminal_window (int size);
-static void update_begin (FRAME_PTR f);
-static void update_end (FRAME_PTR f);
+static void update_begin (struct frame * f);
+static void update_end (struct frame * f);
 static int  hl_mode (int new_highlight);
+static void turn_on_face P_ ((struct frame *, int face_id));
+static void turn_off_face P_ ((struct frame *, int face_id));
 
 COORD	cursor_coords;
 HANDLE	prev_screen, cur_screen;
@@ -97,7 +105,7 @@
 
 /* If we're updating a frame, use it as the current frame
    Otherwise, use the selected frame.  */
-#define PICK_FRAME() (updating_frame ? updating_frame : selected_frame)
+#define PICK_FRAME() (updating_frame ? updating_frame : SELECTED_FRAME ())
 
 /* Move the cursor to (row, col).  */
 void
@@ -106,7 +114,7 @@
   cursor_coords.X = col;
   cursor_coords.Y = row;
   
-  if (updating_frame == (FRAME_PTR) NULL)
+  if (updating_frame == (struct frame *) NULL)
     {
       SetConsoleCursorPosition (cur_screen, cursor_coords);
     }
@@ -116,7 +124,7 @@
 void
 clear_to_end (void)
 {
-  FRAME_PTR f = PICK_FRAME ();
+  struct frame * f = PICK_FRAME ();
   
   clear_end_of_line (FRAME_WIDTH (f) - 1);
   ins_del_lines (cursor_coords.Y, FRAME_HEIGHT (f) - cursor_coords.Y - 1);
@@ -126,7 +134,7 @@
 void
 clear_frame (void)
 {
-  FRAME_PTR  f = PICK_FRAME ();
+  struct frame *  f = PICK_FRAME ();
   COORD	     dest;
   int        n, r;
   CONSOLE_SCREEN_BUFFER_INFO info;
@@ -146,7 +154,7 @@
 }
 
 
-static GLYPH glyph_base[256];
+static struct glyph glyph_base[256];
 static BOOL  ceol_initialized = FALSE;
 
 /* Clear from Cursor to end (what's "standout marker"?).  */
@@ -158,7 +166,7 @@
       int i;
       for (i = 0; i < 256; i++)
         {
-	  glyph_base[i] = SPACEGLYPH;	/* empty space	*/
+	  memcpy (&glyph_base[i], &space_glyph, sizeof (struct glyph));
         }
       ceol_initialized = TRUE;
     }
@@ -173,7 +181,7 @@
   SMALL_RECT scroll;
   COORD	     dest;
   CHAR_INFO  fill;
-  FRAME_PTR  f = PICK_FRAME ();
+  struct frame *  f = PICK_FRAME ();
 
   if (n < 0)
     {
@@ -260,7 +268,8 @@
 /* Call this when about to modify line at position VPOS and change whether it
    is highlighted.  */
 void
-change_line_highlight (int new_highlight, int vpos, int first_unused_hpos)
+change_line_highlight (int new_highlight, int vpos, int y, 
+                       int first_unused_hpos)
 {
   hl_mode (new_highlight);
   move_cursor (vpos, 0);
@@ -289,7 +298,7 @@
   SMALL_RECT scroll;
   COORD	     dest;
   CHAR_INFO  fill;
-  FRAME_PTR  f = PICK_FRAME ();
+  struct frame *  f = PICK_FRAME ();
   
   scroll.Top = cursor_coords.Y;
   scroll.Bottom = cursor_coords.Y;
@@ -317,7 +326,7 @@
 
 /* If start is zero insert blanks instead of a string at start ?. */
 void
-insert_glyphs (register GLYPH *start, register int len)
+insert_glyphs (register struct glyph *start, register int len)
 {
   scroll_line (len, RIGHT);
 
@@ -336,75 +345,98 @@
 }
 
 void
-write_glyphs (register GLYPH *string, register int len)
+write_glyphs (register struct glyph *string, register int len)
 {
-  register unsigned int glyph_len = GLYPH_TABLE_LENGTH;
-  Lisp_Object *glyph_table = GLYPH_TABLE_BASE;
-  FRAME_PTR f = PICK_FRAME ();
-  register char *ptr;
-  GLYPH glyph;
-  char *chars;
-  int i;
-  
-  if (len <= 0)
-    return;
+  int produced, consumed, i;
+  struct frame * f = PICK_FRAME ();
+
+  /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
+     the tail.  */
+  terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK;
 
-  chars = alloca (len * sizeof (*chars));
-  if (chars == NULL)
+  while (len > 0)
     {
-      printf ("alloca failed in write_glyphs\n");
-      return;
-    }
-  
-  /* We have to deal with the glyph indirection...go over the glyph
-     buffer and extract the characters.  */
-  ptr = chars;
-  while (--len >= 0)
-    {
-      glyph = *string++;
+      /* Identify a run of glyphs with the same face.  */
+      int face_id = string->face_id;
+      int n;
+      
+      for (n = 1; n < len; ++n)
+	if (string[n].face_id != face_id)
+	  break;
+
+      /* Turn appearance modes of the face of the run on.  */
+      turn_on_face (f, face_id);
 
-      if (glyph > glyph_len)
-        {
-	  *ptr++ = glyph & 0xFF;
-	  continue;
-	}
-      GLYPH_FOLLOW_ALIASES (glyph_table, glyph_len, glyph);
-#ifndef HAVE_NTGUI
-      if (GLYPH_FACE (fixfix, glyph) != 0)
-	printf ("Glyph face is %d\n", GLYPH_FACE (fixfix, glyph));
-#endif /* !HAVE_NTGUI */
-      if (GLYPH_SIMPLE_P (glyph_table, glyph_len, glyph))
+      while (n > 0)
         {
-	  *ptr++ = glyph & 0xFF;
-	  continue;
-	}
-      for (i = 0; i < GLYPH_LENGTH (glyph_table, glyph); i++)
-        {
-	  *ptr++ = (GLYPH_STRING (glyph_table, glyph))[i];
-	}
-    }
-  
-  /* Number of characters we have in the buffer.  */
-  len = ptr-chars;
-  
-  /* Set the attribute for these characters.  */
-  if (!FillConsoleOutputAttribute (cur_screen, char_attr, len, cursor_coords, &i))
-    {
-      printf ("Failed writing console attributes: %d\n", GetLastError ());
-      fflush (stdout);
+	  /* We use a shared conversion buffer of the current size
+	     (1024 bytes at least).  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)
+	    {
+              /* Set the attribute for these characters.  */
+              if (!FillConsoleOutputAttribute (cur_screen, char_attr,
+                                               produced, cursor_coords, &i)) 
+                {
+                  printf ("Failed writing console attributes: %d\n",
+                          GetLastError ());
+                  fflush (stdout);
+                }
+
+              /* Write the characters.  */
+              if (!WriteConsoleOutputCharacter (cur_screen, conversion_buffer,
+                                                produced, cursor_coords, &i))
+                {
+                  printf ("Failed writing console characters: %d\n",
+                          GetLastError ());
+                  fflush (stdout);
+                }
+
+              cursor_coords.X += produced;
+              move_cursor (cursor_coords.Y, cursor_coords.X);
+            }    
+          len -= consumed;
+          n -= consumed;
+          string += consumed;
+        }
+
+      /* Turn appearance modes off.  */
+      turn_off_face (f, face_id);
     }
 
-  /* Write the characters.  */
-  if (!WriteConsoleOutputCharacter (cur_screen, chars, len, cursor_coords, &i))
+  /* We may have to output some codes to terminate the writing.  */
+  if (CODING_REQUIRE_FLUSHING (&terminal_coding))
     {
-      printf ("Failed writing console characters: %d\n", GetLastError ());
-      fflush (stdout);
+      terminal_coding.mode |= CODING_MODE_LAST_BLOCK;
+      encode_coding (&terminal_coding, "", conversion_buffer,
+		     0, conversion_buffer_size);
+      if (terminal_coding.produced > 0)
+        {
+          if (!FillConsoleOutputAttribute (cur_screen, char_attr,
+                                           terminal_coding.produced,
+                                           cursor_coords, &i)) 
+            {
+              printf ("Failed writing console attributes: %d\n",
+                      GetLastError ());
+              fflush (stdout);
+            }
+
+          /* Write the characters.  */
+          if (!WriteConsoleOutputCharacter (cur_screen, conversion_buffer,
+                                            produced, cursor_coords, &i))
+            {
+              printf ("Failed writing console characters: %d\n",
+                      GetLastError ());
+              fflush (stdout);
+            }
+        }
     }
-  
-  cursor_coords.X += len;
-  move_cursor (cursor_coords.Y, cursor_coords.X);
 }
 
+
 void
 delete_glyphs (int n)
 {
@@ -499,12 +531,12 @@
    
    we'll start with not moving the cursor while an update is in progress.  */
 void
-update_begin (FRAME_PTR f)
+update_begin (struct frame * f)
 {
 }
 
 void
-update_end (FRAME_PTR f)
+update_end (struct frame * f)
 {
   SetConsoleCursorPosition (cur_screen, cursor_coords);
 }
@@ -514,6 +546,50 @@
 {
 }
 
+/***********************************************************************
+				Faces
+ ***********************************************************************/
+
+
+/* Turn appearances of face FACE_ID on tty frame F on.  */
+
+static void
+turn_on_face (f, face_id)
+     struct frame *f;
+     int face_id;
+{
+  struct face *face = FACE_FROM_ID (f, face_id);
+
+  xassert (face != NULL);
+
+  char_attr = char_attr_normal;
+
+  if (face->foreground != FACE_TTY_DEFAULT_COLOR)
+    char_attr = (char_attr & 0xf0) + face->foreground;
+
+  if (face->background != FACE_TTY_DEFAULT_COLOR)
+    char_attr = (face->background << 4) + char_attr & 0x0f;
+
+  if (face->tty_reverse_p)
+    char_attr = ((char_attr & 0x0f) << 4) + ((char_attr & 0xf0) >> 4);
+
+  /* Ensure readability */
+  if (((char_attr & 0xf0) >> 4) == (char_attr * 0x0f))
+    char_attr ^= 0x0f;
+}
+
+
+/* Turn off appearances of face FACE_ID on tty frame F.  */
+
+static void
+turn_off_face (f, face_id)
+     struct frame *f;
+     int face_id;
+{
+  if (hl_mode (0))
+    hl_mode (1);
+}
+  
 typedef int (*term_hook) ();
 
 void
@@ -541,6 +617,7 @@
   
   read_socket_hook = w32_console_read_socket;
   mouse_position_hook = w32_console_mouse_position;
+  estimate_mode_line_height_hook = 0;
 
   /* Initialize interrupt_handle.  */
   init_crit ();
@@ -612,16 +689,16 @@
 
   if (w32_use_full_screen_buffer)
     {
-      FRAME_HEIGHT (selected_frame) = info.dwSize.Y;	/* lines per page */
-      SET_FRAME_WIDTH (selected_frame, info.dwSize.X);  /* characters per line */
+      FRAME_HEIGHT (SELECTED_FRAME ()) = info.dwSize.Y;	/* lines per page */
+      SET_FRAME_WIDTH (SELECTED_FRAME (), info.dwSize.X);  /* characters per line */
     }
   else
     {
       /* Lines per page.  Use buffer coords instead of buffer size.  */
-      FRAME_HEIGHT (selected_frame) = 1 + info.srWindow.Bottom - 
+      FRAME_HEIGHT (SELECTED_FRAME ()) = 1 + info.srWindow.Bottom - 
 	info.srWindow.Top; 
       /* Characters per line.  Use buffer coords instead of buffer size.  */
-      SET_FRAME_WIDTH (selected_frame, 1 + info.srWindow.Right - 
+      SET_FRAME_WIDTH (SELECTED_FRAME (), 1 + info.srWindow.Right - 
 		       info.srWindow.Left);
     }
 }
@@ -654,7 +731,7 @@
 
 #ifndef HAVE_NTGUI
 void
-pixel_to_glyph_coords (FRAME_PTR f, int pix_x, int pix_y, int *x, int *y,
+pixel_to_glyph_coords (struct frame * f, int pix_x, int pix_y, int *x, int *y,
 		      void *bounds, int noclip)
 {
   *x = pix_x;
@@ -662,7 +739,7 @@
 }
 
 void
-glyph_to_pixel_coords (FRAME_PTR f, int x, int y, int *pix_x, int *pix_y)
+glyph_to_pixel_coords (struct frame * f, int x, int y, int *pix_x, int *pix_y)
 {
   *pix_x = x;
   *pix_y = y;