/* Implementation of GUI terminal on the Microsoft W32 API.
- Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999, 2000, 2001
+ Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999, 2000, 2001, 2005
Free Software Foundation, Inc.
This file is part of GNU Emacs.
#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"
#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>
#define abs(x) ((x) < 0 ? -(x) : (x))
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.
static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int,
enum text_cursor_kinds));
-static void w32_clip_to_row P_ ((struct window *, struct glyph_row *, HDC));
+static void w32_clip_to_row P_ ((struct window *, struct glyph_row *, int, HDC));
static Lisp_Object Qvendor_specific_keysyms;
int oldVH = row->visible_height;
row->visible_height = p->h;
row->y -= rowY - p->y;
- w32_clip_to_row (w, row, hdc);
+ w32_clip_to_row (w, row, -1, hdc);
row->y = oldY;
row->visible_height = oldVH;
}
else
- w32_clip_to_row (w, row, hdc);
+ w32_clip_to_row (w, row, -1, hdc);
if (p->bx >= 0 && !p->overlay_p)
{
/* Function prototypes of this page. */
-static XCharStruct *w32_per_char_metric P_ ((XFontStruct *,
- wchar_t *, int));
-static int w32_encode_char P_ ((int, wchar_t *, struct font_info *, int *));
+XCharStruct *w32_per_char_metric P_ ((XFontStruct *, wchar_t *, 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.
}
-static XCharStruct *
+XCharStruct *
w32_per_char_metric (font, char2b, font_type)
XFontStruct *font;
wchar_t *char2b;
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;
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. */
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;
+ int code = (int) (*char2b);
- ENCODE_SJIS (XCHAR2B_BYTE1 (char2b), XCHAR2B_BYTE2 (char2b),
- sjis1, sjis2);
- STORE_XCHAR2B (char2b, sjis1, sjis2);
+ JIS_TO_SJIS (code);
+ STORE_XCHAR2B (char2b, (code >> 8), (code & 0xFF));
}
}
- codepage = font_info->codepage;
-
- /* 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);
- }
- unicode_p = 1;
- internal_two_byte_p = 1;
- }
if (two_byte_p)
*two_byte_p = internal_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;
+
+ 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)
+ char_table_set_range (table, min_byte2, max_byte2, 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)
+ {
+ char_table_set_range (table, from, i - 1, Qt);
+ from = -1;
+ }
+ }
+ else if (from < 0)
+ from = i;
+ }
+ if (from >= 0)
+ char_table_set_range (table, from, i - 1, Qt);
+ }
+ }
+ else
+ {
+ if (! font->per_char || font->all_chars_exist == True)
+ {
+ int i;
+
+ for (i = min_byte1; i <= max_byte1; i++)
+ char_table_set_range (table,
+ (i << 8) | min_byte2, (i << 8) | max_byte2,
+ 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)
+ {
+ char_table_set_range (table, (i << 8) | from,
+ (i << 8) | (j - 1), Qt);
+ from = -1;
+ }
+ }
+ else if (from < 0)
+ from = j;
+ }
+ if (from >= 0)
+ char_table_set_range (table, (i << 8) | from,
+ (i << 8) | (j - 1), Qt);
+ }
+ }
+ }
+#endif
+ return table;
+}
+
\f
/***********************************************************************
Glyph display
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);
struct glyph *last_glyph;
RECT clip_rect;
- last_x = window_box_right (s->w, s->area);
- if (s->row->full_width_p
- && !s->w->pseudo_window_p)
- {
- last_x += WINDOW_RIGHT_SCROLL_BAR_AREA_WIDTH (s->w);
- if (s->area != RIGHT_MARGIN_AREA
- || WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (s->w))
- last_x += WINDOW_RIGHT_FRINGE_WIDTH (s->w);
- }
+ last_x = ((s->row->full_width_p && !s->w->pseudo_window_p)
+ ? WINDOW_RIGHT_EDGE_X (s->w)
+ : window_box_right (s->w, s->area));
/* The glyph that may have a right box line. */
last_glyph = (s->cmp || s->img
mode lines must be clipped to the whole window. */
static void
-w32_clip_to_row (w, row, hdc)
+w32_clip_to_row (w, row, area, hdc)
struct window *w;
struct glyph_row *row;
+ int area;
HDC hdc;
{
struct frame *f = XFRAME (WINDOW_FRAME (w));
RECT clip_rect;
- int window_y, window_width;
+ int window_x, window_y, window_width;
- window_box (w, -1, 0, &window_y, &window_width, 0);
+ window_box (w, area, &window_x, &window_y, &window_width, 0);
- clip_rect.left = WINDOW_TO_FRAME_PIXEL_X (w, 0);
+ clip_rect.left = window_x;
clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
clip_rect.top = max (clip_rect.top, window_y);
clip_rect.right = clip_rect.left + window_width;
struct frame *f = XFRAME (WINDOW_FRAME (w));
HDC hdc;
RECT rect;
- int wd, h;
+ int h;
struct glyph *cursor_glyph;
HBRUSH hb = CreateSolidBrush (f->output_data.w32->cursor_pixel);
if (cursor_glyph == NULL)
return;
- /* Compute frame-relative coordinates from window-relative
- coordinates. */
+ /* Compute frame-relative coordinates for phys cursor. */
rect.left = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
- rect.top = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
- + row->ascent - w->phys_cursor_ascent);
-
- /* Compute the proper height and ascent of the rectangle, based
- on the actual glyph. Using the full height of the row looks
- bad when there are tall images on that row. */
- h = max (min (FRAME_LINE_HEIGHT (f), row->height),
- cursor_glyph->ascent + cursor_glyph->descent);
- if (h < row->height)
- rect.top += row->ascent /* - w->phys_cursor_ascent */ + cursor_glyph->descent - h;
- h--;
-
+ rect.top = get_phys_cursor_geometry (w, row, cursor_glyph, &h);
rect.bottom = rect.top + h;
+ rect.right = rect.left + w->phys_cursor_width;
- /* Compute the width of the rectangle to draw. If on a stretch
- glyph, and `x-stretch-block-cursor' is nil, don't draw a
- rectangle as wide as the glyph, but use a canonical character
- width instead. */
- wd = cursor_glyph->pixel_width; /* TODO: Why off by one compared with X? */
- if (cursor_glyph->type == STRETCH_GLYPH
- && !x_stretch_cursor_p)
- wd = min (FRAME_COLUMN_WIDTH (f), wd);
- w->phys_cursor_width = wd;
-
- rect.right = rect.left + wd;
hdc = get_frame_dc (f);
/* Set clipping, draw the rectangle, and reset clipping again. */
- w32_clip_to_row (w, row, hdc);
+ w32_clip_to_row (w, row, TEXT_AREA, hdc);
FrameRect (hdc, &rect, hb);
DeleteObject (hb);
w32_set_clip_rectangle (hdc, NULL);
hdc = get_frame_dc (f);
- w32_clip_to_row (w, row, hdc);
+ w32_clip_to_row (w, row, TEXT_AREA, hdc);
if (kind == BAR_CURSOR)
{
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;
- FRAME_COLUMN_WIDTH (f) = FONT_WIDTH (FRAME_FONT (f));
+ FRAME_COLUMN_WIDTH (f) = fontp->average_width;
+ FRAME_SPACE_WIDTH (f) = fontp->space_width;
FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (FRAME_FONT (f));
compute_fringe_widths (f, 1);
return build_string (fontp->full_name);
}
\f
-/* 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);
}
\f
x_calc_absolute_position (f)
struct frame *f;
{
- POINT pt;
int flags = f->size_hint_flags;
- pt.x = pt.y = 0;
-
- /* Find the position of the outside upper-left corner of
- the inner window, with respect to the outer window.
- But do this only if we will need the results. */
- if (f->output_data.w32->parent_desc != FRAME_W32_DISPLAY_INFO (f)->root_window)
- {
- BLOCK_INPUT;
- MapWindowPoints (FRAME_W32_WINDOW (f),
- f->output_data.w32->parent_desc,
- &pt, 1);
- UNBLOCK_INPUT;
- }
-
- {
- RECT rt;
- rt.left = rt.right = rt.top = rt.bottom = 0;
-
- BLOCK_INPUT;
- AdjustWindowRect(&rt, f->output_data.w32->dwStyle,
- FRAME_EXTERNAL_MENU_BAR (f));
- UNBLOCK_INPUT;
-
- pt.x += (rt.right - rt.left);
- pt.y += (rt.bottom - rt.top);
- }
-
/* Treat negative positions as relative to the leftmost bottommost
position that fits on the screen. */
if (flags & XNegative)
f->left_pos = (FRAME_W32_DISPLAY_INFO (f)->width
- - 2 * f->border_width - pt.x
- FRAME_PIXEL_WIDTH (f)
+ f->left_pos);
if (flags & YNegative)
f->top_pos = (FRAME_W32_DISPLAY_INFO (f)->height
- - 2 * f->border_width - pt.y
- FRAME_PIXEL_HEIGHT (f)
+ f->top_pos);
/* The left_pos and top_pos
/* Dynamically link to optional system components. */
{
HANDLE user_lib = LoadLibrary ("user32.dll");
+ HANDLE gdi_lib = LoadLibrary ("gdi32.dll");
-#define LOAD_PROC(fn) pfn##fn = (void *) GetProcAddress (user_lib, #fn)
+#define LOAD_PROC(lib, fn) pfn##fn = (void *) GetProcAddress (lib, #fn)
/* New proportional scroll bar functions. */
- LOAD_PROC (SetScrollInfo);
- LOAD_PROC (GetScrollInfo);
-
+ LOAD_PROC (user_lib, SetScrollInfo);
+ LOAD_PROC (user_lib, GetScrollInfo);
+ LOAD_PROC (gdi_lib, GetFontUnicodeRanges);
+
#undef LOAD_PROC
FreeLibrary (user_lib);
+ FreeLibrary (gdi_lib);
/* If using proportional scroll bars, ensure handle is at least 5 pixels;
otherwise use the fixed height. */