X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/068ae0fd96c6bbd9aaa3b3d96232cf548749a36d..327719ee8a3fcdb36ed6acaf6d8cb5fbdf0bd801:/src/w32term.c diff --git a/src/w32term.c b/src/w32term.c index 3e4543471c..95ccafe415 100644 --- a/src/w32term.c +++ b/src/w32term.c @@ -24,25 +24,21 @@ Boston, MA 02111-1307, USA. */ #include #include #include "lisp.h" -#include "charset.h" #include "blockinput.h" - -#include "w32heap.h" #include "w32term.h" -#include "w32bdf.h" -#include #include "systty.h" #include "systime.h" -#include "atimer.h" -#include "keymap.h" #include #include #include #include -#include "keyboard.h" +#include "charset.h" +#include "character.h" +#include "coding.h" +#include "ccl.h" #include "frame.h" #include "dispextern.h" #include "fontset.h" @@ -53,9 +49,15 @@ Boston, MA 02111-1307, 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 #define abs(x) ((x) < 0 ? -(x) : (x)) @@ -111,6 +113,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. @@ -177,7 +204,7 @@ int last_scroll_bar_drag_pos; 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; @@ -221,8 +248,6 @@ static int input_signal_count; extern Lisp_Object Vcommand_line_args, Vsystem_name; -extern Lisp_Object Qface, Qmouse_face; - #ifndef USE_CRT_DLL extern int errno; #endif @@ -542,6 +567,9 @@ x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p) output_cursor.x, output_cursor.y); x_draw_vertical_border (w); + + draw_window_fringes (w); + UNBLOCK_INPUT; } @@ -626,11 +654,7 @@ x_after_update_window_line (desired_row) 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 @@ -680,34 +704,79 @@ w32_draw_fringe_bitmap (w, row, p) 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); @@ -719,6 +788,25 @@ w32_draw_fringe_bitmap (w, row, p) 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; +} + + /* This is called when starting Emacs and when restarting after suspend. When starting Emacs, no window is mapped. And nothing @@ -748,7 +836,8 @@ w32_reset_terminal_modes (void) 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. @@ -1002,13 +1091,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; @@ -1016,29 +1105,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. */ @@ -1047,50 +1146,26 @@ 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; + 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; @@ -1108,6 +1183,143 @@ 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; + + 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; +} + /*********************************************************************** Glyph display @@ -1123,9 +1335,9 @@ w32_text_out (s, x, y,chars,nchars) 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) @@ -1159,7 +1371,8 @@ static void w32_draw_image_foreground_1 P_ ((struct glyph_string *, HBITMAP)); 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 *)); @@ -1237,9 +1450,9 @@ 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); @@ -1740,9 +1953,10 @@ x_setup_relief_colors (s) 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; @@ -1757,10 +1971,11 @@ w32_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width, 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) @@ -1775,10 +1990,11 @@ w32_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width, 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) @@ -1888,7 +2104,7 @@ x_draw_glyph_string_box (s) { 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); } } @@ -1899,21 +2115,22 @@ static void 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); @@ -1935,12 +2152,12 @@ x_draw_image_foreground (s) 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); @@ -1950,8 +2167,8 @@ x_draw_image_foreground (s) 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 @@ -1964,7 +2181,8 @@ x_draw_image_foreground (s) 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); } } @@ -1975,8 +2193,8 @@ x_draw_image_foreground (s) 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); } @@ -1991,21 +2209,22 @@ x_draw_image_relief (s) { 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) @@ -2021,12 +2240,17 @@ x_draw_image_relief (s) 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); } @@ -2039,21 +2263,22 @@ w32_draw_image_foreground_1 (s, pixmap) { 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) { @@ -2069,12 +2294,12 @@ w32_draw_image_foreground_1 (s, 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); @@ -2084,8 +2309,8 @@ w32_draw_image_foreground_1 (s, pixmap) 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 @@ -2097,8 +2322,9 @@ w32_draw_image_foreground_1 (s, pixmap) { 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); } } @@ -2108,8 +2334,8 @@ w32_draw_image_foreground_1 (s, pixmap) 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); @@ -2168,19 +2394,22 @@ x_draw_image_glyph_string (s) 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) { @@ -4061,8 +4290,6 @@ static short temp_buffer[100]; 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'. @@ -4078,11 +4305,10 @@ static short temp_buffer[100]; */ 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; @@ -4102,13 +4328,16 @@ w32_read_socket (sd, bufp, numchars, expected) /* 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: @@ -4137,12 +4366,8 @@ w32_read_socket (sd, bufp, numchars, expected) 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))) @@ -4172,17 +4397,10 @@ w32_read_socket (sd, bufp, numchars, expected) 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; @@ -4194,22 +4412,18 @@ w32_read_socket (sd, bufp, numchars, expected) { 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; @@ -4221,22 +4435,18 @@ w32_read_socket (sd, bufp, numchars, expected) { 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; @@ -4282,13 +4492,10 @@ w32_read_socket (sd, bufp, numchars, expected) 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; @@ -4304,29 +4511,16 @@ w32_read_socket (sd, bufp, numchars, expected) /* 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: @@ -4340,13 +4534,10 @@ w32_read_socket (sd, bufp, numchars, expected) { /* 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; @@ -4355,35 +4546,29 @@ w32_read_socket (sd, bufp, numchars, expected) 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), @@ -4421,15 +4606,11 @@ w32_read_socket (sd, bufp, numchars, expected) 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 @@ -4446,12 +4627,7 @@ w32_read_socket (sd, bufp, numchars, expected) 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: @@ -4459,15 +4635,8 @@ w32_read_socket (sd, bufp, numchars, expected) 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; } @@ -4543,12 +4712,8 @@ w32_read_socket (sd, bufp, numchars, expected) 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: @@ -4573,12 +4738,8 @@ w32_read_socket (sd, bufp, numchars, expected) 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))) @@ -4646,16 +4807,7 @@ w32_read_socket (sd, bufp, numchars, expected) 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; @@ -4705,16 +4857,7 @@ w32_read_socket (sd, bufp, numchars, expected) 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; @@ -4726,15 +4869,8 @@ w32_read_socket (sd, bufp, numchars, expected) 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; @@ -4743,15 +4879,8 @@ w32_read_socket (sd, bufp, numchars, expected) 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; @@ -4793,6 +4922,42 @@ w32_read_socket (sd, bufp, numchars, expected) } 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, @@ -4925,28 +5090,38 @@ x_draw_hollow_cursor (w, row) 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); @@ -5084,6 +5259,9 @@ w32_draw_window_cursor (w, glyph_row, x, y, cursor_type, cursor_width, on_p, act 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); @@ -5123,6 +5301,14 @@ w32_draw_window_cursor (w, glyph_row, x, y, cursor_type, cursor_width, on_p, act 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: @@ -5241,11 +5427,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; @@ -5278,37 +5469,49 @@ 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); } @@ -6201,32 +6404,7 @@ w32_term_init (display_name, xrm_option, resource_name) 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 @@ -6294,13 +6472,7 @@ x_delete_display (dpyinfo) 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 (); } /* Set up use of W32. */ @@ -6331,6 +6503,8 @@ static struct redisplay_interface w32_redisplay_interface = 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 */ @@ -6423,16 +6597,19 @@ w32_initialize () /* 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. */ @@ -6459,9 +6636,9 @@ syms_of_w32term () 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,