#include "objects-msw.h"
#ifdef MULE
-#include "mule-charset.h"
+#include "character.h"
#endif
#include "buffer.h"
#include "device.h"
#include "insdel.h"
-#ifdef __CYGWIN32__
+#if (defined(__CYGWIN32__) || defined(__MINGW32__)) && \
+ CYGWIN_VERSION_DLL_MAJOR < 21
#define stricmp strcasecmp
+#define FONTENUMPROC FONTENUMEXPROC
+#define ntmTm ntmentm
#endif
typedef struct colormap_t
{
- char *name;
- COLORREF colorref;
+ CONST char *name;
+ CONST COLORREF colorref;
} colormap_t;
/* Colors from X11R6 "XConsortium: rgb.txt,v 10.41 94/02/20 18:39:36 rws Exp" */
{"LightGreen" , PALETTERGB (144, 238, 144) }
};
+
+typedef struct fontmap_t
+{
+ CONST char *name;
+ CONST int value;
+} fontmap_t;
+
+/* Default weight first, preferred names listed before synonyms */
+static CONST fontmap_t fontweight_map[] =
+{
+ {"Regular" , FW_REGULAR}, /* The standard font weight */
+ {"Thin" , FW_THIN},
+ {"Extra Light" , FW_EXTRALIGHT},
+ {"Ultra Light" , FW_ULTRALIGHT},
+ {"Light" , FW_LIGHT},
+ {"Normal" , FW_NORMAL},
+ {"Medium" , FW_MEDIUM},
+ {"Semi Bold" , FW_SEMIBOLD},
+ {"Demi Bold" , FW_DEMIBOLD},
+ {"Bold" , FW_BOLD}, /* The standard bold font weight */
+ {"Extra Bold" , FW_EXTRABOLD},
+ {"Ultra Bold" , FW_ULTRABOLD},
+ {"Heavy" , FW_HEAVY},
+ {"Black" , FW_BLACK}
+};
+
+/* Default charset first, no synonyms allowed because these names are
+ * matched against the names reported by win32 by match_font() */
+static CONST fontmap_t charset_map[] =
+{
+ {"Western" , ANSI_CHARSET},
+ {"Symbol" , SYMBOL_CHARSET},
+ {"Shift JIS" , SHIFTJIS_CHARSET}, /* #### Name to be verified */
+ {"GB2312" , GB2312_CHARSET}, /* #### Name to be verified */
+ {"Hanguel" , HANGEUL_CHARSET},
+ {"Chinese Big 5" , CHINESEBIG5_CHARSET}, /* #### Name to be verified */
+#if (WINVER >= 0x0400)
+ {"Johab" , JOHAB_CHARSET}, /* #### Name to be verified */
+ {"Hebrew" , HEBREW_CHARSET}, /* #### Name to be verified */
+ {"Arabic" , ARABIC_CHARSET}, /* #### Name to be verified */
+ {"Greek" , GREEK_CHARSET},
+ {"Turkish" , TURKISH_CHARSET},
+ {"Vietnamese" , VIETNAMESE_CHARSET}, /* #### Name to be verified */
+ {"Thai" , THAI_CHARSET}, /* #### Name to be verified */
+ {"Central European" , EASTEUROPE_CHARSET},
+ {"Cyrillic" , RUSSIAN_CHARSET},
+ {"Mac" , MAC_CHARSET},
+ {"Baltic" , BALTIC_CHARSET},
+#endif
+ {"OEM/DOS" , OEM_CHARSET}
+};
+
\f
/************************************************************************/
/* helpers */
return 1;
}
+
+
+
+\f
+/************************************************************************/
+/* exports */
+/************************************************************************/
+
+struct font_enum_t
+{
+ HDC hdc;
+ struct device *d;
+};
+
+static int CALLBACK
+font_enum_callback_2 (ENUMLOGFONTEX *lpelfe, NEWTEXTMETRICEX *lpntme,
+ int FontType, struct font_enum_t *font_enum)
+{
+ struct mswindows_font_enum *fontlist, **fonthead;
+ char fontname[MSW_FONTSIZE];
+ int i;
+
+ /*
+ * The enumerated font weights are not to be trusted because:
+ * a) lpelfe->elfStyle is only filled in for TrueType fonts.
+ * b) Not all Bold and Italic styles of all fonts (inluding some Vector,
+ * Truetype and Raster fonts) are enumerated.
+ * I guess that fonts for which Bold and Italic styles are generated
+ * 'on-the-fly' are not enumerated. It would be overly restrictive to
+ * disallow Bold And Italic weights for these fonts, so we just leave
+ * weights unspecified. This means that we have to weed out duplicates of
+ * those fonts that do get enumerated with different weights.
+ */
+ if (FontType == 0 /*vector*/ || FontType == TRUETYPE_FONTTYPE)
+ /* Scalable, so leave pointsize blank */
+ sprintf (fontname, "%s::::", lpelfe->elfLogFont.lfFaceName);
+ else
+ /* Formula for pointsize->height from LOGFONT docs in Platform SDK */
+ sprintf (fontname, "%s::%d::", lpelfe->elfLogFont.lfFaceName,
+ MulDiv (lpntme->ntmTm.tmHeight - lpntme->ntmTm.tmInternalLeading,
+ 72, DEVICE_MSWINDOWS_LOGPIXELSY (font_enum->d)));
+
+ /*
+ * The enumerated font character set strings are not to be trusted because
+ * lpelfe->elfScript is returned in the host language and not in English.
+ * We can't know a priori the translations of "Western", "Central European"
+ * etc into the host language, so we must use English. The same argument
+ * applies to the font weight string when matching fonts.
+ */
+ for (i=0; i<countof (charset_map); i++)
+ if (lpelfe->elfLogFont.lfCharSet == charset_map[i].value)
+ {
+ strcat (fontname, charset_map[i].name);
+ break;
+ }
+ if (i==countof (charset_map))
+ strcpy (fontname, charset_map[0].name);
+
+ /* Check that the new font is not a duplicate */
+ fonthead = &DEVICE_MSWINDOWS_FONTLIST (font_enum->d);
+ fontlist = *fonthead;
+ while (fontlist)
+ if (!strcmp (fontname, fontlist->fontname))
+ return 1; /* found a duplicate */
+ else
+ fontlist = fontlist->next;
+
+ /* Insert entry at head */
+ fontlist = *fonthead;
+ *fonthead = xmalloc (sizeof (struct mswindows_font_enum));
+ if (*fonthead == NULL)
+ {
+ *fonthead = fontlist;
+ return 0;
+ }
+ strcpy ((*fonthead)->fontname, fontname);
+ (*fonthead)->next = fontlist;
+ return 1;
+}
+
+static int CALLBACK
+font_enum_callback_1 (ENUMLOGFONTEX *lpelfe, NEWTEXTMETRICEX *lpntme,
+ int FontType, struct font_enum_t *font_enum)
+{
+ /* This function gets called once per facename per character set.
+ * We call a second callback to enumerate the fonts in each facename */
+ return EnumFontFamiliesEx (font_enum->hdc, &lpelfe->elfLogFont,
+ (FONTENUMPROC) font_enum_callback_2,
+ (LPARAM) font_enum, 0);
+}
+
+/*
+ * Enumerate the available fonts. Called by mswindows_init_device().
+ * Fills in the device's device-type-specfic fontlist.
+ */
+void
+mswindows_enumerate_fonts (struct device *d)
+{
+ HDC hdc = CreateCompatibleDC (NULL);
+ LOGFONT logfont;
+ struct font_enum_t font_enum;
+
+ assert (hdc!=NULL);
+ logfont.lfCharSet = DEFAULT_CHARSET;
+ logfont.lfFaceName[0] = '\0';
+ logfont.lfPitchAndFamily = DEFAULT_PITCH;
+ font_enum.hdc = hdc;
+ font_enum.d = d;
+ DEVICE_MSWINDOWS_FONTLIST (d) = NULL;
+ EnumFontFamiliesEx (hdc, &logfont, (FONTENUMPROC) font_enum_callback_1,
+ (LPARAM) (&font_enum), 0);
+ DeleteDC (hdc);
+}
+
\f
/************************************************************************/
/* methods */
COLOR_INSTANCE_MSWINDOWS_COLOR (c) = color;
return 1;
}
- maybe_signal_simple_error ("unrecognized color", name, Qcolor, errb);
+ maybe_signal_simple_error ("Unrecognized color", name, Qcolor, errb);
return(0);
}
#if 0
static void
-mswindows_mark_color_instance (struct Lisp_Color_Instance *c,
- void (*markobj) (Lisp_Object))
+mswindows_mark_color_instance (struct Lisp_Color_Instance *c)
{
}
#endif
static unsigned long
mswindows_color_instance_hash (struct Lisp_Color_Instance *c, int depth)
{
- return (unsigned long)(COLOR_INSTANCE_MSWINDOWS_COLOR(c));
+ return (unsigned long) COLOR_INSTANCE_MSWINDOWS_COLOR(c);
}
static Lisp_Object
}
}
+
static int
mswindows_initialize_font_instance (struct Lisp_Font_Instance *f, Lisp_Object name,
Lisp_Object device, Error_behavior errb)
{
CONST char *extname;
LOGFONT logfont;
- int fields;
+ int fields, i;
int pt;
char fontname[LF_FACESIZE], weight[LF_FACESIZE], *style, points[8];
char effects[LF_FACESIZE], charset[LF_FACESIZE];
char *c;
-
- GET_C_STRING_CTEXT_DATA_ALLOCA (f->name, extname);
+ HDC hdc;
+ HFONT holdfont;
+ TEXTMETRIC metrics;
+
+ extname = XSTRING_DATA (name);
/*
* mswindows fonts look like:
/* This function is implemented in a fairly ad-hoc manner.
* The general idea is to validate and canonicalize each of the above fields
* at the same time as we build up the win32 LOGFONT structure. This enables
- * us to use math_font() on a canonicalized font string to check the
+ * us to use match_font() on a canonicalized font string to check the
* availability of the requested font */
- if (fields<0)
+ if (fields < 0)
{
- maybe_signal_simple_error ("Invalid font", f->name, Qfont, errb);
+ maybe_signal_simple_error ("Invalid font", name, Qfont, errb);
return (0);
}
}
else
{
- maybe_signal_simple_error ("Must specify a font name", f->name, Qfont, errb);
+ maybe_signal_simple_error ("Must specify a font name", name, Qfont, errb);
return (0);
}
/* weight */
if (fields < 2)
- strcpy (weight, "Regular");
+ strcpy (weight, fontweight_map[0].name);
/* Maybe split weight into weight and style */
if ((c=strchr(weight, ' ')))
else
style = NULL;
-#define FROB(wgt) \
- if (stricmp (weight, #wgt) == 0) \
- logfont.lfWeight = FW_##wgt
-
- FROB (REGULAR);
- else FROB (THIN);
- else FROB (EXTRALIGHT);
- else FROB (ULTRALIGHT);
- else FROB (LIGHT);
- else FROB (NORMAL);
- else FROB (MEDIUM);
- else FROB (SEMIBOLD);
- else FROB (DEMIBOLD);
- else FROB (BOLD);
- else FROB (EXTRABOLD);
- else FROB (ULTRABOLD);
- else FROB (HEAVY);
- else FROB (BLACK);
- else if (!style)
- {
- logfont.lfWeight = FW_REGULAR;
- style = weight; /* May have specified style without weight */
- }
- else
+ for (i=0; i<countof (fontweight_map); i++)
+ if (!stricmp (weight, fontweight_map[i].name))
+ {
+ logfont.lfWeight = fontweight_map[i].value;
+ break;
+ }
+ if (i == countof (fontweight_map)) /* No matching weight */
{
- maybe_signal_simple_error ("Invalid font weight", f->name, Qfont, errb);
- return (0);
+ if (!style)
+ {
+ logfont.lfWeight = FW_REGULAR;
+ style = weight; /* May have specified style without weight */
+ }
+ else
+ {
+ maybe_signal_simple_error ("Invalid font weight", name, Qfont, errb);
+ return (0);
+ }
}
-#undef FROB
-
if (style)
{
/* #### what about oblique? */
logfont.lfItalic = TRUE;
else
{
- maybe_signal_simple_error ("Invalid font weight or style", f->name, Qfont, errb);
+ maybe_signal_simple_error ("Invalid font weight or style", name, Qfont, errb);
return (0);
}
pt = 10; /* #### Should we reject strings that don't specify a size? */
else if ((pt=atoi(points)) == 0)
{
- maybe_signal_simple_error ("Invalid font pointsize", f->name, Qfont, errb);
+ maybe_signal_simple_error ("Invalid font pointsize", name, Qfont, errb);
return (0);
}
/* Formula for pointsize->height from LOGFONT docs in MSVC5 Platform SDK */
- logfont.lfHeight = -MulDiv(pt, DEVICE_MSWINDOWS_LOGPIXELSY(XDEVICE (device)), 72);
+ logfont.lfHeight = -MulDiv(pt, DEVICE_MSWINDOWS_LOGPIXELSY (XDEVICE (device)), 72);
logfont.lfWidth = 0;
/* Effects */
logfont.lfStrikeOut = TRUE;
else
{
- maybe_signal_simple_error ("Invalid font effect", f->name,
- Qfont, errb);
+ maybe_signal_simple_error ("Invalid font effect", name, Qfont, errb);
return (0);
}
logfont.lfStrikeOut = TRUE;
else
{
- maybe_signal_simple_error ("Invalid font effect", f->name,
+ maybe_signal_simple_error ("Invalid font effect", name,
Qfont, errb);
return (0);
}
else
effects[0] = '\0';
-#define FROB(cs) \
- else if (stricmp (charset, #cs) == 0) \
- logfont.lfCharSet = cs##_CHARSET
-
- /* Charset aliases. Hangeul = Hangul is defined in windows.h.
- We do not use the name "russian", only "cyrillic", as it is
- the common name of this charset, used in other languages
- than Russian. */
-#define CYRILLIC_CHARSET RUSSIAN_CHARSET
-#define CENTRALEUROPEAN_CHARSET EASTEUROPE_CHARSET
-#define CENTRALEUROPEAN_CHARSET EASTEUROPE_CHARSET
-
+ /* Charset */
/* charset can be specified even if earlier fields havn't been */
- if ((fields < 5) && (c=strchr (extname, ':')) && (c=strchr (c+1, ':')) &&
- (c=strchr (c+1, ':')) && (c=strchr (c+1, ':')))
- {
- strncpy (charset, c+1, LF_FACESIZE);
- charset[LF_FACESIZE-1] = '\0';
- }
- else
- charset[0] = '\0';
-
- if (charset[0] == '\0' || (stricmp (charset, "ansi") == 0) ||
- (stricmp (charset, "western") == 0))
+ if (fields < 5)
{
- logfont.lfCharSet = ANSI_CHARSET;
- strcpy (charset, "western");
+ if ((c=strchr (extname, ':')) && (c=strchr (c+1, ':')) &&
+ (c=strchr (c+1, ':')) && (c=strchr (c+1, ':')))
+ {
+ strncpy (charset, c+1, LF_FACESIZE);
+ charset[LF_FACESIZE-1] = '\0';
+ }
+ else
+ strcpy (charset, charset_map[0].name);
}
- FROB (SYMBOL);
- FROB (SHIFTJIS);
- FROB (GB2312);
- FROB (HANGEUL);
- FROB (CHINESEBIG5);
- FROB (JOHAB);
- FROB (HEBREW);
- FROB (ARABIC);
- FROB (GREEK);
- FROB (TURKISH);
- FROB (THAI);
- FROB (EASTEUROPE);
- FROB (CENTRALEUROPEAN);
- FROB (CYRILLIC);
- FROB (MAC);
- FROB (BALTIC);
- else if (stricmp (charset, "oem/dos") == 0)
- logfont.lfCharSet = OEM_CHARSET;
- else
+
+ for (i=0; i<countof (charset_map); i++)
+ if (!stricmp (charset, charset_map[i].name))
+ {
+ logfont.lfCharSet = charset_map[i].value;
+ break;
+ }
+
+ if (i == countof (charset_map)) /* No matching charset */
{
- maybe_signal_simple_error ("Invalid charset", f->name, Qfont, errb);
+ maybe_signal_simple_error ("Invalid charset", name, Qfont, errb);
return 0;
}
-#undef FROB
+ /* Misc crud */
+ logfont.lfEscapement = logfont.lfOrientation = 0;
+#if 1
+ logfont.lfOutPrecision = OUT_DEFAULT_PRECIS;
+ logfont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
+ logfont.lfQuality = DEFAULT_QUALITY;
+#else
+ logfont.lfOutPrecision = OUT_STROKE_PRECIS;
+ logfont.lfClipPrecision = CLIP_STROKE_PRECIS;
+ logfont.lfQuality = PROOF_QUALITY;
+#endif
+ /* Default to monospaced if the specified fontname doesn't exist. */
+ logfont.lfPitchAndFamily = FF_MODERN;
/* Windows will silently substitute a default font if the fontname
* specifies a non-existent font. So we check the font against the device's
- * list of font patterns to make sure that at least one of them matches */
+ * list of font patterns to make sure that at least one of them matches. */
{
struct mswindows_font_enum *fontlist;
char truename[MSW_FONTSIZE];
}
if (!done)
{
- maybe_signal_simple_error ("No matching font", f->name, Qfont, errb);
+ maybe_signal_simple_error ("No matching font", name, Qfont, errb);
return 0;
}
}
- /* Misc crud */
- logfont.lfEscapement = logfont.lfOrientation = 0;
-#if 1
- logfont.lfOutPrecision = OUT_DEFAULT_PRECIS;
- logfont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
- logfont.lfQuality = DEFAULT_QUALITY;
-#else
- logfont.lfOutPrecision = OUT_STROKE_PRECIS;
- logfont.lfClipPrecision = CLIP_STROKE_PRECIS;
- logfont.lfQuality = PROOF_QUALITY;
-#endif
- /* Default to monospaced if the specified fontname doesn't exist.
- * The match_font calls above should mean that this can't happen. */
- logfont.lfPitchAndFamily = FF_MODERN;
-
if ((f->data = CreateFontIndirect(&logfont)) == NULL)
{
- maybe_signal_simple_error ("Couldn't create font", f->name, Qfont, errb);
+ maybe_signal_simple_error ("Couldn't create font", name, Qfont, errb);
return 0;
}
- {
- HDC hdc;
- HFONT holdfont;
- TEXTMETRIC metrics;
-
- hdc = CreateCompatibleDC (NULL);
- if (hdc)
- {
- holdfont = SelectObject(hdc, f->data);
- if (holdfont)
- {
- GetTextMetrics (hdc, &metrics);
- SelectObject(hdc, holdfont);
- DeleteDC (hdc);
- f->width = (unsigned short) metrics.tmAveCharWidth;
- f->height = (unsigned short) metrics.tmHeight;
- f->ascent = (unsigned short) metrics.tmAscent;
- f->descent = (unsigned short) metrics.tmDescent;
- f->proportional_p = (metrics.tmPitchAndFamily & TMPF_FIXED_PITCH);
- return 1;
- }
- DeleteDC (hdc);
- }
- mswindows_finalize_font_instance (f);
- maybe_signal_simple_error ("Couldn't map font", f->name, Qfont, errb);
- }
+ hdc = CreateCompatibleDC (NULL);
+ if (hdc)
+ {
+ holdfont = SelectObject(hdc, f->data);
+ if (holdfont)
+ {
+ GetTextMetrics (hdc, &metrics);
+ SelectObject(hdc, holdfont);
+ DeleteDC (hdc);
+ f->width = (unsigned short) metrics.tmAveCharWidth;
+ f->height = (unsigned short) metrics.tmHeight;
+ f->ascent = (unsigned short) metrics.tmAscent;
+ f->descent = (unsigned short) metrics.tmDescent;
+ f->proportional_p = (metrics.tmPitchAndFamily & TMPF_FIXED_PITCH);
+ return 1;
+ }
+ DeleteDC (hdc);
+ }
+ mswindows_finalize_font_instance (f);
+ maybe_signal_simple_error ("Couldn't map font", name, Qfont, errb);
return 0;
}
#if 0
static void
-mswindows_mark_font_instance (struct Lisp_Font_Instance *f,
- void (*markobj) (Lisp_Object))
+mswindows_mark_font_instance (struct Lisp_Font_Instance *f)
{
}
#endif
return Fnreverse (result);
}
+/* Fill in missing parts of a font spec. This is primarily intended as a
+ * helper function for the functions below.
+ * mswindows fonts look like:
+ * fontname[:[weight][ style][:pointsize[:effects]]][:charset]
+ * A minimal mswindows font spec looks like:
+ * Courier New
+ * A maximal mswindows font spec looks like:
+ * Courier New:Bold Italic:10:underline strikeout:Western
+ * Missing parts of the font spec should be filled in with these values:
+ * Courier New:Regular:10::Western */
+static Lisp_Object
+mswindows_font_instance_truename (struct Lisp_Font_Instance *f, Error_behavior errb)
+{
+ int nsep=0;
+ char *name = (char *) XSTRING_DATA (f->name);
+ char* ptr = name;
+ char* extname = alloca (strlen (name) + 19);
+ strcpy (extname, name);
+
+ while ((ptr = strchr (ptr, ':')) != 0)
+ {
+ ptr++;
+ nsep++;
+ }
+
+ switch (nsep)
+ {
+ case 0:
+ strcat (extname, ":Regular:10::Western");
+ break;
+ case 1:
+ strcat (extname, ":10::Western");
+ break;
+ case 2:
+ strcat (extname, "::Western");
+ break;
+ case 3:
+ strcat (extname, ":Western");
+ break;
+ default:;
+ }
+
+ return build_ext_string (extname, FORMAT_OS);
+}
+
#ifdef MULE
static int
/* CONSOLE_HAS_METHOD (mswindows, mark_font_instance); */
CONSOLE_HAS_METHOD (mswindows, print_font_instance);
CONSOLE_HAS_METHOD (mswindows, finalize_font_instance);
-/* CONSOLE_HAS_METHOD (mswindows, font_instance_truename); */
+ CONSOLE_HAS_METHOD (mswindows, font_instance_truename);
CONSOLE_HAS_METHOD (mswindows, list_fonts);
#ifdef MULE
CONSOLE_HAS_METHOD (mswindows, font_spec_matches_charset);