changeset 28369:3fb90cd81d3b

(w32_read_socket): Handle WM_MENUSELECT message. (Vw32_charset_to_codepage_alist): Removed. (Vw32_charset_info_alist): New variable. (Qw32_charset_[ansi, default, symbol, shiftjis, hangul, gb2312, chinesebig5, oem, easteurope, turkish, baltic, russian, arabic, greek, hebrew, thai, johab, mac, unicode]): New symbols. (x_produce_glyphs): Remove out of date #ifdef 0'd section. Replace with TODO comment. (w32_codepage_for_font): Use Vw32_charset_info_alist. (syms_of_w32term): Remove Vw32_charset_to_codepage_alist. Define Vw32_charset_info_alist and w32_charset symbols.
author Jason Rumney <jasonr@gnu.org>
date Mon, 27 Mar 2000 20:19:49 +0000
parents 43835d5a94be
children b445e32d5a7a
files src/w32term.c
diffstat 1 files changed, 256 insertions(+), 416 deletions(-) [+]
line wrap: on
line diff
--- a/src/w32term.c	Mon Mar 27 19:55:38 2000 +0000
+++ b/src/w32term.c	Mon Mar 27 20:19:49 2000 +0000
@@ -24,7 +24,6 @@
 #include <stdlib.h>
 #include "lisp.h"
 #include "charset.h"
-#include "fontset.h"
 #include "blockinput.h"
 
 #include "w32heap.h"
@@ -43,6 +42,7 @@
 
 #include "frame.h"
 #include "dispextern.h"
+#include "fontset.h"
 #include "termhooks.h"
 #include "termopts.h"
 #include "termchar.h"
@@ -174,6 +174,8 @@
 
 extern void free_frame_menubar ();
 
+extern void w32_menu_display_help (HMENU menu, UINT menu_item, UINT flags);
+
 extern Lisp_Object Vwindow_system;
 
 #define x_any_window_to_frame x_window_to_frame
@@ -287,7 +289,7 @@
 Time last_mouse_movement_time;
 
 /* Associative list linking character set strings to Windows codepages. */
-Lisp_Object Vw32_charset_to_codepage_alist;
+Lisp_Object Vw32_charset_info_alist;
 
 /* Incremented by w32_read_socket whenever it really tries to read events.  */
 #ifdef __STDC__
@@ -392,6 +394,32 @@
 
 static Lisp_Object Qvendor_specific_keysyms;
 
+Lisp_Object Qw32_charset_ansi;
+Lisp_Object Qw32_charset_default;
+Lisp_Object Qw32_charset_symbol;
+Lisp_Object Qw32_charset_shiftjis;
+Lisp_Object Qw32_charset_hangul;
+Lisp_Object Qw32_charset_gb2312;
+Lisp_Object Qw32_charset_chinesebig5;
+Lisp_Object Qw32_charset_oem;
+
+#ifdef JOHAB_CHARSET
+Lisp_Object Qw32_charset_easteurope;
+Lisp_Object Qw32_charset_turkish;
+Lisp_Object Qw32_charset_baltic;
+Lisp_Object Qw32_charset_russian;
+Lisp_Object Qw32_charset_arabic;
+Lisp_Object Qw32_charset_greek;
+Lisp_Object Qw32_charset_hebrew;
+Lisp_Object Qw32_charset_thai;
+Lisp_Object Qw32_charset_johab;
+Lisp_Object Qw32_charset_mac;
+#endif
+
+#ifdef UNICODE_CHARSET
+Lisp_Object Qw32_charset_unicode;
+#endif
+
 
 #if 0
 /* This is a function useful for recording debugging information
@@ -1046,7 +1074,8 @@
 
 static struct face *x_get_glyph_face_and_encoding P_ ((struct frame *,
 						       struct glyph *,
-						       wchar_t *));
+						       wchar_t *,
+                                                       int *));
 static struct face *x_get_char_face_and_encoding P_ ((struct frame *, int,
 						      int, wchar_t *, int));
 static XCharStruct *w32_per_char_metric P_ ((HDC hdc, XFontStruct *,
@@ -1072,6 +1101,8 @@
  ((ch) & 0x00ff)
 
 
+/* NTEMACS_TODO: Add support for bdf fonts back in. */
+
 /* Get metrics of character CHAR2B in FONT.  Value is always non-null.
    If CHAR2B is not contained in FONT, the font's default character
    metric is returned. If unicode_p is non-zero, use unicode functions,
@@ -1134,6 +1165,12 @@
   pcm->ascent = FONT_BASE (font);
   pcm->descent = FONT_DESCENT (font);
 
+  if (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0)
+    {
+      xfree (pcm);
+      pcm = NULL;
+    }
+
   return pcm;
 }
 
@@ -1246,12 +1283,8 @@
       /* Unibyte case.  We don't have to encode, but we have to make
 	 sure to use a face suitable for unibyte.  */
       *char2b = BUILD_WCHAR_T (0, c);
-      
-      if (!FACE_SUITABLE_FOR_CHARSET_P (face, -1))
-	{
-	  face_id = FACE_FOR_CHARSET (f, face_id, -1);
-	  face = FACE_FROM_ID (f, face_id);
-	}
+      face_id = FACE_FOR_CHAR (f, face, c);
+      face = FACE_FROM_ID (f, face_id);
     }
   else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
     {
@@ -1269,32 +1302,14 @@
 	*char2b = BUILD_WCHAR_T (c1, c2);
       else
 	*char2b = BUILD_WCHAR_T (0, c1);
-
-      /* Get the face for displaying C.  If `face' is not suitable for
-	 charset, get the one that fits.  (This can happen for the
-	 translations of a composition where the glyph
-	 specifies a face for the first component, but the other
-         components have a different charset.)  */
-      if (!FACE_SUITABLE_FOR_CHARSET_P (face, charset))
-	{
-	  face_id = FACE_FOR_CHARSET (f, face_id, charset);
-	  face = FACE_FROM_ID (f, face_id);
-	}
   
       /* Maybe encode the character in *CHAR2B.  */
-      if (charset != CHARSET_ASCII)
+      if (face->font != NULL)
 	{
 	  struct font_info *font_info
 	    = FONT_INFO_FROM_ID (f, face->font_info_id);
 	  if (font_info)
-	    {
 	      x_encode_char (c, char2b, font_info);
-#if 0 /* NTEMACS_TODO: Isn't this undoing what we just did?  Investigate. */
-	      if (charset == charset_latin_iso8859_1)
-                *char2b = BUILD_WCHAR_T (BYTE1 (*char2b),
-                                         BYTE2 (*char2b) | 0x80);
-#endif
-	    }
 	}
     }
 
@@ -1306,21 +1321,34 @@
 }
 
 
+/* Determine if a font is double byte. */
+int w32_font_is_double_byte (XFontStruct *font)
+{
+  /* NTEMACS_TODO: Determine this properly using GetFontLanguageInfo
+     or similar.  Returning 1 might work, as we use Unicode anyway. */
+  return 1;
+}
+
+
 /* Get face and two-byte form of character glyph GLYPH on frame F.
    The encoding of GLYPH->u.ch is returned in *CHAR2B.  Value is
    a pointer to a realized face that is ready for display.  */
 
 static INLINE struct face *
-x_get_glyph_face_and_encoding (f, glyph, char2b)
+x_get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
      struct frame *f;
      struct glyph *glyph;
      wchar_t *char2b;
+     int *two_byte_p;
 {
   struct face *face;
 
   xassert (glyph->type == CHAR_GLYPH);
   face = FACE_FROM_ID (f, glyph->face_id);
 
+  if (two_byte_p)
+    *two_byte_p = 0;
+
   if (!glyph->multibyte_p)
     {
       /* Unibyte case.  We don't have to encode, but we have to make
@@ -1353,11 +1381,8 @@
 	  if (font_info)
 	    {
 	      x_encode_char (glyph->u.ch, char2b, font_info);
-#if 0 /* NTEMACS_TODO: Isn't this undoing what we just did?  Investigate. */
-	      if (charset == charset_latin_iso8859_1)
-		*char2b = BUILD_WCHAR_T (BYTE1 (*char2b),
-                                         BYTE2 (*char2b) | 0x80);
-#endif
+              if (two_byte_p)
+                *two_byte_p = w32_font_is_double_byte (font_info->font);
 	    }
 	}
     }
@@ -1402,6 +1427,7 @@
       glyph->multibyte_p = it->multibyte_p;
       glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
 				      || it->phys_descent > it->descent);
+      glyph->glyph_not_available_p = it->glyph_not_available_p;
       ++it->glyph_row->used[area];
     }
 }
@@ -1748,35 +1774,48 @@
 x_produce_glyphs (it)
      struct it *it;
 {
+  it->glyph_not_available_p = 0;
+
   if (it->what == IT_CHARACTER)
     {
       wchar_t char2b;
       XFontStruct *font;
-      struct face *face;
+      struct face *face = FACE_FROM_ID (it->f, it->face_id);
       XCharStruct *pcm;
-     int font_not_found_p;
+      int font_not_found_p;
       struct font_info *font_info;
       int boff;                 /* baseline offset */
       HDC hdc;
 
       hdc = get_frame_dc (it->f);
 
-      /* Maybe translate single-byte characters to multibyte.  */
+      /* Maybe translate single-byte characters to multibyte, or the
+         other way.  */
       it->char_to_display = it->c;
-      if (unibyte_display_via_language_environment
-	  && SINGLE_BYTE_CHAR_P (it->c)
-	  && (it->c >= 0240
-	      || (it->c >= 0200
-		  && !NILP (Vnonascii_translation_table))))
-	{
-	  it->char_to_display = unibyte_char_to_multibyte (it->c);
-	  it->charset = CHAR_CHARSET (it->char_to_display);
-	}
+      if (!ASCII_BYTE_P (it->c))
+        {
+          if (unibyte_display_via_language_environment
+              && SINGLE_BYTE_CHAR_P (it->c)
+              && (it->c >= 0240
+                  || !NILP (Vnonascii_translation_table)))
+            {
+              it->char_to_display = unibyte_char_to_multibyte (it->c);
+	      it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
+	      face = FACE_FROM_ID (it->f, it->face_id);
+	    }
+	  else if (!SINGLE_BYTE_CHAR_P (it->c)
+		   && !it->multibyte_p)
+	    {
+	      it->char_to_display = multibyte_char_to_unibyte (it->c, Qnil);
+	      it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
+	      face = FACE_FROM_ID (it->f, it->face_id);
+	    }
+        }
       
-      /* Get face and font to use.  Encode IT->char_to_display.  */
-      face = x_get_char_face_and_encoding (it->f, it->char_to_display,
-					   it->face_id, &char2b,
-					   it->multibyte_p);
+      /* Get font to use.  Encode IT->char_to_display.  */
+      x_get_char_face_and_encoding (it->f, it->char_to_display,
+                                    it->face_id, &char2b,
+                                    it->multibyte_p);
       font = face->font;
 
       /* When no suitable font found, use the default font.  */
@@ -1863,6 +1902,7 @@
 	      if (pcm->lbearing < 0
 		  || pcm->rbearing > pcm->width)
 		it->glyph_row->contains_overlapping_glyphs_p = 1;
+              xfree (pcm);
 	    }
 	}
       else if (it->char_to_display == '\n')
@@ -1908,33 +1948,31 @@
              default font and calculate the width of the character
              from the charset width; this is what old redisplay code
              did.  */
-          if (font_not_found_p)
-            {
-              wchar_t dummy = BUILD_WCHAR_T (0, 'X');
-
-              /* Get some metrics for the default font.  */
-              pcm = w32_per_char_metric (hdc, font, &dummy, 0);
-
-              /* Ignore the width obtained above, and use the average
-                 width of a character in the default font. */
-              it->pixel_width = FONT_WIDTH (font)
-                * CHARSET_WIDTH (it->charset);
-            }
-          else
-            {
-              pcm = w32_per_char_metric (hdc, font, &char2b, 1);
-              it->pixel_width = pcm->width;
+          pcm = w32_per_char_metric (hdc, font, &char2b, 1);
+
+	  if (font_not_found_p || !pcm)
+	    {
+	      int charset = CHAR_CHARSET (it->char_to_display);
+
+	      it->glyph_not_available_p = 1;
+	      it->pixel_width = (FONT_WIDTH (FRAME_FONT (it->f))
+				 * CHARSET_WIDTH (charset));
+	      it->phys_ascent = FONT_BASE (font) + boff;
+	      it->phys_descent = FONT_DESCENT (font) - boff;
+	    }
+	  else
+	    {
+              it->phys_ascent = pcm->ascent + boff;
+              it->phys_descent = pcm->descent - boff;
+              if (it->glyph_row
+                  && (pcm->lbearing < 0
+                      || pcm->rbearing > pcm->width))
+                it->glyph_row->contains_overlapping_glyphs_p = 1;
             }
 
           it->nglyphs = 1;
           it->ascent = FONT_BASE (font) + boff;
           it->descent = FONT_DESCENT (font) - boff;
-          it->phys_ascent = pcm->ascent + boff;
-          it->phys_descent = pcm->descent - boff;
-          if (it->glyph_row
-              && (pcm->lbearing < 0
-                  || pcm->rbearing > pcm->width))
-            it->glyph_row->contains_overlapping_glyphs_p = 1;
 
 	  if (face->box != FACE_NO_BOX)
 	    {
@@ -1957,249 +1995,14 @@
   
 	  if (it->glyph_row)
 	    x_append_glyph (it);
+
+          xfree (pcm);
 	}
       release_frame_dc (it->f, hdc);
     }
   else if (it->what == IT_COMPOSITION)
     {
-#if 0 /* NTEMACS_TODO: Composite glyphs.  */
-      /* Note: A composition is represented as one glyph in the
-	 glyph matrix.  There are no padding glyphs.  */
-      XChar2b char2b;
-      XFontStruct *font;
-      struct face *face;
-      XCharStruct *pcm;
-      int font_not_found_p;
-      struct font_info *font_info;
-      int boff;			/* baseline offset */
-      struct composition *cmp = composition_table[it->cmp_id];
-
-      /* Maybe translate single-byte characters to multibyte.  */
-      it->char_to_display = it->c;
-      if (unibyte_display_via_language_environment
-	  && SINGLE_BYTE_CHAR_P (it->c)
-	  && (it->c >= 0240
-	      || (it->c >= 0200
-		  && !NILP (Vnonascii_translation_table))))
-	{
-	  it->char_to_display = unibyte_char_to_multibyte (it->c);
-	  it->charset = CHAR_CHARSET (it->char_to_display);
-	}
-      
-      /* Get face and font to use.  Encode IT->char_to_display.  */
-      face = x_get_char_face_and_encoding (it->f, it->char_to_display,
-					   it->face_id, &char2b,
-					   it->multibyte_p);
-      font = face->font;
-
-      /* When no suitable font found, use the default font.  */
-      font_not_found_p = font == NULL;
-      if (font_not_found_p)
-	{
-	  font = FRAME_FONT (it->f);
-	  boff = it->f->output_data.x->baseline_offset;
-	  font_info = NULL;
-	}
-      else
-	{
-	  font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
-	  boff = font_info->baseline_offset;
-	  if (font_info->vertical_centering)
-	    boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
-	}
-
-      /* There are no padding glyphs, so there is only one glyph to
-	 produce for the composition.  Important is that pixel_width,
-	 ascent and descent are the values of what is drawn by
-	 draw_glyphs (i.e. the values of the overall glyphs composed).  */
-      it->nglyphs = 1;
-
-      /* If we have not yet calculated pixel size data of glyphs of
-	 the composition for the current face font, calculate them
-	 now.  Theoretically, we have to check all fonts for the
-	 glyphs, but that requires much time and memory space.  So,
-	 here we check only the font of the first glyph.  This leads
-	 to incorrect display very rarely, and C-l (recenter) can
-	 correct the display anyway.  */
-      if (cmp->font != (void *) font)
-	{
-	  /* Ascent and descent of the font of the first character of
-	     this composition (adjusted by baseline offset).  Ascent
-	     and descent of overall glyphs should not be less than
-	     them respectively.  */
-	  int font_ascent = font->ascent + boff;
-	  int font_descent = font->descent - boff;
-	  /* Bounding box of the overall glyphs.  */
-	  int leftmost, rightmost, lowest, highest;
-	  int i;
-
-	  cmp->font = (void *) font;
-
-	  /* Initialize the bounding box.  */
-	  pcm = x_per_char_metric (font, &char2b);
-	  leftmost = 0;
-	  rightmost = pcm->width;
-	  lowest = - pcm->descent + boff;
-	  highest = pcm->ascent + boff;
-	  if (font_info
-	      && font_info->default_ascent
-	      && CHAR_TABLE_P (Vuse_default_ascent)
-	      && !NILP (Faref (Vuse_default_ascent,
-			       make_number (it->char_to_display))))
-	    highest = font_info->default_ascent + boff;
-
-	  /* Draw the first glyph at the normal position.  It may be
-	     shifted to right later if some other glyphs are drawn at
-	     the left.  */
-	  cmp->offsets[0] = 0;
-	  cmp->offsets[1] = boff;
-
-	  /* Set cmp->offsets for the remaining glyphs.  */
-	  for (i = 1; i < cmp->glyph_len; i++)
-	    {
-	      int left, right, btm, top;
-	      int ch = COMPOSITION_GLYPH (cmp, i);
-
-	      face = x_get_char_face_and_encoding (it->f, ch,
-						   it->face_id, &char2b,
-						   it->multibyte_p);
-	      font = face->font;
-	      if (font == NULL)
-		{
-		  font = FRAME_FONT (it->f);
-		  boff = it->f->output_data.x->baseline_offset;
-		  font_info = NULL;
-		}
-	      else
-		{
-		  font_info
-		    = FONT_INFO_FROM_ID (it->f, face->font_info_id);
-		  boff = font_info->baseline_offset;
-		  if (font_info->vertical_centering)
-		    boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
-		}
-
-	      pcm = x_per_char_metric (font, &char2b);
-
-	      if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
-		{
-		  /* Relative composition with or without
-		     alternate chars.  */
-		  left = (leftmost + rightmost - pcm->width) / 2;
-		  btm = - pcm->descent + boff;
-		  if (font_info && font_info->relative_compose
-		      && (! CHAR_TABLE_P (Vignore_relative_composition)
-			  || NILP (Faref (Vignore_relative_composition,
-					  make_number (ch)))))
-		    {
-
-		      if (- pcm->descent
-			  >= font_info->relative_compose)
-			/* One extra pixel between two glyphs.  */
-			btm = highest + 1;
-		      else if (pcm->ascent <= 0)
-			/* One extra pixel between two glyphs.  */
-			btm = lowest - 1 - pcm->ascent - pcm->descent;
-		    }
-		}
-	      else
-		{
-		  /* A composition rule is specified by an integer
-		     value that encodes global and new reference
-		     points (GREF and NREF).  GREF and NREF are
-		     specified by numbers as below:
-
-			0---1---2 -- ascent
-			|       |
-			|       |
-			|       |
-			9--10--11 -- center
-			|       |
-		     ---3---4---5--- baseline
-			|       |
-			6---7---8 -- descent
-		  */
-		  int rule = COMPOSITION_RULE (cmp, i);
-		  int gref, nref, grefx, grefy, nrefx, nrefy;
-
-		  COMPOSITION_DECODE_RULE (rule, gref, nref);
-		  grefx = gref % 3, nrefx = nref % 3;
-		  grefy = gref / 3, nrefy = nref / 3;
-
-		  left = (leftmost
-			  + grefx * (rightmost - leftmost) / 2
-			  - nrefx * pcm->width / 2);
-		  btm = ((grefy == 0 ? highest
-			  : grefy == 1 ? 0
-			  : grefy == 2 ? lowest
-			  : (highest + lowest) / 2)
-			 - (nrefy == 0 ? pcm->ascent + pcm->descent
-			    : nrefy == 1 ? pcm->descent - boff
-			    : nrefy == 2 ? 0
-			    : (pcm->ascent + pcm->descent) / 2));
-		}
-
-	      cmp->offsets[i * 2] = left;
-	      cmp->offsets[i * 2 + 1] = btm + pcm->descent;
-
-	      /* Update the bounding box of the overall glyphs. */
-	      right = left + pcm->width;
-	      top = btm + pcm->descent + pcm->ascent;
-	      if (left < leftmost)
-		leftmost = left;
-	      if (right > rightmost)
-		rightmost = right;
-	      if (top > highest)
-		highest = top;
-	      if (btm < lowest)
-		lowest = btm;
-	    }
-
-	  /* If there are glyphs whose x-offsets are negative,
-	     shift all glyphs to the right and make all x-offsets
-	     non-negative.  */
-	  if (leftmost < 0)
-	    {
-	      for (i = 0; i < cmp->glyph_len; i++)
-		cmp->offsets[i * 2] -= leftmost;
-	      rightmost -= leftmost;
-	    }
-
-	  cmp->pixel_width = rightmost;
-	  cmp->ascent = highest;
-	  cmp->descent = - lowest;
-	  if (cmp->ascent < font_ascent)
-	    cmp->ascent = font_ascent;
-	  if (cmp->descent < font_descent)
-	    cmp->descent = font_descent;
-	}
-
-      it->pixel_width = cmp->pixel_width;
-      it->ascent = it->phys_ascent = cmp->ascent;
-      it->descent = it->phys_descent = cmp->descent;
-
-      if (face->box != FACE_NO_BOX)
-	{
-	  int thick = face->box_line_width;
-	  it->ascent += thick;
-	  it->descent += thick;
-	  
-	  if (it->start_of_box_run_p)
-	    it->pixel_width += thick;
-	  if (it->end_of_box_run_p)
-	    it->pixel_width += thick;
-	}
-  
-      /* If face has an overline, add the height of the overline
-	 (1 pixel) and a 1 pixel margin to the character height.  */
-      if (face->overline_p)
-	it->ascent += 2;
-
-      take_vertical_position_into_account (it);
-  
-      if (it->glyph_row)
-	x_append_composite_glyph (it);
-#endif
+      /* NTEMACS_TODO: Composite glyphs.  */
     }
   else if (it->what == IT_IMAGE)
     x_produce_image_glyph (it);
@@ -2233,7 +2036,7 @@
   if (FRAME_FACE_CACHE (f))
       {
 	struct face *face = FACE_FROM_ID (f, face_id);
-	if (face)
+	if (face && face->font)
 	  height = FONT_HEIGHT (face->font) + 2 * face->box_line_width;
       }
   
@@ -2270,9 +2073,8 @@
         *end = '\0';
       }
 
-  codepage = Fcdr (Fassoc (build_string(charset),
-                           Vw32_charset_to_codepage_alist));
-
+  codepage = Fcdr (Fcdr (Fassoc (build_string(charset),
+                                 Vw32_charset_info_alist)));
   if (INTEGERP (codepage))
     return XINT (codepage);
   else
@@ -2349,9 +2151,6 @@
   wchar_t *char2b;
   int nchars;
 
-  /* Character set of this glyph string.  */
-  int charset;
-
   /* A face-override for drawing cursors, mouse face and similar.  */
   enum draw_glyphs_face hl;
 
@@ -2422,16 +2221,16 @@
      wchar_t * chars;
      int nchars;
 {
-  int charset_dim = CHARSET_DIMENSION (s->charset);
-
+  /* NTEMACS_TODO: Find way to figure out charset_dim. */
+  /*  int charset_dim = CHARSET_DIMENSION (s->charset); */
   if (s->gc->font->bdf)
     w32_BDF_TextOut (s->gc->font->bdf, s->hdc,
-                     x, y, (char *) chars, charset_dim, nchars, 0);
+                     x, y, (char *) chars, 1 /* charset_dim */, nchars, 0);
   else if (s->two_byte_p)
     ExtTextOutW (s->hdc, x, y, 0, NULL, chars, nchars, NULL);
   else
     ExtTextOut (s->hdc, x, y, 0, NULL, (char *) chars,
-                nchars * charset_dim, NULL);
+                nchars /* * charset_dim */, NULL);
 }
 
 #if 0
@@ -2634,10 +2433,12 @@
      struct glyph_string *s;
 {     
   int face_id;
+  struct face *face;
 
   /* What face has to be used for the mouse face?  */
   face_id = FRAME_W32_DISPLAY_INFO (s->f)->mouse_face_face_id;
-  face_id = FACE_FOR_CHARSET (s->f, face_id, s->charset);
+  face = FACE_FROM_ID (s->f, face_id);
+  face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
   s->face = FACE_FROM_ID (s->f, face_id);
   PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
 
@@ -2887,19 +2688,19 @@
       struct face *face;
       struct font_info *font_info;
       wchar_t char2b;
-      
-      face = x_get_glyph_face_and_encoding (f, glyph, &char2b);
+      XCharStruct *pcm;
+
+      face = x_get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
       font = face->font;
       font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
-      if (font)
+      if (font
+          && (pcm = w32_per_char_metric (hdc, font, &char2b, unicode_p)))
 	{
-	  XCharStruct *pcm = w32_per_char_metric (hdc, font, &char2b,
-                                                  unicode_p);
-
 	  if (pcm->rbearing > pcm->width)
 	    *right = pcm->rbearing - pcm->width;
 	  if (pcm->lbearing < 0)
 	    *left = -pcm->lbearing;
+          xfree (pcm);
 	}
     }
 }
@@ -3228,6 +3029,9 @@
                       max (0, min (0xff, delta + GetGValue (*color))),
                       max (0, min (0xff, delta + GetBValue (*color))));
 
+  /* NTEMACS_TODO: Map to palette and retry with delta if same? */
+  /* NTEMACS_TODO: Free colors (if using palette)? */
+
   if (new == *color)
     return 0;
 
@@ -3259,6 +3063,8 @@
   COLORREF background = di->relief_background;
   struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
 
+  /* NTEMACS_TODO: Free colors (if using palette)? */
+
   /* Allocate new color.  */
   xgcv.foreground = default_pixel;
   pixel = background;
@@ -4125,6 +3931,7 @@
 {
   struct glyph *glyph, *last;
   int voffset;
+  int glyph_not_available_p;
 
   xassert (s->f == XFRAME (s->w->frame));
   xassert (s->nchars == 0);
@@ -4135,18 +3942,22 @@
   glyph = s->row->glyphs[s->area] + start;
   last = s->row->glyphs[s->area] + end;
   voffset = glyph->voffset;
-  
+
+  glyph_not_available_p = glyph->glyph_not_available_p;
+
   while (glyph < last
 	 && glyph->type == CHAR_GLYPH
 	 && glyph->voffset == voffset
-	 /* Same face id implies same charset, nowadays.  */
-	 && glyph->face_id == face_id)
-    {
+	 /* Same face id implies same font, nowadays.  */
+	 && glyph->face_id == face_id
+         && glyph->glyph_not_available_p == glyph_not_available_p)
+    {
+      int two_byte_p;
+
       s->face = x_get_glyph_face_and_encoding (s->f, glyph,
-					       s->char2b + s->nchars);
-      if (BYTE2(s->char2b[s->nchars]) != 0)
-	s->two_byte_p = 1;
-      
+					       s->char2b + s->nchars,
+                                               &two_byte_p);
+      s->two_byte_p = two_byte_p;
       ++s->nchars;
       xassert (s->nchars <= end - start);
       s->width += glyph->pixel_width;
@@ -4160,7 +3971,7 @@
      but record the fact that we couldn't load it in
      S->font_not_found_p so that we can draw rectangles for the
      characters of the glyph string.  */
-  if (s->font == NULL)
+  if (s->font == NULL || glyph_not_available_p)
     {
       s->font_not_found_p = 1;
       s->font = FRAME_FONT (s->f);
@@ -4337,13 +4148,11 @@
 	 wchar_t *char2b;						   \
 									   \
 	 c = (ROW)->glyphs[AREA][START].u.ch;				   \
-	 charset = CHAR_CHARSET (c);					   \
 	 face_id = (ROW)->glyphs[AREA][START].face_id;			   \
 	 s = (struct glyph_string *) alloca (sizeof *s);		   \
 	 char2b = (wchar_t *) alloca ((END - START) * sizeof *char2b);	   \
 	 w32_init_glyph_string (s, hdc, char2b, W, ROW, AREA, START, HL);  \
 	 x_append_glyph_string (&HEAD, &TAIL, s);			   \
-	 s->charset = charset;						   \
 	 s->x = (X);							   \
 	 START = x_fill_glyph_string (s, face_id, START, END,		   \
                                           OVERLAPS_P);			   \
@@ -4364,6 +4173,7 @@
   do {									  \
     int cmp_id = (ROW)->glyphs[AREA][START].u.cmp_id;			  \
     int face_id = (ROW)->glyphs[AREA][START].face_id;			  \
+    struct face *base_face = FACE_FROM_ID (XFRAME (w->frame), face_id);	  \
     struct composition *cmp = composition_table[cmp_id];		  \
     int glyph_len = cmp->glyph_len;					  \
     wchar_t *char2b;							  \
@@ -4371,14 +4181,17 @@
     struct glyph_string *first_s = NULL;				  \
     int n;								  \
     									  \
+    base_face = base_face->ascii_face;					  \
     char2b = (wchar_t *) alloca ((sizeof *char2b) * glyph_len);		  \
     faces = (struct face **) alloca ((sizeof *faces) * glyph_len);	  \
     /* At first, fill in `char2b' and `faces'.  */			  \
     for (n = 0; n < glyph_len; n++)					  \
       {									  \
 	int c = COMPOSITION_GLYPH (cmp, n);				  \
-	faces[n] = x_get_char_face_and_encoding (XFRAME (w->frame), c,	  \
-						 face_id, char2b + n, 1); \
+	int this_face_id = FACE_FOR_CHAR (XFRAME (w->frame), base_face, c); \
+	faces[n] = FACE_FROM_ID (XFRAME (w->frame), this_face_id);	  \
+	x_get_char_face_and_encoding (XFRAME (w->frame), c,		  \
+				      this_face_id, char2b + n, 1);	  \
       }									  \
     									  \
     /* Make glyph_strings for each glyph sequence that is drawable by	  \
@@ -4390,7 +4203,6 @@
 	x_append_glyph_string (&(HEAD), &(TAIL), s);			  \
 	s->cmp = cmp;							  \
 	s->gidx = n;							  \
-	s->charset = 0;							  \
 	s->x = (X);							  \
 									  \
 	if (n == 0)							  \
@@ -6025,7 +5837,7 @@
   if (popup_activated ())
     return;
 
-  if (disable_mouse_highlight)
+  if (disable_mouse_highlight || !f->glyphs_initialized_p)
     return;
 
   dpyinfo->mouse_face_mouse_x = x;
@@ -7900,6 +7712,16 @@
             }
 	  break;
 
+        case WM_MENUSELECT:
+          {
+            HMENU menu = (HMENU) msg.msg.lParam;
+            UINT menu_item = (UINT) LOWORD (msg.msg.wParam);
+            UINT flags = (UINT) HIWORD (msg.msg.wParam);
+ 
+            w32_menu_display_help (menu, menu_item, flags);
+          }
+          break;
+
 	case WM_DROPFILES:
 	  f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
 
@@ -8818,8 +8640,7 @@
      register char *fontname;
 {
   struct font_info *fontp
-    = fs_load_font (f, FRAME_W32_FONT_TABLE (f), CHARSET_ASCII,
-                    fontname, -1);
+    = FS_LOAD_FONT (f, 0, fontname, -1);
 
   if (!fontp)
     return Qnil;
@@ -8861,9 +8682,9 @@
      struct frame *f;
      char *fontsetname;
 {
-  int fontset = fs_query_fontset (f, fontsetname);
-  struct fontset_info *fontsetp;
+  int fontset = fs_query_fontset (build_string (fontsetname), 0);
   Lisp_Object result;
+  char *fontname;
 
   if (fontset < 0)
     return Qnil;
@@ -8871,15 +8692,9 @@
   if (FRAME_FONTSET (f) == fontset)
     /* This fontset is already set in frame F.  There's nothing more
        to do.  */
-    return build_string (fontsetname);
-
-  fontsetp = FRAME_FONTSET_DATA (f)->fontset_table[fontset];
-
-  if (!fontsetp->fontname[CHARSET_ASCII])
-    /* This fontset doesn't contain ASCII font.  */
-    return Qnil;
-
-  result = x_new_font (f, fontsetp->fontname[CHARSET_ASCII]);
+    return fontset_name (fontset);
+
+  result = x_new_font (f, (XSTRING (fontset_ascii (fontset))->data));
 
   if (!STRINGP (result))
     /* Can't load ASCII font.  */
@@ -8887,8 +8702,6 @@
 
   /* Since x_new_font doesn't update any fontset information, do it now.  */
   FRAME_FONTSET(f) = fontset;
-  FS_LOAD_FONT (f, FRAME_W32_FONT_TABLE (f),
-		CHARSET_ASCII, XSTRING (result)->data, fontset);
 
   return build_string (fontsetname);
 }
@@ -9901,64 +9714,91 @@
 affect on NT machines.");
   w32_enable_unicode_output = 1;
 
-  DEFVAR_LISP ("w32-charset-to-codepage-alist",
-               &Vw32_charset_to_codepage_alist,
-               "Alist linking character sets to Windows Codepages.");
-  Vw32_charset_to_codepage_alist = Qnil;
-  /* Initialise the alist with some defaults.  */
-  XSETFASTINT (codepage, 936);
-  store_in_alist (&Vw32_charset_to_codepage_alist,
-                  build_string ("gb2312"), codepage);
-  XSETFASTINT (codepage, 950);
-  store_in_alist (&Vw32_charset_to_codepage_alist,
-                  build_string ("big5"), codepage);
-  XSETFASTINT (codepage, 949);
-  store_in_alist (&Vw32_charset_to_codepage_alist,
-                  build_string ("ksc5601.1987"), codepage);
-  XSETFASTINT (codepage, 1361);
-  store_in_alist (&Vw32_charset_to_codepage_alist,
-                  build_string ("ksc5601.1992"), codepage);
-  XSETFASTINT (codepage, 932);
-  store_in_alist (&Vw32_charset_to_codepage_alist,
-                  build_string ("jisx0208-sjis"), codepage);
-  XSETFASTINT (codepage, 874);
-  store_in_alist (&Vw32_charset_to_codepage_alist,
-                  build_string ("tis620"), codepage);
-  XSETFASTINT (codepage, 20866);
-  store_in_alist (&Vw32_charset_to_codepage_alist,
-                  build_string ("koi8-r"), codepage);
-  /* iso8859-13 is not yet officially adopted, but it is conveniently
-     covered by CP 1257.  */
-  XSETFASTINT (codepage, 1257);
-  store_in_alist (&Vw32_charset_to_codepage_alist,
-                  build_string ("iso8859-13"), codepage);
-  XSETFASTINT (codepage, 1254);
-  store_in_alist (&Vw32_charset_to_codepage_alist,
-                  build_string ("iso8859-9"), codepage);
-  XSETFASTINT (codepage, 1255);
-  store_in_alist (&Vw32_charset_to_codepage_alist,
-                  build_string ("iso8859-8"), codepage);
-  XSETFASTINT (codepage, 28597);
-  store_in_alist (&Vw32_charset_to_codepage_alist,
-                  build_string ("iso8859-7"), codepage);
-  XSETFASTINT (codepage, 28596);
-  store_in_alist (&Vw32_charset_to_codepage_alist,
-                  build_string ("iso8859-6"), codepage);
-  XSETFASTINT (codepage, 28595);
-  store_in_alist (&Vw32_charset_to_codepage_alist,
-                  build_string ("iso8859-5"), codepage);
-  XSETFASTINT (codepage, 28594);
-  store_in_alist (&Vw32_charset_to_codepage_alist,
-                  build_string ("iso8859-4"), codepage);
-  XSETFASTINT (codepage, 28593);
-  store_in_alist (&Vw32_charset_to_codepage_alist,
-                  build_string ("iso8859-3"), codepage);
-  XSETFASTINT (codepage, 28592);
-  store_in_alist (&Vw32_charset_to_codepage_alist,
-                  build_string ("iso8859-2"), codepage);
-  XSETFASTINT (codepage, 1252);
-  store_in_alist (&Vw32_charset_to_codepage_alist,
-                  build_string ("iso8859-1"), codepage);
+/* VIETNAMESE_CHARSET is not defined in some versions of MSVC.  */
+#ifndef VIETNAMESE_CHARSET
+#define VIETNAMESE_CHARSET 163
+#endif
+
+  DEFVAR_LISP ("w32-charset-info-alist",
+               &Vw32_charset_info_alist,
+               "Alist linking Emacs character sets to Windows fonts\n\
+and codepages. Each entry should be of the form:\n\
+\n\
+   (CHARSET_NAME . (WINDOWS_CHARSET . CODEPAGE))\n\
+\n\
+where CHARSET_NAME is a string used in font names to identify the charset,\n\
+WINDOWS_CHARSET is a symbol that can be one of:\n\
+w32-charset-ansi, w32-charset-default, w32-charset-symbol,\n\
+w32-charset-shiftjis, w32-charset-hangul, w32-charset-gb2312,\n\
+w32-charset-chinesebig5, "
+#ifdef JOHAB_CHARSET
+"w32-charset-johab, w32-charset-hebrew,\n\
+w32-charset-arabic, w32-charset-greek, w32-charset-turkish,\n\
+w32-charset-vietnamese, w32-charset-thai, w32-charset-easteurope,\n\
+w32-charset-russian, w32-charset-mac, w32-charset-baltic,\n"
+#endif
+#ifdef UNICODE_CHARSET
+"w32-charset-unicode, "
+#endif
+"or w32-charset-oem.\n\
+CODEPAGE should be an integer specifying the codepage that should be used\n\
+to display the character set, t to do no translation and output as Unicode,\n\
+or nil to do no translation and output as 8 bit (or multibyte on far-east\n\
+versions of Windows) characters.");
+    Vw32_charset_info_alist = Qnil;
+
+  staticpro (&Qw32_charset_ansi);
+  Qw32_charset_ansi = intern ("w32-charset-ansi");
+  staticpro (&Qw32_charset_symbol);
+  Qw32_charset_symbol = intern ("w32-charset-symbol");
+  staticpro (&Qw32_charset_shiftjis);
+  Qw32_charset_shiftjis = intern ("w32-charset-shiftjis");
+  staticpro (&Qw32_charset_hangul);
+  Qw32_charset_hangul = intern ("w32-charset-hangul");
+  staticpro (&Qw32_charset_chinesebig5);
+  Qw32_charset_chinesebig5 = intern ("w32-charset-chinesebig5");
+  staticpro (&Qw32_charset_gb2312);
+  Qw32_charset_gb2312 = intern ("w32-charset-gb2312");
+  staticpro (&Qw32_charset_oem);
+  Qw32_charset_oem = intern ("w32-charset-oem");
+
+#ifdef JOHAB_CHARSET
+  {
+    static int w32_extra_charsets_defined = 1;
+    DEFVAR_BOOL ("w32-extra-charsets-defined", w32_extra_charsets_defined, "");
+
+    staticpro (&Qw32_charset_johab);
+    Qw32_charset_johab = intern ("w32-charset-johab");
+    staticpro (&Qw32_charset_easteurope);
+    Qw32_charset_easteurope = intern ("w32-charset-easteurope");
+    staticpro (&Qw32_charset_turkish);
+    Qw32_charset_turkish = intern ("w32-charset-turkish");
+    staticpro (&Qw32_charset_baltic);
+    Qw32_charset_baltic = intern ("w32-charset-baltic");
+    staticpro (&Qw32_charset_russian);
+    Qw32_charset_russian = intern ("w32-charset-russian");
+    staticpro (&Qw32_charset_arabic);
+    Qw32_charset_arabic = intern ("w32-charset-arabic");
+    staticpro (&Qw32_charset_greek);
+    Qw32_charset_greek = intern ("w32-charset-greek");
+    staticpro (&Qw32_charset_hebrew);
+    Qw32_charset_hebrew = intern ("w32-charset-hebrew");
+    staticpro (&Qw32_charset_thai);
+    Qw32_charset_thai = intern ("w32-charset-thai");
+    staticpro (&Qw32_charset_mac);
+    Qw32_charset_mac = intern ("w32-charset-mac");
+  }
+#endif
+
+#ifdef UNICODE_CHARSET
+  {
+    static int w32_unicode_charset_defined = 1;
+    DEFVAR_BOOL ("w32-unicode-charset-defined",
+                 w32_unicode_charset_defined, "");
+
+    staticpro (&Qw32_charset_unicode);
+    Qw32_charset_unicode = intern ("w32-charset-unicode");
+#endif
 
   staticpro (&help_echo);
   help_echo = Qnil;