#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 RECT last_mouse_glyph;
static Lisp_Object last_mouse_press_frame;
-Lisp_Object Vw32_num_mouse_buttons;
+int w32_num_mouse_buttons;
Lisp_Object Vw32_swap_mouse_buttons;
extern Lisp_Object Vcommand_line_args, Vsystem_name;
-extern Lisp_Object Qface, Qmouse_face;
-
#ifndef USE_CRT_DLL
extern int errno;
#endif
output_cursor.x, output_cursor.y);
x_draw_vertical_border (w);
+
+ draw_window_fringes (w);
+
UNBLOCK_INPUT;
}
xassert (w);
if (!desired_row->mode_line_p && !w->pseudo_window_p)
- {
- BLOCK_INPUT;
- draw_row_fringe_bitmaps (w, desired_row);
- UNBLOCK_INPUT;
- }
+ desired_row->redraw_fringe_bitmaps_p = 1;
/* When a window has disappeared, make sure that no rest of
full-width rows stays visible in the internal border. Could
struct frame *f = XFRAME (WINDOW_FRAME (w));
HDC hdc;
struct face *face = p->face;
+ int rowY;
hdc = get_frame_dc (f);
/* Must clip because of partially visible lines. */
- w32_clip_to_row (w, row, hdc);
+ rowY = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
+ if (p->y < rowY)
+ {
+ /* Adjust position of "bottom aligned" bitmap on partially
+ visible last row. */
+ int oldY = row->y;
+ int oldVH = row->visible_height;
+ row->visible_height = p->h;
+ row->y -= rowY - p->y;
+ w32_clip_to_row (w, row, hdc);
+ row->y = oldY;
+ row->visible_height = oldVH;
+ }
+ else
+ w32_clip_to_row (w, row, hdc);
- if (p->bx >= 0)
+ if (p->bx >= 0 && !p->overlay_p)
{
w32_fill_area (f, hdc, face->background,
p->bx, p->by, p->nx, p->ny);
}
- if (p->which != NO_FRINGE_BITMAP)
+ if (p->which)
{
HBITMAP pixmap = fringe_bmp[p->which];
HDC compat_hdc;
HANDLE horig_obj;
compat_hdc = CreateCompatibleDC (hdc);
+
SaveDC (hdc);
horig_obj = SelectObject (compat_hdc, pixmap);
- SetTextColor (hdc, face->background);
- SetBkColor (hdc, face->foreground);
- BitBlt (hdc, p->x, p->y, p->wd, p->h,
- compat_hdc, 0, p->dh,
- SRCCOPY);
+ /* Paint overlays transparently. */
+ if (p->overlay_p)
+ {
+ HBRUSH h_brush, h_orig_brush;
+
+ SetTextColor (hdc, BLACK_PIX_DEFAULT (f));
+ SetBkColor (hdc, WHITE_PIX_DEFAULT (f));
+ h_brush = CreateSolidBrush (face->foreground);
+ h_orig_brush = SelectObject (hdc, h_brush);
+
+ BitBlt (hdc, p->x, p->y, p->wd, p->h,
+ compat_hdc, 0, p->dh,
+ DSTINVERT);
+ BitBlt (hdc, p->x, p->y, p->wd, p->h,
+ compat_hdc, 0, p->dh,
+ 0x2E064A);
+ BitBlt (hdc, p->x, p->y, p->wd, p->h,
+ compat_hdc, 0, p->dh,
+ DSTINVERT);
+
+ SelectObject (hdc, h_orig_brush);
+ DeleteObject (h_brush);
+ }
+ else
+ {
+ SetTextColor (hdc, face->background);
+ SetBkColor (hdc, (p->cursor_p
+ ? f->output_data.w32->cursor_pixel
+ : face->foreground));
+
+ BitBlt (hdc, p->x, p->y, p->wd, p->h,
+ compat_hdc, 0, p->dh,
+ SRCCOPY);
+ }
SelectObject (compat_hdc, horig_obj);
DeleteDC (compat_hdc);
release_frame_dc (f, hdc);
}
+static void
+w32_define_fringe_bitmap (which, bits, h, wd)
+ int which;
+ unsigned short *bits;
+ int h, wd;
+{
+ fringe_bmp[which] = CreateBitmap (wd, h, 1, 1, bits);
+}
+
+static void
+w32_destroy_fringe_bitmap (which)
+ int which;
+{
+ if (fringe_bmp[which])
+ DeleteObject (fringe_bmp[which]);
+ fringe_bmp[which] = 0;
+}
+
+
\f
/* This is called when starting Emacs and when restarting after
suspend. When starting Emacs, no window is mapped. And nothing
static 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.
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
wchar_t * chars;
int nchars;
{
- int charset_dim = w32_font_is_double_byte (s->gc->font) ? 2 : 1;
- if (s->gc->font->bdf)
- w32_BDF_TextOut (s->gc->font->bdf, s->hdc,
+ int charset_dim = w32_font_is_double_byte (s->font) ? 2 : 1;
+ if (s->font->bdf)
+ w32_BDF_TextOut (s->font->bdf, s->hdc,
x, y, (char *) chars, charset_dim,
nchars * charset_dim, 0);
else if (s->first_glyph->font_type == UNICODE_FONT)
static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
int, int, int));
static void w32_draw_relief_rect P_ ((struct frame *, int, int, int, int,
- int, int, int, int, RECT *));
+ int, int, int, int, int, int,
+ RECT *));
static void w32_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
int, int, int, RECT *));
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);
static void
w32_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
- raised_p, left_p, right_p, clip_rect)
+ raised_p, top_p, bot_p, left_p, right_p, clip_rect)
struct frame *f;
- int left_x, top_y, right_x, bottom_y, width, left_p, right_p, raised_p;
+ int left_x, top_y, right_x, bottom_y, width;
+ int top_p, bot_p, left_p, right_p, raised_p;
RECT *clip_rect;
{
int i;
w32_set_clip_rectangle (hdc, clip_rect);
/* Top. */
- for (i = 0; i < width; ++i)
- w32_fill_area (f, hdc, gc.foreground,
- left_x + i * left_p, top_y + i,
- right_x - left_x - i * (left_p + right_p ) + 1, 1);
+ if (top_p)
+ for (i = 0; i < width; ++i)
+ w32_fill_area (f, hdc, gc.foreground,
+ left_x + i * left_p, top_y + i,
+ right_x - left_x - i * (left_p + right_p ) + 1, 1);
/* Left. */
if (left_p)
gc.foreground = f->output_data.w32->white_relief.gc->foreground;
/* Bottom. */
- for (i = 0; i < width; ++i)
- w32_fill_area (f, hdc, gc.foreground,
- left_x + i * left_p, bottom_y - i,
- right_x - left_x - i * (left_p + right_p) + 1, 1);
+ if (bot_p)
+ for (i = 0; i < width; ++i)
+ w32_fill_area (f, hdc, gc.foreground,
+ left_x + i * left_p, bottom_y - i,
+ right_x - left_x - i * (left_p + right_p) + 1, 1);
/* Right. */
if (right_p)
{
x_setup_relief_colors (s);
w32_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
- width, raised_p, left_p, right_p, &clip_rect);
+ width, raised_p, 1, 1, left_p, right_p, &clip_rect);
}
}
x_draw_image_foreground (s)
struct glyph_string *s;
{
- int x;
- int y = s->ybase - image_ascent (s->img, s->face);
+ int x = s->x;
+ int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
/* If first glyph of S has a left box line, start drawing it to the
right of that line. */
if (s->face->box != FACE_NO_BOX
- && s->first_glyph->left_box_line_p)
- x = s->x + abs (s->face->box_line_width);
- else
- x = s->x;
+ && s->first_glyph->left_box_line_p
+ && s->slice.x == 0)
+ x += abs (s->face->box_line_width);
/* If there is a margin around the image, adjust x- and y-position
by that margin. */
- x += s->img->hmargin;
- y += s->img->vmargin;
+ if (s->slice.x == 0)
+ x += s->img->hmargin;
+ if (s->slice.y == 0)
+ y += s->img->vmargin;
SaveDC (s->hdc);
SetTextColor (s->hdc, RGB (255, 255, 255));
SetBkColor (s->hdc, RGB (0, 0, 0));
- BitBlt (s->hdc, x, y, s->img->width, s->img->height,
- compat_hdc, 0, 0, SRCINVERT);
- BitBlt (s->hdc, x, y, s->img->width, s->img->height,
- mask_dc, 0, 0, SRCAND);
- BitBlt (s->hdc, x, y, s->img->width, s->img->height,
- compat_hdc, 0, 0, SRCINVERT);
+ BitBlt (s->hdc, x, y, s->slice.width, s->slice.height,
+ compat_hdc, s->slice.x, s->slice.y, SRCINVERT);
+ BitBlt (s->hdc, x, y, s->slice.width, s->slice.height,
+ mask_dc, s->slice.x, s->slice.y, SRCAND);
+ BitBlt (s->hdc, x, y, s->slice.width, s->slice.height,
+ compat_hdc, s->slice.x, s->slice.y, SRCINVERT);
SelectObject (mask_dc, mask_orig_obj);
DeleteDC (mask_dc);
SetTextColor (s->hdc, s->gc->foreground);
SetBkColor (s->hdc, s->gc->background);
- BitBlt (s->hdc, x, y, s->img->width, s->img->height,
- compat_hdc, 0, 0, SRCCOPY);
+ BitBlt (s->hdc, x, y, s->slice.width, s->slice.height,
+ compat_hdc, s->slice.x, s->slice.y, SRCCOPY);
/* When the image has a mask, we can expect that at
least part of a mouse highlight or a block cursor will
int r = s->img->relief;
if (r < 0) r = -r;
w32_draw_rectangle (s->hdc, s->gc, x - r, y - r ,
- s->img->width + r*2 - 1, s->img->height + r*2 - 1);
+ s->slice.width + r*2 - 1,
+ s->slice.height + r*2 - 1);
}
}
DeleteDC (compat_hdc);
}
else
- w32_draw_rectangle (s->hdc, s->gc, x, y, s->img->width -1,
- s->img->height - 1);
+ w32_draw_rectangle (s->hdc, s->gc, x, y,
+ s->slice.width - 1, s->slice.height - 1);
RestoreDC (s->hdc ,-1);
}
{
int x0, y0, x1, y1, thick, raised_p;
RECT r;
- int x;
- int y = s->ybase - image_ascent (s->img, s->face);
+ int x = s->x;
+ int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
/* If first glyph of S has a left box line, start drawing it to the
right of that line. */
if (s->face->box != FACE_NO_BOX
- && s->first_glyph->left_box_line_p)
- x = s->x + abs (s->face->box_line_width);
- else
- x = s->x;
+ && s->first_glyph->left_box_line_p
+ && s->slice.x == 0)
+ x += abs (s->face->box_line_width);
/* If there is a margin around the image, adjust x- and y-position
by that margin. */
- x += s->img->hmargin;
- y += s->img->vmargin;
+ if (s->slice.x == 0)
+ x += s->img->hmargin;
+ if (s->slice.y == 0)
+ y += s->img->vmargin;
if (s->hl == DRAW_IMAGE_SUNKEN
|| s->hl == DRAW_IMAGE_RAISED)
x0 = x - thick;
y0 = y - thick;
- x1 = x + s->img->width + thick - 1;
- y1 = y + s->img->height + thick - 1;
+ x1 = x + s->slice.width + thick - 1;
+ y1 = y + s->slice.height + thick - 1;
x_setup_relief_colors (s);
get_glyph_string_clip_rect (s, &r);
- w32_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
+ w32_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p,
+ s->slice.y == 0,
+ s->slice.y + s->slice.height == s->img->height,
+ s->slice.x == 0,
+ s->slice.x + s->slice.width == s->img->width,
+ &r);
}
{
HDC hdc = CreateCompatibleDC (s->hdc);
HGDIOBJ orig_hdc_obj = SelectObject (hdc, pixmap);
- int x;
- int y = s->ybase - s->y - image_ascent (s->img, s->face);
+ int x = 0;
+ int y = s->ybase - s->y - image_ascent (s->img, s->face, &s->slice);
/* If first glyph of S has a left box line, start drawing it to the
right of that line. */
if (s->face->box != FACE_NO_BOX
- && s->first_glyph->left_box_line_p)
- x = abs (s->face->box_line_width);
- else
- x = 0;
+ && s->first_glyph->left_box_line_p
+ && s->slice.x == 0)
+ x += abs (s->face->box_line_width);
/* If there is a margin around the image, adjust x- and y-position
by that margin. */
- x += s->img->hmargin;
- y += s->img->vmargin;
+ if (s->slice.x == 0)
+ x += s->img->hmargin;
+ if (s->slice.y == 0)
+ y += s->img->vmargin;
if (s->img->pixmap)
{
SetTextColor (hdc, RGB (0, 0, 0));
SetBkColor (hdc, RGB (255, 255, 255));
- BitBlt (hdc, x, y, s->img->width, s->img->height,
- compat_hdc, 0, 0, SRCINVERT);
- BitBlt (hdc, x, y, s->img->width, s->img->height,
- mask_dc, 0, 0, SRCAND);
- BitBlt (hdc, x, y, s->img->width, s->img->height,
- compat_hdc, 0, 0, SRCINVERT);
+ BitBlt (hdc, x, y, s->slice.width, s->slice.height,
+ compat_hdc, s->slice.x, s->slice.y, SRCINVERT);
+ BitBlt (hdc, x, y, s->slice.width, s->slice.height,
+ mask_dc, s->slice.x, s->slice.y, SRCAND);
+ BitBlt (hdc, x, y, s->slice.width, s->slice.height,
+ compat_hdc, s->slice.x, s->slice.y, SRCINVERT);
SelectObject (mask_dc, mask_orig_obj);
DeleteDC (mask_dc);
SetTextColor (hdc, s->gc->foreground);
SetBkColor (hdc, s->gc->background);
- BitBlt (hdc, x, y, s->img->width, s->img->height,
- compat_hdc, 0, 0, SRCCOPY);
+ BitBlt (hdc, x, y, s->slice.width, s->slice.height,
+ compat_hdc, s->slice.x, s->slice.y, SRCCOPY);
/* When the image has a mask, we can expect that at
least part of a mouse highlight or a block cursor will
{
int r = s->img->relief;
if (r < 0) r = -r;
- w32_draw_rectangle (hdc, s->gc, x - r, y - r ,
- s->img->width + r*2 - 1, s->img->height + r*2 - 1);
+ w32_draw_rectangle (hdc, s->gc, x - r, y - r,
+ s->slice.width + r*2 - 1,
+ s->slice.height + r*2 - 1);
}
}
DeleteDC (compat_hdc);
}
else
- w32_draw_rectangle (hdc, s->gc, x, y, s->img->width - 1,
- s->img->height - 1);
+ w32_draw_rectangle (hdc, s->gc, x, y,
+ s->slice.width - 1, s->slice.height - 1);
SelectObject (hdc, orig_hdc_obj);
DeleteDC (hdc);
taller than image or if image has a clip mask to reduce
flickering. */
s->stippled_p = s->face->stipple != 0;
- if (height > s->img->height
+ if (height > s->slice.height
|| s->img->hmargin
|| s->img->vmargin
|| s->img->mask
|| s->img->pixmap == 0
|| s->width != s->background_width)
{
- if (box_line_hwidth && s->first_glyph->left_box_line_p)
- x = s->x + box_line_hwidth;
- else
- x = s->x;
+ x = s->x;
+ if (s->first_glyph->left_box_line_p
+ && s->slice.x == 0)
+ x += box_line_hwidth;
+
+ y = s->y;
+ if (s->slice.y == 0)
+ y += box_line_vwidth;
- y = s->y + box_line_vwidth;
#if 0 /* TODO: figure out if we need to do this on Windows. */
if (s->img->mask)
{
This routine is called by the SIGIO handler.
We return as soon as there are no more events to be read.
- Events representing keys are stored in buffer BUFP,
- which can hold up to NUMCHARS characters.
We return the number of characters stored into the buffer,
thus pretending to be `read'.
*/
int
-w32_read_socket (sd, bufp, numchars, expected)
+w32_read_socket (sd, expected, hold_quit)
register int sd;
- /* register */ struct input_event *bufp;
- /* register */ int numchars;
int expected;
+ struct input_event *hold_quit;
{
int count = 0;
int check_visibility = 0;
/* So people can tell when we have read the available input. */
input_signal_count++;
- if (numchars <= 0)
- abort (); /* Don't think this happens. */
-
- /* TODO: tool-bars, ghostscript integration, mouse
- cursors. */
+ /* TODO: ghostscript integration. */
while (get_next_msg (&msg, FALSE))
{
+ struct input_event inev;
+ int do_help = 0;
+
+ EVENT_INIT (inev);
+ inev.kind = NO_EVENT;
+ inev.arg = Qnil;
+
switch (msg.msg.message)
{
case WM_PAINT:
visibility changes properly. */
if (f->iconified)
{
- bufp->kind = DEICONIFY_EVENT;
- XSETFRAME (bufp->frame_or_window, f);
- bufp->arg = Qnil;
- bufp++;
- count++;
- numchars--;
+ inev.kind = DEICONIFY_EVENT;
+ XSETFRAME (inev.frame_or_window, f);
}
else if (! NILP (Vframe_list)
&& ! NILP (XCDR (Vframe_list)))
if (f)
{
- if (numchars == 0)
- abort ();
-
- bufp->kind = LANGUAGE_CHANGE_EVENT;
- XSETFRAME (bufp->frame_or_window, f);
- bufp->arg = Qnil;
- bufp->code = msg.msg.wParam;
- bufp->modifiers = msg.msg.lParam & 0xffff;
- bufp++;
- count++;
- numchars--;
+ inev.kind = LANGUAGE_CHANGE_EVENT;
+ XSETFRAME (inev.frame_or_window, f);
+ inev.code = msg.msg.wParam;
+ inev.modifiers = msg.msg.lParam & 0xffff;
}
break;
{
if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
{
- dpyinfo->mouse_face_hidden = 1;
clear_mouse_face (dpyinfo);
+ dpyinfo->mouse_face_hidden = 1;
}
if (temp_index == sizeof temp_buffer / sizeof (short))
temp_index = 0;
temp_buffer[temp_index++] = msg.msg.wParam;
- bufp->kind = NON_ASCII_KEYSTROKE_EVENT;
- bufp->code = msg.msg.wParam;
- bufp->modifiers = msg.dwModifiers;
- XSETFRAME (bufp->frame_or_window, f);
- bufp->arg = Qnil;
- bufp->timestamp = msg.msg.time;
- bufp++;
- numchars--;
- count++;
+ inev.kind = NON_ASCII_KEYSTROKE_EVENT;
+ inev.code = msg.msg.wParam;
+ inev.modifiers = msg.dwModifiers;
+ XSETFRAME (inev.frame_or_window, f);
+ inev.timestamp = msg.msg.time;
}
break;
{
if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
{
- dpyinfo->mouse_face_hidden = 1;
clear_mouse_face (dpyinfo);
+ dpyinfo->mouse_face_hidden = 1;
}
if (temp_index == sizeof temp_buffer / sizeof (short))
temp_index = 0;
temp_buffer[temp_index++] = msg.msg.wParam;
- bufp->kind = ASCII_KEYSTROKE_EVENT;
- bufp->code = msg.msg.wParam;
- bufp->modifiers = msg.dwModifiers;
- XSETFRAME (bufp->frame_or_window, f);
- bufp->arg = Qnil;
- bufp->timestamp = msg.msg.time;
- bufp++;
- numchars--;
- count++;
+ inev.kind = ASCII_KEYSTROKE_EVENT;
+ inev.code = msg.msg.wParam;
+ inev.modifiers = msg.dwModifiers;
+ XSETFRAME (inev.frame_or_window, f);
+ inev.timestamp = msg.msg.time;
}
break;
iff it is active. */
if (WINDOWP(window)
&& !EQ (window, last_window)
- && !EQ (window, selected_window)
- && numchars > 0)
+ && !EQ (window, selected_window))
{
- bufp->kind = SELECT_WINDOW_EVENT;
- bufp->frame_or_window = window;
- bufp->arg = Qnil;
- ++bufp, ++count, --numchars;
+ inev.kind = SELECT_WINDOW_EVENT;
+ inev.frame_or_window = window;
}
last_window=window;
/* If the contents of the global variable help_echo_string
has changed, generate a HELP_EVENT. */
+#if 0 /* The below is an invalid comparison when USE_LISP_UNION_TYPE.
+ But it was originally changed to this to fix a bug, so I have
+ not removed it completely in case the bug is still there. */
if (help_echo_string != previous_help_echo_string ||
(!NILP (help_echo_string) && !STRINGP (help_echo_string) && f->mouse_moved))
- {
- Lisp_Object frame;
- int n;
-
- if (help_echo_string == Qnil)
- {
- help_echo_object = help_echo_window = Qnil;
- help_echo_pos = -1;
- }
-
- if (f)
- XSETFRAME (frame, f);
- else
- frame = Qnil;
-
- any_help_event_p = 1;
- n = gen_help_event (bufp, numchars, help_echo_string, frame,
- help_echo_window, help_echo_object,
- help_echo_pos);
- bufp += n, count += n, numchars -= n;
- }
+#else /* This is what xterm.c does. */
+ if (!NILP (help_echo_string)
+ || !NILP (previous_help_echo_string))
+ do_help = 1;
+#endif
break;
case WM_LBUTTONDOWN:
{
/* If we decide we want to generate an event to be seen
by the rest of Emacs, we put it here. */
- struct input_event emacs_event;
int tool_bar_p = 0;
int button;
int up;
- emacs_event.kind = NO_EVENT;
-
if (dpyinfo->grabbed && last_mouse_frame
&& FRAME_LIVE_P (last_mouse_frame))
f = last_mouse_frame;
if (f)
{
- construct_mouse_click (&emacs_event, &msg, f);
+ construct_mouse_click (&inev, &msg, f);
/* Is this in the tool-bar? */
if (WINDOWP (f->tool_bar_window)
&& WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)))
{
Lisp_Object window;
- int x = XFASTINT (emacs_event.x);
- int y = XFASTINT (emacs_event.y);
+ int x = XFASTINT (inev.x);
+ int y = XFASTINT (inev.y);
window = window_from_coordinates (f, x, y, 0, 0, 0, 1);
if (EQ (window, f->tool_bar_window))
{
- w32_handle_tool_bar_click (f, &emacs_event);
+ w32_handle_tool_bar_click (f, &inev);
tool_bar_p = 1;
}
}
- if (!tool_bar_p)
- if (!dpyinfo->w32_focus_frame
- || f == dpyinfo->w32_focus_frame
- && (numchars >= 1))
- {
- construct_mouse_click (bufp, &msg, f);
- bufp++;
- count++;
- numchars--;
- }
+ if (tool_bar_p
+ || (dpyinfo->w32_focus_frame
+ && f != dpyinfo->w32_focus_frame))
+ inev.kind = NO_EVENT;
}
parse_button (msg.msg.message, HIWORD (msg.msg.wParam),
if (f)
{
- if ((!dpyinfo->w32_focus_frame
- || f == dpyinfo->w32_focus_frame)
- && (numchars >= 1))
+ if (!dpyinfo->w32_focus_frame
+ || f == dpyinfo->w32_focus_frame)
{
/* Emit an Emacs wheel-up/down event. */
- construct_mouse_wheel (bufp, &msg, f);
- bufp++;
- count++;
- numchars--;
+ construct_mouse_wheel (&inev, &msg, f);
}
/* Ignore any mouse motion that happened before this
event; any subsequent mouse-movement Emacs events
f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
if (f)
- {
- construct_drag_n_drop (bufp, &msg, f);
- bufp++;
- count++;
- numchars--;
- }
+ construct_drag_n_drop (&inev, &msg, f);
break;
case WM_VSCROLL:
struct scroll_bar *bar =
x_window_to_scroll_bar ((HWND)msg.msg.lParam);
- if (bar && numchars >= 1)
- {
- if (w32_scroll_bar_handle_click (bar, &msg, bufp))
- {
- bufp++;
- count++;
- numchars--;
- }
- }
+ if (bar)
+ w32_scroll_bar_handle_click (bar, &msg, &inev);
break;
}
f->async_visible = 0;
f->async_iconified = 1;
- bufp->kind = ICONIFY_EVENT;
- XSETFRAME (bufp->frame_or_window, f);
- bufp->arg = Qnil;
- bufp++;
- count++;
- numchars--;
+ inev.kind = ICONIFY_EVENT;
+ XSETFRAME (inev.frame_or_window, f);
break;
case SIZE_MAXIMIZED:
f->left_pos = x;
f->top_pos = y;
- bufp->kind = DEICONIFY_EVENT;
- XSETFRAME (bufp->frame_or_window, f);
- bufp->arg = Qnil;
- bufp++;
- count++;
- numchars--;
+ inev.kind = DEICONIFY_EVENT;
+ XSETFRAME (inev.frame_or_window, f);
}
else if (! NILP (Vframe_list)
&& ! NILP (XCDR (Vframe_list)))
Otherwise, the startup message is cleared when
the mouse leaves the frame. */
if (any_help_event_p)
- {
- Lisp_Object frame;
- int n;
-
- XSETFRAME (frame, f);
- help_echo_string = Qnil;
- n = gen_help_event (bufp, numchars,
- Qnil, frame, Qnil, Qnil, 0);
- bufp += n, count += n, numchars -= n;
- }
+ do_help = -1;
}
break;
Otherwise, the startup message is cleared when
the mouse leaves the frame. */
if (any_help_event_p)
- {
- Lisp_Object frame;
- int n;
-
- XSETFRAME (frame, f);
- help_echo_string = Qnil;
- n = gen_help_event (bufp, numchars,
- Qnil, frame, Qnil, Qnil, 0);
- bufp += n, count += n, numchars -=n;
- }
+ do_help = -1;
}
dpyinfo->grabbed = 0;
if (f)
{
- if (numchars == 0)
- abort ();
-
- bufp->kind = DELETE_WINDOW_EVENT;
- XSETFRAME (bufp->frame_or_window, f);
- bufp->arg = Qnil;
- bufp++;
- count++;
- numchars--;
+ inev.kind = DELETE_WINDOW_EVENT;
+ XSETFRAME (inev.frame_or_window, f);
}
break;
if (f)
{
- if (numchars == 0)
- abort ();
-
- bufp->kind = MENU_BAR_ACTIVATE_EVENT;
- XSETFRAME (bufp->frame_or_window, f);
- bufp->arg = Qnil;
- bufp++;
- count++;
- numchars--;
+ inev.kind = MENU_BAR_ACTIVATE_EVENT;
+ XSETFRAME (inev.frame_or_window, f);
}
break;
}
break;
}
+
+ if (inev.kind != NO_EVENT)
+ {
+ kbd_buffer_store_event_hold (&inev, hold_quit);
+ count++;
+ }
+
+ if (do_help
+ && !(hold_quit && hold_quit->kind != NO_EVENT))
+ {
+ Lisp_Object frame;
+
+ if (f)
+ XSETFRAME (frame, f);
+ else
+ frame = Qnil;
+
+ if (do_help > 0)
+ {
+ if (NILP (help_echo_string))
+ {
+ help_echo_object = help_echo_window = Qnil;
+ help_echo_pos = -1;
+ }
+
+ any_help_event_p = 1;
+ gen_help_event (help_echo_string, frame, help_echo_window,
+ help_echo_object, help_echo_pos);
+ }
+ else
+ {
+ help_echo_string = Qnil;
+ gen_help_event (Qnil, frame, Qnil, Qnil, 0);
+ }
+ count++;
+ }
}
/* If the focus was just given to an autoraising frame,
struct frame *f = XFRAME (WINDOW_FRAME (w));
HDC hdc;
RECT rect;
- int wd;
+ int wd, h;
struct glyph *cursor_glyph;
HBRUSH hb = CreateSolidBrush (f->output_data.w32->cursor_pixel);
+ /* Get the glyph the cursor is on. If we can't tell because
+ the current matrix is invalid or such, give up. */
+ cursor_glyph = get_phys_cursor_glyph (w);
+ if (cursor_glyph == NULL)
+ return;
+
/* Compute frame-relative coordinates from window-relative
coordinates. */
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);
- rect.bottom = rect.top + row->height;
- /* Get the glyph the cursor is on. If we can't tell because
- the current matrix is invalid or such, give up. */
- cursor_glyph = get_phys_cursor_glyph (w);
- if (cursor_glyph == NULL)
- return;
+ /* 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.bottom = rect.top + h;
/* 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;
+ 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);
cursor remains invisible. */
if (w32_use_visible_system_caret)
{
+ /* Call to erase_phys_cursor here seems to use the
+ wrong values of w->phys_cursor, as they have been
+ overwritten before this function was called. */
if (w->phys_cursor_type != NO_CURSOR)
erase_phys_cursor (w);
PostMessage (hwnd, WM_EMACS_TRACK_CARET, 0, 0);
}
+ if (glyph_row->exact_window_width_line_p
+ && w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])
+ {
+ glyph_row->cursor_in_fringe_p = 1;
+ draw_fringe_bitmap (w, glyph_row, 0);
+ return;
+ }
+
switch (cursor_type)
{
case HOLLOW_BOX_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;
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
horizontally reflected compared to how they appear on X, so we
need to bitswap and convert to unsigned shorts before creating
the bitmaps. */
- {
- int i, j;
-
- for (i = NO_FRINGE_BITMAP + 1; i < MAX_FRINGE_BITMAPS; i++)
- {
- int h = fringe_bitmaps[i].height;
- int wd = fringe_bitmaps[i].width;
- unsigned short *w32bits
- = (unsigned short *)alloca (h * sizeof (unsigned short));
- unsigned short *wb = w32bits;
- unsigned char *bits = fringe_bitmaps[i].bits;
- for (j = 0; j < h; j++)
- {
- static unsigned char swap_nibble[16]
- = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
- 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
- 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
- 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
-
- unsigned char b = *bits++;
- *wb++ = (unsigned short)((swap_nibble[b & 0xf]<<4)
- | (swap_nibble[(b>>4) & 0xf]));
- }
- fringe_bmp[i] = CreateBitmap (wd, h, 1, 1, w32bits);
- }
- }
+ w32_init_fringe ();
#ifndef F_SETOWN_BUG
#ifdef F_SETOWN
xfree (dpyinfo->font_table);
xfree (dpyinfo->w32_id_name);
- /* Destroy row bitmaps. */
- {
- int i;
-
- for (i = NO_FRINGE_BITMAP + 1; i < MAX_FRINGE_BITMAPS; i++)
- DeleteObject (fringe_bmp[i]);
- }
+ w32_reset_fringes ();
}
\f
/* Set up use of W32. */
w32_get_glyph_overhangs,
x_fix_overlapping_area,
w32_draw_fringe_bitmap,
+ w32_define_fringe_bitmap,
+ w32_destroy_fringe_bitmap,
w32_per_char_metric,
w32_encode_char,
NULL, /* w32_compute_glyph_string_overhangs */
/* 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. */
Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
DEFVAR_INT ("w32-num-mouse-buttons",
- &Vw32_num_mouse_buttons,
+ &w32_num_mouse_buttons,
doc: /* Number of physical mouse buttons. */);
- Vw32_num_mouse_buttons = Qnil;
+ w32_num_mouse_buttons = 2;
DEFVAR_LISP ("w32-swap-mouse-buttons",
&Vw32_swap_mouse_buttons,