summaryrefslogtreecommitdiff
path: root/src/w32term.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/w32term.c')
-rw-r--r--src/w32term.c789
1 files changed, 670 insertions, 119 deletions
diff --git a/src/w32term.c b/src/w32term.c
index edde95f5f13..aae84473532 100644
--- a/src/w32term.c
+++ b/src/w32term.c
@@ -25,25 +25,21 @@ Boston, MA 02110-1301, USA. */
#include <stdio.h>
#include <stdlib.h>
#include "lisp.h"
-#include "charset.h"
#include "blockinput.h"
-
-#include "w32heap.h"
#include "w32term.h"
-#include "w32bdf.h"
-#include <shellapi.h>
#include "systty.h"
#include "systime.h"
-#include "atimer.h"
-#include "keymap.h"
#include <ctype.h>
#include <errno.h>
#include <setjmp.h>
#include <sys/stat.h>
-#include "keyboard.h"
+#include "charset.h"
+#include "character.h"
+#include "coding.h"
+#include "ccl.h"
#include "frame.h"
#include "dispextern.h"
#include "fontset.h"
@@ -54,9 +50,19 @@ Boston, MA 02110-1301, USA. */
#include "disptab.h"
#include "buffer.h"
#include "window.h"
+#include "keyboard.h"
#include "intervals.h"
-#include "composite.h"
-#include "coding.h"
+#include "process.h"
+#include "atimer.h"
+#include "keymap.h"
+
+#include "w32heap.h"
+#include "w32bdf.h"
+#include <shellapi.h>
+
+#ifdef USE_FONT_BACKEND
+#include "font.h"
+#endif /* USE_FONT_BACKEND */
/* Fringe bitmaps. */
@@ -119,6 +125,31 @@ struct w32_display_info *x_display_list;
FONT-LIST-CACHE records previous values returned by x-list-fonts. */
Lisp_Object w32_display_name_list;
+
+#ifndef GLYPHSET
+/* Pre Windows 2000, this was not available, but define it here so
+ that Emacs compiled on such a platform will run on newer versions. */
+
+typedef struct tagWCRANGE
+{
+ WCHAR wcLow;
+ USHORT cGlyphs;
+} WCRANGE;
+
+typedef struct tagGLYPHSET
+{
+ DWORD cbThis;
+ DWORD flAccel;
+ DWORD cGlyphsSupported;
+ DWORD cRanges;
+ WCRANGE ranges[1];
+} GLYPHSET;
+
+#endif
+
+/* Dynamic linking to GetFontUnicodeRanges (not available on 95, 98, ME). */
+DWORD (PASCAL *pfnGetFontUnicodeRanges) (HDC device, GLYPHSET *ranges);
+
/* Frame being updated by update_frame. This is declared in term.c.
This is set by update_begin and looked at by all the
w32 functions. It is zero while not inside an update.
@@ -867,7 +898,8 @@ w32_reset_terminal_modes (struct terminal *term)
/* Function prototypes of this page. */
XCharStruct *w32_per_char_metric P_ ((XFontStruct *, wchar_t *, int));
-static int w32_encode_char P_ ((int, wchar_t *, struct font_info *, int *));
+static int w32_encode_char P_ ((int, wchar_t *, struct font_info *,
+ struct charset *, int *));
/* Get metrics of character CHAR2B in FONT. Value is always non-null.
@@ -992,8 +1024,8 @@ w32_native_per_char_metric (font, char2b, font_type, pcm)
if (retval)
{
- pcm->width = sz.cx - font->tm.tmOverhang;
- pcm->rbearing = sz.cx;
+ pcm->width = sz.cx;
+ pcm->rbearing = sz.cx + font->tm.tmOverhang;
pcm->lbearing = 0;
pcm->ascent = FONT_BASE (font);
pcm->descent = FONT_DESCENT (font);
@@ -1074,9 +1106,9 @@ w32_cache_char_metrics (font)
{
/* Use the font width and height as max bounds, as not all BDF
fonts contain the letter 'x'. */
- font->max_bounds.width = FONT_MAX_WIDTH (font);
+ font->max_bounds.width = FONT_WIDTH (font);
font->max_bounds.lbearing = -font->bdf->llx;
- font->max_bounds.rbearing = FONT_MAX_WIDTH (font) - font->bdf->urx;
+ font->max_bounds.rbearing = FONT_WIDTH (font) - font->bdf->urx;
font->max_bounds.ascent = FONT_BASE (font);
font->max_bounds.descent = FONT_DESCENT (font);
}
@@ -1132,13 +1164,13 @@ w32_use_unicode_for_codepage (codepage)
the two-byte form of C. Encoding is returned in *CHAR2B. */
static int /* enum w32_char_font_type */
-w32_encode_char (c, char2b, font_info, two_byte_p)
+w32_encode_char (c, char2b, font_info, charset, two_byte_p)
int c;
wchar_t *char2b;
struct font_info *font_info;
+ struct charset *charset;
int * two_byte_p;
{
- int charset = CHAR_CHARSET (c);
int codepage;
int unicode_p = 0;
int internal_two_byte_p = 0;
@@ -1146,29 +1178,39 @@ w32_encode_char (c, char2b, font_info, two_byte_p)
XFontStruct *font = font_info->font;
internal_two_byte_p = w32_font_is_double_byte (font);
+ codepage = font_info->codepage;
+
+ /* If font can output unicode, use the original unicode character. */
+ if ( font && !font->bdf && w32_use_unicode_for_codepage (codepage)
+ && c >= 0x100)
+ {
+ *char2b = c;
+ unicode_p = 1;
+ internal_two_byte_p = 1;
+ }
/* FONT_INFO may define a scheme by which to encode byte1 and byte2.
This may be either a program in a special encoder language or a
fixed encoding. */
- if (font_info->font_encoder)
+ else if (font_info->font_encoder)
{
/* It's a program. */
struct ccl_program *ccl = font_info->font_encoder;
if (CHARSET_DIMENSION (charset) == 1)
{
- ccl->reg[0] = charset;
+ ccl->reg[0] = CHARSET_ID (charset);
ccl->reg[1] = XCHAR2B_BYTE2 (char2b);
ccl->reg[2] = -1;
}
else
{
- ccl->reg[0] = charset;
+ ccl->reg[0] = CHARSET_ID (charset);
ccl->reg[1] = XCHAR2B_BYTE1 (char2b);
ccl->reg[2] = XCHAR2B_BYTE2 (char2b);
}
- ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
+ ccl_driver (ccl, NULL, NULL, 0, 0, Qnil);
/* We assume that MSBs are appropriately set/reset by CCL
program. */
@@ -1177,49 +1219,25 @@ w32_encode_char (c, char2b, font_info, two_byte_p)
else
STORE_XCHAR2B (char2b, ccl->reg[1], ccl->reg[2]);
}
- else if (font_info->encoding[charset])
+ else if (font_info->encoding_type)
{
/* Fixed encoding scheme. See fontset.h for the meaning of the
encoding numbers. */
- int enc = font_info->encoding[charset];
+ unsigned char enc = font_info->encoding_type;
if ((enc == 1 || enc == 2)
&& CHARSET_DIMENSION (charset) == 2)
STORE_XCHAR2B (char2b, XCHAR2B_BYTE1 (char2b) | 0x80, XCHAR2B_BYTE2 (char2b));
- if (enc == 1 || enc == 3
- || (enc == 4 && CHARSET_DIMENSION (charset) == 1))
+ if (enc == 1 || enc == 3 || (enc == 4 && CHARSET_DIMENSION (charset) == 1))
STORE_XCHAR2B (char2b, XCHAR2B_BYTE1 (char2b), XCHAR2B_BYTE2 (char2b) | 0x80);
else if (enc == 4)
{
- int sjis1, sjis2;
-
- ENCODE_SJIS (XCHAR2B_BYTE1 (char2b), XCHAR2B_BYTE2 (char2b),
- sjis1, sjis2);
- STORE_XCHAR2B (char2b, sjis1, sjis2);
- }
- }
- codepage = font_info->codepage;
+ int code = (int) (*char2b);
- /* If charset is not ASCII or Latin-1, may need to move it into
- Unicode space. */
- if ( font && !font->bdf && w32_use_unicode_for_codepage (codepage)
- && charset != CHARSET_ASCII && charset != charset_latin_iso8859_1
- && charset != CHARSET_8_BIT_CONTROL && charset != CHARSET_8_BIT_GRAPHIC)
- {
- char temp[3];
- temp[0] = XCHAR2B_BYTE1 (char2b);
- temp[1] = XCHAR2B_BYTE2 (char2b);
- temp[2] = '\0';
- if (codepage != CP_UNICODE)
- {
- if (temp[0])
- MultiByteToWideChar (codepage, 0, temp, 2, char2b, 1);
- else
- MultiByteToWideChar (codepage, 0, temp+1, 1, char2b, 1);
+ JIS_TO_SJIS (code);
+ STORE_XCHAR2B (char2b, (code >> 8), (code & 0xFF));
}
- unicode_p = 1;
- internal_two_byte_p = 1;
}
if (two_byte_p)
@@ -1238,6 +1256,207 @@ w32_encode_char (c, char2b, font_info, two_byte_p)
}
+/* Return a char-table whose elements are t if the font FONT_INFO
+ contains a glyph for the corresponding character, and nil if not.
+
+ Fixme: For the moment, this function works only for fonts whose
+ glyph encoding is the same as Unicode (e.g. ISO10646-1 fonts). */
+
+Lisp_Object
+x_get_font_repertory (f, font_info)
+ FRAME_PTR f;
+ struct font_info *font_info;
+{
+ XFontStruct *font = (XFontStruct *) font_info->font;
+ Lisp_Object table;
+ int min_byte1, max_byte1, min_byte2, max_byte2;
+ int c;
+ struct charset *charset = CHARSET_FROM_ID (font_info->charset);
+ int offset = CHARSET_OFFSET (charset);
+
+ table = Fmake_char_table (Qnil, Qnil);
+
+ if (!font->bdf && pfnGetFontUnicodeRanges)
+ {
+ GLYPHSET *glyphset;
+ DWORD glyphset_size;
+ HDC display = get_frame_dc (f);
+ HFONT prev_font;
+ int i;
+
+ prev_font = SelectObject (display, font->hfont);
+
+ /* First call GetFontUnicodeRanges to find out how big a structure
+ we need. */
+ glyphset_size = pfnGetFontUnicodeRanges (display, NULL);
+ if (glyphset_size)
+ {
+ glyphset = (GLYPHSET *) alloca (glyphset_size);
+ glyphset->cbThis = glyphset_size;
+
+ /* Now call it again to get the ranges. */
+ glyphset_size = pfnGetFontUnicodeRanges (display, glyphset);
+
+ if (glyphset_size)
+ {
+ /* Store the ranges in TABLE. */
+ for (i = 0; i < glyphset->cRanges; i++)
+ {
+ int from = glyphset->ranges[i].wcLow;
+ int to = from + glyphset->ranges[i].cGlyphs - 1;
+ char_table_set_range (table, from, to, Qt);
+ }
+ }
+ }
+
+ SelectObject (display, prev_font);
+ release_frame_dc (f, display);
+
+ /* If we got the information we wanted above, then return it. */
+ if (glyphset_size)
+ return table;
+ }
+
+#if 0 /* TODO: Convert to work on Windows so BDF and older platforms work. */
+ /* When GetFontUnicodeRanges is not available or does not work,
+ work it out manually. */
+ min_byte1 = font->min_byte1;
+ max_byte1 = font->max_byte1;
+ min_byte2 = font->min_char_or_byte2;
+ max_byte2 = font->max_char_or_byte2;
+ if (min_byte1 == 0 && max_byte1 == 0)
+ {
+ if (! font->per_char || font->all_chars_exist == True)
+ {
+ if (offset >= 0)
+ char_table_set_range (table, offset + min_byte2,
+ offset + max_byte2, Qt);
+ else
+ for (; min_byte2 <= max_byte2; min_byte2++)
+ {
+ c = DECODE_CHAR (charset, min_byte2);
+ CHAR_TABLE_SET (table, c, Qt);
+ }
+ }
+ else
+ {
+ XCharStruct *pcm = font->per_char;
+ int from = -1;
+ int i;
+
+ for (i = min_byte2; i <= max_byte2; i++, pcm++)
+ {
+ if (pcm->width == 0 && pcm->rbearing == pcm->lbearing)
+ {
+ if (from >= 0)
+ {
+ if (offset >= 0)
+ char_table_set_range (table, offset + from,
+ offset + i - 1, Qt);
+ else
+ for (; from < i; from++)
+ {
+ c = DECODE_CHAR (charset, from);
+ CHAR_TABLE_SET (table, c, Qt);
+ }
+ from = -1;
+ }
+ }
+ else if (from < 0)
+ from = i;
+ }
+ if (from >= 0)
+ {
+ if (offset >= 0)
+ char_table_set_range (table, offset + from, offset + i - 1,
+ Qt);
+ else
+ for (; from < i; from++)
+ {
+ c = DECODE_CHAR (charset, from);
+ CHAR_TABLE_SET (table, c, Qt);
+ }
+ }
+ }
+ }
+ else
+ {
+ if (! font->per_char || font->all_chars_exist == True)
+ {
+ int i, j;
+
+ if (offset >= 0)
+ for (i = min_byte1; i <= max_byte1; i++)
+ char_table_set_range
+ (table, offset + ((i << 8) | min_byte2),
+ offset + ((i << 8) | max_byte2), Qt);
+ else
+ for (i = min_byte1; i <= max_byte1; i++)
+ for (j = min_byte2; j <= max_byte2; j++)
+ {
+ unsiged code = (i << 8) | j;
+ c = DECODE_CHAR (charset, code);
+ CHAR_TABLE_SET (table, c, Qt);
+ }
+ }
+ else
+ {
+ XCharStruct *pcm = font->per_char;
+ int i;
+
+ for (i = min_byte1; i <= max_byte1; i++)
+ {
+ int from = -1;
+ int j;
+
+ for (j = min_byte2; j <= max_byte2; j++, pcm++)
+ {
+ if (pcm->width == 0 && pcm->rbearing == pcm->lbearing)
+ {
+ if (from >= 0)
+ {
+ if (offset >= 0)
+ char_table_set_range
+ (table, offset + ((i << 8) | from),
+ offset + ((i << 8) | (j - 1)), Qt);
+ else
+ {
+ for (; from < j; from++)
+ {
+ unsigned code = (i << 8) | from;
+ c = ENCODE_CHAR (charset, code);
+ CHAR_TABLE_SET (table, c, Qt);
+ }
+ }
+ from = -1;
+ }
+ }
+ else if (from < 0)
+ from = j;
+ }
+ if (from >= 0)
+ {
+ if (offset >= 0)
+ char_table_set_range
+ (table, offset + ((i << 8) | from),
+ offset + ((i << 8) | (j - 1)), Qt);
+ else
+ {
+ for (; from < j; from++)
+ {
+ unsigned code = (i << 8) | from;
+ c = DECODE_CHAR (charset, code);
+ CHAR_TABLE_SET (table, c, Qt);
+ }
+ }
+ }
+ }
+ }
+ }
+#endif
+ return table;
+}
+
/***********************************************************************
Glyph display
@@ -1367,15 +1586,20 @@ x_set_mouse_face_gc (s)
face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
if (s->first_glyph->type == CHAR_GLYPH)
- face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
+ face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch, -1, Qnil);
else
- face_id = FACE_FOR_CHAR (s->f, face, 0);
+ face_id = FACE_FOR_CHAR (s->f, face, 0, -1, Qnil);
s->face = FACE_FROM_ID (s->f, face_id);
PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
/* If font in this face is same as S->font, use it. */
if (s->font == s->face->font)
s->gc = s->face->gc;
+#ifdef USE_FONT_BACKEND
+ else if (enable_font_backend)
+ /* No need of setting a font for s->gc. */
+ s->gc = s->face->gc;
+#endif /* USE_FONT_BACKEND */
else
{
/* Otherwise construct scratch_cursor_gc with values from FACE
@@ -1469,11 +1693,68 @@ static INLINE void
x_set_glyph_string_clipping (s)
struct glyph_string *s;
{
- RECT r;
- get_glyph_string_clip_rect (s, &r);
- w32_set_clip_rectangle (s->hdc, &r);
+#ifdef USE_FONT_BACKEND
+ RECT *r = s->clip;
+#else
+ RECT r[2];
+#endif
+ int n = get_glyph_string_clip_rects (s, r, 2);
+
+ if (n == 1)
+ w32_set_clip_rectangle (s->hdc, r);
+ else if (n > 1)
+ {
+ HRGN full_clip, clip1, clip2;
+ clip1 = CreateRectRgnIndirect (r);
+ clip2 = CreateRectRgnIndirect (r + 1);
+ if (CombineRgn (full_clip, clip1, clip2, RGN_OR) != ERROR)
+ {
+ SelectClipRgn (s->hdc, full_clip);
+ }
+ DeleteObject (clip1);
+ DeleteObject (clip2);
+ DeleteObject (full_clip);
+ }
+#ifdef USE_FONT_BACKEND
+ s->num_clips = n;
+#endif /* USE_FONT_BACKEND */
}
+/* Set SRC's clipping for output of glyph string DST. This is called
+ when we are drawing DST's left_overhang or right_overhang only in
+ the area of SRC. */
+
+static void
+x_set_glyph_string_clipping_exactly (src, dst)
+ struct glyph_string *src, *dst;
+{
+ RECT r;
+
+#ifdef USE_FONT_BACKEND
+ if (enable_font_backend)
+ {
+ r.left = src->x;
+ r.right = r.left + src->width;
+ r.top = src->y;
+ r.bottom = r.top + src->height;
+ dst->clip[0] = r;
+ dst->num_clips = 1;
+ }
+ else
+ {
+#endif /* USE_FONT_BACKEND */
+ struct glyph_string *clip_head = src->clip_head;
+ struct glyph_string *clip_tail = src->clip_tail;
+
+ /* This foces clipping just this glyph string. */
+ src->clip_head = src->clip_tail = src;
+ get_glyph_string_clip_rect (src, &r);
+ src->clip_head = clip_head, src->clip_tail = clip_tail;
+#ifdef USE_FONT_BACKEND
+ }
+#endif /* USE_FONT_BACKEND */
+ w32_set_clip_rectangle (dst->hdc, &r);
+}
/* RIF:
Compute left and right overhang of glyph string S. If S is a glyph
@@ -1618,6 +1899,26 @@ x_draw_glyph_string_foreground (s)
x += g->pixel_width;
}
}
+#ifdef USE_FONT_BACKEND
+ else if (enable_font_backend)
+ {
+ int boff = s->font_info->baseline_offset;
+ struct font *font = (struct font *) s->font_info;
+ int y;
+
+ if (s->font_info->vertical_centering)
+ boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
+
+ y = s->ybase - boff;
+ if (s->for_overlaps
+ || (s->background_filled_p && s->hl != DRAW_CURSOR))
+ font->driver->draw (s, 0, s->nchars, x, y, 0);
+ else
+ font->driver->draw (s, 0, s->nchars, x, y, 1);
+ if (s->face->overstrike)
+ font->driver->draw (s, 0, s->nchars, x + 1, y, 0);
+ }
+#endif /* USE_FONT_BACKEND */
else
{
char *char1b = (char *) s->char2b;
@@ -1654,12 +1955,12 @@ static void
x_draw_composite_glyph_string_foreground (s)
struct glyph_string *s;
{
- int i, x;
+ int i, j, x;
HFONT old_font;
/* If first glyph of S has a left box line, start drawing the text
of S to the right of that box line. */
- if (s->face->box != FACE_NO_BOX
+ if (s->face && s->face->box != FACE_NO_BOX
&& s->first_glyph->left_box_line_p)
x = s->x + eabs (s->face->box_line_width);
else
@@ -1686,19 +1987,77 @@ x_draw_composite_glyph_string_foreground (s)
w32_draw_rectangle (s->hdc, s->gc, x, s->y, s->width - 1,
s->height - 1);
}
- else
+#ifdef USE_FONT_BACKEND
+ else if (enable_font_backend)
{
- for (i = 0; i < s->nchars; i++, ++s->gidx)
+ struct font *font = (struct font *) s->font_info;
+ int y = s->ybase;
+ int width = 0;
+
+ if (s->cmp->method == COMPOSITION_WITH_GLYPH_STRING)
+ {
+ Lisp_Object gstring = AREF (XHASH_TABLE (composition_hash_table)
+ ->key_and_value,
+ s->cmp->hash_index * 2);
+ int from;
+
+ for (i = from = 0; i < s->nchars; i++)
+ {
+ Lisp_Object g = LGSTRING_GLYPH (gstring, i);
+ Lisp_Object adjustment = LGLYPH_ADJUSTMENT (g);
+ int xoff, yoff, wadjust;
+
+ if (! VECTORP (adjustment))
+ {
+ width += XINT (LGLYPH_WIDTH (g));
+ continue;
+ }
+ if (from < i)
+ {
+ font->driver->draw (s, from, i, x, y, 0);
+ x += width;
+ }
+ xoff = XINT (AREF (adjustment, 0));
+ yoff = XINT (AREF (adjustment, 1));
+ wadjust = XINT (AREF (adjustment, 2));
+
+ font->driver->draw (s, i, i + 1, x + xoff, y + yoff, 0);
+ x += XINT (LGLYPH_WIDTH (g)) + wadjust;
+ from = i + 1;
+ width = 0;
+ }
+ if (from < i)
+ font->driver->draw (s, from, i, x, y, 0);
+ }
+ else
{
- w32_text_out (s, x + s->cmp->offsets[s->gidx * 2],
- s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
- s->char2b + i, 1);
- if (s->face->overstrike)
- w32_text_out (s, x + s->cmp->offsets[s->gidx * 2] + 1,
- s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
- s->char2b + i, 1);
+ for (i = 0, j = s->gidx; i < s->nchars; i++, j++)
+ if (COMPOSITION_GLYPH (s->cmp, j) != '\t')
+ {
+ int xx = x + s->cmp->offsets[j * 2];
+ int yy = y - s->cmp->offsets[j * 2 + 1];
+
+ font->driver->draw (s, j, j + 1, xx, yy, 0);
+ if (s->face->overstrike)
+ font->driver->draw (s, j, j + 1, xx + 1, yy, 0);
+ }
}
}
+#endif /* USE_FONT_BACKEND */
+ else
+ {
+ for (i = 0, j = s->gidx; i < s->nchars; i++, j++)
+ if (s->face)
+ {
+ w32_text_out (s, x + s->cmp->offsets[j * 2],
+ s->ybase - s->cmp->offsets[j * 2 + 1],
+ s->char2b + j, 1);
+ if (s->face->overstrike)
+ w32_text_out (s, x + s->cmp->offsets[j * 2] + 1,
+ s->ybase - s->cmp->offsets[j + 1],
+ s->char2b + j, 1);
+ }
+ }
if (s->font && s->font->hfont)
SelectObject (s->hdc, old_font);
@@ -2500,10 +2859,19 @@ x_draw_glyph_string (s)
This makes S->next use XDrawString instead of XDrawImageString. */
if (s->next && s->right_overhang && !s->for_overlaps)
{
- xassert (s->next->img == NULL);
- x_set_glyph_string_gc (s->next);
- x_set_glyph_string_clipping (s->next);
- x_draw_glyph_string_background (s->next, 1);
+ int width;
+ struct glyph_string *next;
+ for (width = 0, next = s->next; next;
+ width += next->width, next = next->next)
+ if (next->first_glyph->type != IMAGE_GLYPH)
+ {
+ x_set_glyph_string_gc (next);
+ x_set_glyph_string_clipping (next);
+ x_draw_glyph_string_background (next, 1);
+#ifdef USE_FONT_BACKEND
+ next->num_clips = 0;
+#endif /* USE_FONT_BACKEND */
+ }
}
/* Set up S->gc, set clipping and draw S. */
@@ -2523,6 +2891,12 @@ x_draw_glyph_string (s)
x_set_glyph_string_clipping (s);
relief_drawn_p = 1;
}
+ else if ((s->prev && s->prev->hl != s->hl && s->left_overhang)
+ || (s->next && s->next->hl != s->hl && s->right_overhang))
+ /* We must clip just this glyph. left_overhang part has already
+ drawn when s->prev was drawn, and right_overhang part will be
+ drawn later when s->next is drawn. */
+ x_set_glyph_string_clipping_exactly (s, s);
else
x_set_glyph_string_clipping (s);
@@ -2562,41 +2936,64 @@ x_draw_glyph_string (s)
if (s->face->underline_p
&& (s->font->bdf || !s->font->tm.tmUnderlined))
{
- unsigned long h = 1;
- unsigned long dy = 0;
+ unsigned long h;
+ int y;
+ /* Get the underline thickness. Default is 1 pixel. */
+#ifdef USE_FONT_BACKEND
+ if (enable_font_backend)
+ /* In the future, we must use information of font. */
+ h = 1;
+ else
+#endif /* USE_FONT_BACKEND */
+ h = 1;
- if (x_underline_at_descent_line)
- dy = s->height - h;
- else
+#ifdef USE_FONT_BACKEND
+ if (enable_font_backend)
+ {
+ if (s->face->font)
+ /* In the future, we must use information of font. */
+ y = s->ybase + (s->face->font->max_bounds.descent + 1) / 2;
+ else
+ y = s->y + s->height - h;
+ }
+ else
+#endif
{
- /* TODO: Use font information for positioning and thickness of
- underline. See OUTLINETEXTMETRIC, and xterm.c. Note: If
- you make this work, don't forget to change the doc string of
- x-use-underline-position-properties below. */
- dy = s->height - h;
+ y = s->y + s->height - h;
+ /* TODO: Use font information for positioning and
+ thickness of underline. See OUTLINETEXTMETRIC,
+ and xterm.c. Note: If you make this work,
+ don't forget to change the doc string of
+ x-use-underline_color-position-properties
+ below. */
+#if 0
+ if (!x_underline_at_descent_line)
+ {
+ ...
+ }
+#endif
}
if (s->face->underline_defaulted_p)
{
w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
- s->y + dy, s->background_width, 1);
+ y, s->background_width, 1);
}
else
{
w32_fill_area (s->f, s->hdc, s->face->underline_color, s->x,
- s->y + dy, s->background_width, 1);
+ y, s->background_width, 1);
}
}
-
/* Draw overline. */
if (s->face->overline_p)
{
unsigned long dy = 0, h = 1;
if (s->face->overline_color_defaulted_p)
- {
- w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
- s->y + dy, s->background_width, h);
- }
+ {
+ w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
+ s->y + dy, s->background_width, h);
+ }
else
{
w32_fill_area (s->f, s->hdc, s->face->overline_color, s->x,
@@ -2623,13 +3020,70 @@ x_draw_glyph_string (s)
}
}
- /* Draw relief. */
+ /* Draw relief if not yet drawn. */
if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
x_draw_glyph_string_box (s);
+
+ if (s->prev)
+ {
+ struct glyph_string *prev;
+
+ for (prev = s->prev; prev; prev = prev->prev)
+ if (prev->hl != s->hl
+ && prev->x + prev->width + prev->right_overhang > s->x)
+ {
+ /* As prev was drawn while clipped to its own area, we
+ must draw the right_overhang part using s->hl now. */
+ enum draw_glyphs_face save = prev->hl;
+
+ prev->hl = s->hl;
+ x_set_glyph_string_gc (prev);
+ x_set_glyph_string_clipping_exactly (s, prev);
+ if (prev->first_glyph->type == CHAR_GLYPH)
+ x_draw_glyph_string_foreground (prev);
+ else
+ x_draw_composite_glyph_string_foreground (prev);
+ w32_set_clip_rectangle (prev->hdc, NULL);
+ prev->hl = save;
+#ifdef USE_FONT_BACKEND
+ prev->num_clips = 0;
+#endif /* USE_FONT_BACKEND */
+ }
+ }
+
+ if (s->next)
+ {
+ struct glyph_string *next;
+
+ for (next = s->next; next; next = next->next)
+ if (next->hl != s->hl
+ && next->x - next->left_overhang < s->x + s->width)
+ {
+ /* As next will be drawn while clipped to its own area,
+ we must draw the left_overhang part using s->hl now. */
+ enum draw_glyphs_face save = next->hl;
+
+ next->hl = s->hl;
+ x_set_glyph_string_gc (next);
+ x_set_glyph_string_clipping_exactly (s, next);
+ if (next->first_glyph->type == CHAR_GLYPH)
+ x_draw_glyph_string_foreground (next);
+ else
+ x_draw_composite_glyph_string_foreground (next);
+ w32_set_clip_rectangle (next->hdc, NULL);
+ next->hl = save;
+#ifdef USE_FONT_BACKEND
+ next->num_clips = 0;
+#endif /* USE_FONT_BACKEND */
+ }
+ }
}
/* Reset clipping. */
w32_set_clip_rectangle (s->hdc, NULL);
+#ifdef USE_FONT_BACKEND
+ s->num_clips = 0;
+#endif /* USE_FONT_BACKEND */
}
@@ -2905,9 +3359,9 @@ x_focus_changed (type, state, dpyinfo, frame, bufp)
/* Don't stop displaying the initial startup message
for a switch-frame event we don't need. */
- if (GC_NILP (Vterminal_frame)
- && GC_CONSP (Vframe_list)
- && !GC_NILP (XCDR (Vframe_list)))
+ if (NILP (Vterminal_frame)
+ && CONSP (Vframe_list)
+ && !NILP (XCDR (Vframe_list)))
{
bufp->kind = FOCUS_IN_EVENT;
XSETFRAME (bufp->frame_or_window, frame);
@@ -2993,7 +3447,7 @@ x_frame_rehighlight (dpyinfo)
if (dpyinfo->w32_focus_frame)
{
dpyinfo->x_highlight_frame
- = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame)))
+ = ((FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame)))
? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame))
: dpyinfo->w32_focus_frame);
if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
@@ -3252,6 +3706,9 @@ note_mouse_movement (frame, msg)
memcpy (&last_mouse_motion_event, msg, sizeof (last_mouse_motion_event));
XSETFRAME (last_mouse_motion_frame, frame);
+ if (!FRAME_X_OUTPUT (frame))
+ return 0;
+
if (msg->hwnd != FRAME_W32_WINDOW (frame))
{
frame->mouse_moved = 1;
@@ -3459,15 +3916,13 @@ x_window_to_scroll_bar (window_id)
{
Lisp_Object tail;
- for (tail = Vframe_list;
- XGCTYPE (tail) == Lisp_Cons;
- tail = XCDR (tail))
+ for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
{
Lisp_Object frame, bar, condemned;
frame = XCAR (tail);
/* All elements of Vframe_list should be frames. */
- if (! GC_FRAMEP (frame))
+ if (! FRAMEP (frame))
abort ();
/* Scan this frame's scroll bar list for a scroll bar with the
@@ -3476,9 +3931,9 @@ x_window_to_scroll_bar (window_id)
for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
/* This trick allows us to search both the ordinary and
condemned scroll bar lists with one loop. */
- ! GC_NILP (bar) || (bar = condemned,
+ ! NILP (bar) || (bar = condemned,
condemned = Qnil,
- ! GC_NILP (bar));
+ ! NILP (bar));
bar = XSCROLL_BAR (bar)->next)
if (SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar)) == window_id)
return XSCROLL_BAR (bar);
@@ -3968,7 +4423,7 @@ w32_scroll_bar_handle_click (bar, msg, emacs_event)
W32Msg *msg;
struct input_event *emacs_event;
{
- if (! GC_WINDOWP (bar->window))
+ if (! WINDOWP (bar->window))
abort ();
emacs_event->kind = W32_SCROLL_BAR_CLICK_EVENT;
@@ -5304,11 +5759,16 @@ x_new_font (f, fontname)
register char *fontname;
{
struct font_info *fontp
- = FS_LOAD_FONT (f, 0, fontname, -1);
+ = FS_LOAD_FONT (f, fontname);
if (!fontp)
return Qnil;
+ if (FRAME_FONT (f) == (XFontStruct *) (fontp->font))
+ /* This font is already set in frame F. There's nothing more to
+ do. */
+ return build_string (fontp->full_name);
+
FRAME_FONT (f) = (XFontStruct *) (fontp->font);
FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
FRAME_FONTSET (f) = -1;
@@ -5342,38 +5802,112 @@ x_new_font (f, fontname)
return build_string (fontp->full_name);
}
-/* Give frame F the fontset named FONTSETNAME as its default font, and
- return the full name of that fontset. FONTSETNAME may be a wildcard
- pattern; in that case, we choose some fontset that fits the pattern.
- The return value shows which fontset we chose. */
+/* Give frame F the fontset named FONTSETNAME as its default fontset,
+ and return the full name of that fontset. FONTSETNAME may be a
+ wildcard pattern; in that case, we choose some fontset that fits
+ the pattern. FONTSETNAME may be a font name for ASCII characters;
+ in that case, we create a fontset from that font name.
+
+ The return value shows which fontset we chose.
+ If FONTSETNAME specifies the default fontset, return Qt.
+ If an ASCII font in the specified fontset can't be loaded, return
+ Qnil. */
Lisp_Object
x_new_fontset (f, fontsetname)
struct frame *f;
- char *fontsetname;
+ Lisp_Object fontsetname;
{
- int fontset = fs_query_fontset (build_string (fontsetname), 0);
+ int fontset = fs_query_fontset (fontsetname, 0);
Lisp_Object result;
- if (fontset < 0)
- return Qnil;
-
- if (FRAME_FONTSET (f) == fontset)
+ if (fontset > 0 && FRAME_FONTSET(f) == fontset)
/* This fontset is already set in frame F. There's nothing more
to do. */
return fontset_name (fontset);
+ else if (fontset == 0)
+ /* The default fontset can't be the default font. */
+ return Qt;
- result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
+ if (fontset > 0)
+ result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
+ else
+ result = x_new_font (f, SDATA (fontsetname));
if (!STRINGP (result))
/* Can't load ASCII font. */
return Qnil;
+ if (fontset < 0)
+ fontset = new_fontset_from_font_name (result);
+
/* Since x_new_font doesn't update any fontset information, do it now. */
FRAME_FONTSET(f) = fontset;
- return build_string (fontsetname);
+ return fontset_name (fontset);
+}
+
+#ifdef USE_FONT_BACKEND
+Lisp_Object
+x_new_fontset2 (f, fontset, font_object)
+ struct frame *f;
+ int fontset;
+ Lisp_Object font_object;
+{
+ struct font *font = XSAVE_VALUE (font_object)->pointer;
+
+ if (FRAME_FONT_OBJECT (f) == font)
+ /* This font is already set in frame F. There's nothing more to
+ do. */
+ return fontset_name (fontset);
+
+ BLOCK_INPUT;
+
+ FRAME_FONT_OBJECT (f) = font;
+ FRAME_FONT (f) = font->font.font;
+ FRAME_BASELINE_OFFSET (f) = font->font.baseline_offset;
+ FRAME_FONTSET (f) = fontset;
+
+ FRAME_COLUMN_WIDTH (f) = font->font.average_width;
+ FRAME_SPACE_WIDTH (f) = font->font.space_width;
+ FRAME_LINE_HEIGHT (f) = font->font.height;
+
+ compute_fringe_widths (f, 1);
+
+ /* Compute the scroll bar width in character columns. */
+ if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
+ {
+ int wid = FRAME_COLUMN_WIDTH (f);
+ FRAME_CONFIG_SCROLL_BAR_COLS (f)
+ = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid - 1) / wid;
+ }
+ else
+ {
+ int wid = FRAME_COLUMN_WIDTH (f);
+ FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
+ }
+
+ /* Now make the frame display the given font. */
+ if (FRAME_X_WINDOW (f) != 0)
+ {
+ /* Don't change the size of a tip frame; there's no point in
+ doing it because it's done in Fx_show_tip, and it leads to
+ problems because the tip frame has no widget. */
+ if (NILP (tip_frame) || XFRAME (tip_frame) != f)
+ x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
+ }
+
+#ifdef HAVE_X_I18N
+ if (FRAME_XIC (f)
+ && (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea)))
+ xic_set_xfontset (f, SDATA (fontset_ascii (fontset)));
+#endif
+
+ UNBLOCK_INPUT;
+
+ return fontset_name (fontset);
}
+#endif /* USE_FONT_BACKEND */
/***********************************************************************
@@ -5930,6 +6464,15 @@ x_free_frame_resources (f)
BLOCK_INPUT;
+#ifdef USE_FONT_BACKEND
+ /* We must free faces before destroying windows because some
+ font-driver (e.g. xft) access a window while finishing a
+ face. */
+ if (enable_font_backend
+ && FRAME_FACE_CACHE (f))
+ free_frame_faces (f);
+#endif /* USE_FONT_BACKEND */
+
if (FRAME_W32_WINDOW (f))
my_destroy_window (f, FRAME_W32_WINDOW (f));
@@ -6082,7 +6625,7 @@ x_font_min_bounds (font, w, h)
* average and maximum width, and maximum height.
*/
*h = FONT_HEIGHT (font);
- *w = FONT_WIDTH (font);
+ *w = FONT_AVG_WIDTH (font);
}
@@ -6565,13 +7108,22 @@ w32_initialize ()
AttachThreadInput (dwMainThreadId, dwWindowsThreadId, TRUE);
#endif
- /* Load system settings. */
+ /* Dynamically link to optional system components. */
{
UINT smoothing_type;
BOOL smoothing_enabled;
- /* If using proportional scroll bars, ensure handle is at least 5 pixels;
- otherwise use the fixed height. */
+ HANDLE gdi_lib = LoadLibrary ("gdi32.dll");
+
+#define LOAD_PROC(lib, fn) pfn##fn = (void *) GetProcAddress (lib, #fn)
+
+ LOAD_PROC (gdi_lib, GetFontUnicodeRanges);
+
+#undef LOAD_PROC
+
+ FreeLibrary (gdi_lib);
+
+ /* Ensure scrollbar handle is at least 5 pixels. */
vertical_scroll_bar_min_handle = 5;
/* For either kind of scroll bar, take account of the arrows; these
@@ -6612,8 +7164,7 @@ syms_of_w32term ()
staticpro (&last_mouse_scroll_bar);
last_mouse_scroll_bar = Qnil;
- staticpro (&Qvendor_specific_keysyms);
- Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
+ DEFSYM (Qvendor_specific_keysyms, "vendor-specific-keysyms");
DEFVAR_INT ("w32-num-mouse-buttons",
&w32_num_mouse_buttons,