X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/0648dde0da60856aa02b78078ae7e380aba02e39..327719ee8a3fcdb36ed6acaf6d8cb5fbdf0bd801:/src/w32term.c diff --git a/src/w32term.c b/src/w32term.c index 4098ee5482..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)) @@ -73,6 +75,11 @@ Lisp_Object Vx_toolkit_scroll_bars; static int last_mousemove_x = 0; static int last_mousemove_y = 0; +/* Define GET_WHEEL_DELTA_WPARAM macro if system headers don't. */ +#ifndef GET_WHEEL_DELTA_WPARAM +#define GET_WHEEL_DELTA_WPARAM(wparam) ((short)HIWORD (wparam)) +#endif + /* Non-zero means that a HELP_EVENT has been generated since Emacs start. */ @@ -106,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. @@ -172,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; @@ -216,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 @@ -256,8 +286,7 @@ static void x_frame_rehighlight P_ ((struct w32_display_info *)); 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, int)); +static void w32_clip_to_row P_ ((struct window *, struct glyph_row *, HDC)); static Lisp_Object Qvendor_specific_keysyms; @@ -296,8 +325,9 @@ record_event (locus, type) #endif /* 0 */ -void XChangeGC (void * ignore, XGCValues* gc, unsigned long mask, - XGCValues *xgcv) +void +XChangeGC (void * ignore, XGCValues* gc, unsigned long mask, + XGCValues *xgcv) { if (mask & GCForeground) gc->foreground = xgcv->foreground; @@ -318,7 +348,8 @@ XGCValues *XCreateGC (void * ignore, Window window, unsigned long mask, return gc; } -void XGetGCValues (void* ignore, XGCValues *gc, +void +XGetGCValues (void* ignore, XGCValues *gc, unsigned long mask, XGCValues *xgcv) { XChangeGC (ignore, xgcv, mask, gc); @@ -494,7 +525,7 @@ w32_draw_vertical_window_border (w, x, y0, y1) struct frame *f = XFRAME (WINDOW_FRAME (w)); RECT r; HDC hdc; - + r.left = x; r.right = x + 1; r.top = y0; @@ -536,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; } @@ -620,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 @@ -651,7 +681,7 @@ x_after_update_window_line (desired_row) { HDC hdc = get_frame_dc (f); w32_clear_area (f, hdc, 0, y, width, height); - w32_clear_area (f, hdc, f->output_data.w32->pixel_width - width, + w32_clear_area (f, hdc, FRAME_PIXEL_WIDTH (f) - width, y, width, height); release_frame_dc (f, hdc); } @@ -674,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, 1); + 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); @@ -713,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 @@ -742,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. @@ -889,7 +984,17 @@ w32_per_char_metric (font, char2b, font_type) BOOL retval; xassert (font && char2b); - xassert (font_type != UNKNOWN_FONT); + + /* TODO: This function is currently called through the RIF, and in + some cases font_type is UNKNOWN_FONT. We currently allow the + cached metrics to be used, which seems to work, but in cases + where font_type is UNKNOWN_FONT, we probably haven't encoded + char2b appropriately. All callers need checking to see what they + are passing. This is most likely to affect variable width fonts + outside the Latin-1 range, particularly in languages like Thai + that rely on rbearing and lbearing to provide composition. I + don't think that is working currently anyway, but we don't seem + to have anyone testing such languages on Windows. */ /* Handle the common cases quickly. */ if (!font->bdf && font->per_char == NULL) @@ -898,6 +1003,8 @@ w32_per_char_metric (font, char2b, font_type) else if (!font->bdf && *char2b < 128) return &font->per_char[*char2b]; + xassert (font_type != UNKNOWN_FONT); + pcm = &font->scratch; if (font_type == BDF_1D_FONT) @@ -984,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; @@ -998,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. */ @@ -1029,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; @@ -1090,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 @@ -1105,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) @@ -1141,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 *)); @@ -1219,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); @@ -1722,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; @@ -1739,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) @@ -1757,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) @@ -1832,9 +2066,10 @@ x_draw_glyph_string_box (s) if (s->row->full_width_p && !s->w->pseudo_window_p) { - last_x += FRAME_X_RIGHT_FRINGE_WIDTH (s->f); - if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f)) - last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f); + 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); } /* The glyph that may have a right box line. */ @@ -1869,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); } } @@ -1880,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); @@ -1916,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); @@ -1931,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 @@ -1945,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); } } @@ -1956,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); } @@ -1972,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) @@ -2002,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); } @@ -2020,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) { @@ -2050,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); @@ -2065,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 @@ -2078,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); } } @@ -2089,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); @@ -2149,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) { @@ -2256,7 +2504,7 @@ x_draw_stretch_glyph_string (s) { /* If `x-stretch-block-cursor' is nil, don't draw a block cursor as wide as the stretch glyph. */ - int width = min (CANON_X_UNIT (s->f), s->background_width); + int width = min (FRAME_COLUMN_WIDTH (s->f), s->background_width); /* Draw cursor. */ x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height); @@ -2601,8 +2849,6 @@ x_scroll_run (w, run) without mode lines. Include in this box the left and right fringes of W. */ window_box (w, -1, &x, &y, &width, &height); - width += FRAME_X_FRINGE_WIDTH (f); - x -= FRAME_X_LEFT_FRINGE_WIDTH (f); from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y); to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y); @@ -2911,10 +3157,22 @@ construct_mouse_wheel (result, msg, f) struct frame *f; { POINT p; - result->kind = MOUSE_WHEEL_EVENT; - result->code = (short) HIWORD (msg->msg.wParam); + int delta; + + result->kind = WHEEL_EVENT; + result->code = 0; result->timestamp = msg->msg.time; - result->modifiers = msg->dwModifiers; + + /* A WHEEL_DELTA positive value indicates that the wheel was rotated + forward, away from the user (up); a negative value indicates that + the wheel was rotated backward, toward the user (down). */ + delta = GET_WHEEL_DELTA_WPARAM (msg->msg.wParam); + + /* The up and down modifiers indicate if the wheel was rotated up or + down based on WHEEL_DELTA value. */ + result->modifiers = (msg->dwModifiers + | ((delta < 0 ) ? down_modifier : up_modifier)); + p.x = LOWORD (msg->msg.lParam); p.y = HIWORD (msg->msg.lParam); ScreenToClient (msg->msg.hwnd, &p); @@ -3035,7 +3293,6 @@ note_mouse_movement (frame, msg) static struct scroll_bar *x_window_to_scroll_bar (); static void x_scroll_bar_report_motion (); static void x_check_fullscreen P_ ((struct frame *)); -static void x_check_fullscreen_move P_ ((struct frame *)); static int glyph_rect P_ ((struct frame *f, int, int, RECT *)); @@ -3070,15 +3327,14 @@ glyph_rect (f, x, y, rect) { Lisp_Object window; - window = window_from_coordinates (f, x, y, 0, 0); + window = window_from_coordinates (f, x, y, 0, &x, &y, 0); + if (!NILP (window)) { struct window *w = XWINDOW (window); struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix); struct glyph_row *end = r + w->current_matrix->nrows - 1; - frame_to_window_pixel_xy (w, &x, &y); - for (; r < end && r->enabled_p; ++r) if (r->y <= y && r->y + r->height > y) { @@ -3093,7 +3349,10 @@ glyph_rect (f, x, y, rect) if (x < r->x) { /* x is to the left of the first glyph in the row. */ - rect->left = XINT (w->left); + /* Shouldn't this be a pixel value? + WINDOW_LEFT_EDGE_X (w) seems to be the right value. + ++KFS */ + rect->left = WINDOW_LEFT_EDGE_COL (w); rect->right = WINDOW_TO_FRAME_PIXEL_X (w, r->x); return 1; } @@ -3109,7 +3368,10 @@ glyph_rect (f, x, y, rect) /* x is to the right of the last glyph in the row. */ rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx); - rect->right = XINT (w->left) + XINT (w->width); + /* Shouldn't this be a pixel value? + WINDOW_RIGHT_EDGE_X (w) seems to be the right value. + ++KFS */ + rect->right = WINDOW_RIGHT_EDGE_COL (w); return 1; } } @@ -3129,7 +3391,7 @@ remember_mouse_glyph (f1, gx, gy) int width = FRAME_SMALLEST_CHAR_WIDTH (f1); int height = FRAME_SMALLEST_FONT_HEIGHT (f1); - /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to + /* Arrange for the division in FRAME_PIXEL_X_TO_COL etc. to round down even for negative values. */ if (gx < 0) gx -= width - 1; @@ -3570,31 +3832,26 @@ w32_set_vertical_scroll_bar (w, portion, whole, position) struct frame *f = XFRAME (w->frame); struct scroll_bar *bar; int top, height, left, sb_left, width, sb_width; - int window_x, window_y, window_width, window_height; + int window_y, window_height; /* Get window dimensions. */ - window_box (w, -1, &window_x, &window_y, &window_width, &window_height); + window_box (w, -1, 0, &window_y, 0, &window_height); top = window_y; - width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f); + width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f); height = window_height; /* Compute the left edge of the scroll bar area. */ - if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f)) - left = XINT (w->left) + XINT (w->width) - FRAME_SCROLL_BAR_COLS (f); - else - left = XFASTINT (w->left); - left *= CANON_X_UNIT (f); - left += FRAME_INTERNAL_BORDER_WIDTH (f); + left = WINDOW_SCROLL_BAR_AREA_X (w); /* Compute the width of the scroll bar which might be less than the width of the area reserved for the scroll bar. */ - if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0) - sb_width = FRAME_SCROLL_BAR_PIXEL_WIDTH (f); + if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w) > 0) + sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w); else sb_width = width; /* Compute the left edge of the scroll bar. */ - if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f)) + if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w)) sb_left = left + width - sb_width - (width - sb_width) / 2; else sb_left = left + (width - sb_width) / 2; @@ -4033,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'. @@ -4050,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; @@ -4074,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: @@ -4109,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))) @@ -4144,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; @@ -4166,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; @@ -4193,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; @@ -4246,7 +4484,7 @@ w32_read_socket (sd, bufp, numchars, expected) int x = LOWORD (msg.msg.lParam); int y = HIWORD (msg.msg.lParam); - window = window_from_coordinates (f, x, y, 0, 0); + window = window_from_coordinates (f, x, y, 0, 0, 0, 0); /* Window will be selected only when it is not selected now and last mouse movement event was @@ -4254,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; @@ -4276,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: @@ -4312,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; @@ -4327,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) - && XFASTINT (XWINDOW (f->tool_bar_window)->height)) + && 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, 1); + 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), @@ -4382,37 +4595,39 @@ w32_read_socket (sd, bufp, numchars, expected) break; } - case WM_MOUSEWHEEL: - if (dpyinfo->grabbed && last_mouse_frame - && FRAME_LIVE_P (last_mouse_frame)) - f = last_mouse_frame; - else - f = x_window_to_frame (dpyinfo, msg.msg.hwnd); + case WM_MOUSEWHEEL: + { + if (dpyinfo->grabbed && last_mouse_frame + && FRAME_LIVE_P (last_mouse_frame)) + f = last_mouse_frame; + else + f = x_window_to_frame (dpyinfo, msg.msg.hwnd); - if (f) - { - if ((!dpyinfo->w32_focus_frame - || f == dpyinfo->w32_focus_frame) - && (numchars >= 1)) - { - construct_mouse_wheel (bufp, &msg, f); - bufp++; - count++; - numchars--; - } - } + if (f) + { + + if (!dpyinfo->w32_focus_frame + || f == dpyinfo->w32_focus_frame) + { + /* Emit an Emacs wheel-up/down event. */ + construct_mouse_wheel (&inev, &msg, f); + } + /* Ignore any mouse motion that happened before this + event; any subsequent mouse-movement Emacs events + should reflect only motion after the + ButtonPress. */ + f->mouse_moved = 0; + } + last_mouse_frame = f; + last_tool_bar_item = -1; + } break; case WM_DROPFILES: 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: @@ -4420,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; } @@ -4436,10 +4644,8 @@ w32_read_socket (sd, bufp, numchars, expected) f = x_window_to_frame (dpyinfo, msg.msg.hwnd); if (f) { - x_check_fullscreen_move(f); - if (f->output_data.w32->want_fullscreen & FULLSCREEN_WAIT) - f->output_data.w32->want_fullscreen &= - ~(FULLSCREEN_WAIT|FULLSCREEN_BOTH); + if (f->want_fullscreen & FULLSCREEN_WAIT) + f->want_fullscreen &= ~(FULLSCREEN_WAIT|FULLSCREEN_BOTH); } check_visibility = 1; break; @@ -4460,8 +4666,8 @@ w32_read_socket (sd, bufp, numchars, expected) int x, y; x_real_positions (f, &x, &y); - f->output_data.w32->left_pos = x; - f->output_data.w32->top_pos = y; + f->left_pos = x; + f->top_pos = y; } check_visibility = 1; @@ -4506,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: @@ -4533,15 +4735,11 @@ w32_read_socket (sd, bufp, numchars, expected) when the Window is iconified, with 3000,3000 as the co-ords. */ x_real_positions (f, &x, &y); - f->output_data.w32->left_pos = x; - f->output_data.w32->top_pos = y; - - bufp->kind = DEICONIFY_EVENT; - XSETFRAME (bufp->frame_or_window, f); - bufp->arg = Qnil; - bufp++; - count++; - numchars--; + f->left_pos = x; + f->top_pos = y; + + inev.kind = DEICONIFY_EVENT; + XSETFRAME (inev.frame_or_window, f); } else if (! NILP (Vframe_list) && ! NILP (XCDR (Vframe_list))) @@ -4566,8 +4764,8 @@ w32_read_socket (sd, bufp, numchars, expected) height = rect.bottom - rect.top; width = rect.right - rect.left; - rows = PIXEL_TO_CHAR_HEIGHT (f, height); - columns = PIXEL_TO_CHAR_WIDTH (f, width); + rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height); + columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width); /* TODO: Clip size to the screen dimensions. */ @@ -4575,17 +4773,17 @@ w32_read_socket (sd, bufp, numchars, expected) not changed, the font size may have changed, so we need to check the pixel dimensions as well. */ - if (columns != f->width - || rows != f->height - || width != f->output_data.w32->pixel_width - || height != f->output_data.w32->pixel_height) + if (columns != FRAME_COLS (f) + || rows != FRAME_LINES (f) + || width != FRAME_PIXEL_WIDTH (f) + || height != FRAME_PIXEL_HEIGHT (f)) { change_frame_size (f, rows, columns, 0, 1, 0); SET_FRAME_GARBAGED (f); cancel_mouse_face (f); - f->output_data.w32->pixel_width = width; - f->output_data.w32->pixel_height = height; - f->output_data.w32->win_gravity = NorthWestGravity; + FRAME_PIXEL_WIDTH (f) = width; + FRAME_PIXEL_HEIGHT (f) = height; + f->win_gravity = NorthWestGravity; } } @@ -4609,28 +4807,19 @@ 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; case WM_SETFOCUS: /* TODO: Port this change: 2002-06-28 Jan D. - * xterm.h (struct x_output): Add focus_state. - * xterm.c (x_focus_changed): New function. + * xterm.h (struct x_output): Add focus_state. + * xterm.c (x_focus_changed): New function. (x_detect_focus_change): New function. (XTread_socket): Call x_detect_focus_change for FocusIn/FocusOut EnterNotify and LeaveNotify to track X focus changes. - */ + */ f = x_any_window_to_frame (dpyinfo, msg.msg.hwnd); dpyinfo->w32_focus_event_frame = f; @@ -4668,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; @@ -4689,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; @@ -4706,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; @@ -4747,29 +4913,50 @@ w32_read_socket (sd, bufp, numchars, expected) break; default: - /* Check for messages registered at runtime. */ + /* Check for messages registered at runtime. */ if (msg.msg.message == msh_mousewheel) { - if (dpyinfo->grabbed && last_mouse_frame - && FRAME_LIVE_P (last_mouse_frame)) - f = last_mouse_frame; - else - f = x_window_to_frame (dpyinfo, msg.msg.hwnd); + /* Forward MSH_MOUSEWHEEL as WM_MOUSEWHEEL. */ + msg.msg.message = WM_MOUSEWHEEL; + prepend_msg (&msg); + } + break; + } - if (f) + 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)) { - if ((!dpyinfo->w32_focus_frame - || f == dpyinfo->w32_focus_frame) - && (numchars >= 1)) - { - construct_mouse_wheel (bufp, &msg, f); - bufp++; - count++; - numchars--; - } + 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); } - break; + else + { + help_echo_string = Qnil; + gen_help_event (Qnil, frame, Qnil, Qnil, 0); + } + count++; } } @@ -4792,65 +4979,65 @@ w32_read_socket (sd, bufp, numchars, expected) Lisp_Object tail, frame; FOR_EACH_FRAME (tail, frame) - { - FRAME_PTR f = XFRAME (frame); - /* The tooltip has been drawn already. Avoid the - SET_FRAME_GARBAGED below. */ - if (EQ (frame, tip_frame)) - continue; - - /* Check "visible" frames and mark each as obscured or not. - Note that async_visible is nonzero for unobscured and - obscured frames, but zero for hidden and iconified frames. */ - if (FRAME_W32_P (f) && f->async_visible) - { - RECT clipbox; - HDC hdc; - - enter_crit (); - /* Query clipping rectangle for the entire window area - (GetWindowDC), not just the client portion (GetDC). - Otherwise, the scrollbars and menubar aren't counted as - part of the visible area of the frame, and we may think - the frame is obscured when really a scrollbar is still - visible and gets WM_PAINT messages above. */ - hdc = GetWindowDC (FRAME_W32_WINDOW (f)); - GetClipBox (hdc, &clipbox); - ReleaseDC (FRAME_W32_WINDOW (f), hdc); - leave_crit (); - - if (clipbox.right == clipbox.left - || clipbox.bottom == clipbox.top) - { - /* Frame has become completely obscured so mark as - such (we do this by setting async_visible to 2 so - that FRAME_VISIBLE_P is still true, but redisplay - will skip it). */ - f->async_visible = 2; + { + FRAME_PTR f = XFRAME (frame); + /* The tooltip has been drawn already. Avoid the + SET_FRAME_GARBAGED below. */ + if (EQ (frame, tip_frame)) + continue; + + /* Check "visible" frames and mark each as obscured or not. + Note that async_visible is nonzero for unobscured and + obscured frames, but zero for hidden and iconified frames. */ + if (FRAME_W32_P (f) && f->async_visible) + { + RECT clipbox; + HDC hdc; + + enter_crit (); + /* Query clipping rectangle for the entire window area + (GetWindowDC), not just the client portion (GetDC). + Otherwise, the scrollbars and menubar aren't counted as + part of the visible area of the frame, and we may think + the frame is obscured when really a scrollbar is still + visible and gets WM_PAINT messages above. */ + hdc = GetWindowDC (FRAME_W32_WINDOW (f)); + GetClipBox (hdc, &clipbox); + ReleaseDC (FRAME_W32_WINDOW (f), hdc); + leave_crit (); + + if (clipbox.right == clipbox.left + || clipbox.bottom == clipbox.top) + { + /* Frame has become completely obscured so mark as + such (we do this by setting async_visible to 2 so + that FRAME_VISIBLE_P is still true, but redisplay + will skip it). */ + f->async_visible = 2; - if (!FRAME_OBSCURED_P (f)) - { - DebPrint (("frame %p (%s) obscured\n", f, - SDATA (f->name))); - } - } - else - { - /* Frame is not obscured, so mark it as such. */ - f->async_visible = 1; + if (!FRAME_OBSCURED_P (f)) + { + DebPrint (("frame %p (%s) obscured\n", f, + SDATA (f->name))); + } + } + else + { + /* Frame is not obscured, so mark it as such. */ + f->async_visible = 1; - if (FRAME_OBSCURED_P (f)) - { - SET_FRAME_GARBAGED (f); - DebPrint (("obscured frame %p (%s) found to be visible\n", f, - SDATA (f->name))); + if (FRAME_OBSCURED_P (f)) + { + SET_FRAME_GARBAGED (f); + DebPrint (("obscured frame %p (%s) found to be visible\n", f, + SDATA (f->name))); - /* Force a redisplay sooner or later. */ - record_asynch_buffer_change (); - } - } - } - } + /* Force a redisplay sooner or later. */ + record_asynch_buffer_change (); + } + } + } + } } UNBLOCK_INPUT; @@ -4866,25 +5053,22 @@ w32_read_socket (sd, bufp, numchars, expected) /* Set clipping for output in glyph row ROW. W is the window in which we operate. GC is the graphics context to set clipping in. - WHOLE_LINE_P non-zero means include the areas used for truncation - mark display and alike in the clipping rectangle. ROW may be a text row or, e.g., a mode line. Text rows must be clipped to the interior of the window dedicated to text display, mode lines must be clipped to the whole window. */ static void -w32_clip_to_row (w, row, hdc, whole_line_p) +w32_clip_to_row (w, row, hdc) struct window *w; struct glyph_row *row; HDC hdc; - int whole_line_p; { struct frame *f = XFRAME (WINDOW_FRAME (w)); RECT clip_rect; - int window_x, window_y, window_width, window_height; + int window_y, window_width; - window_box (w, -1, &window_x, &window_y, &window_width, &window_height); + window_box (w, -1, 0, &window_y, &window_width, 0); clip_rect.left = WINDOW_TO_FRAME_PIXEL_X (w, 0); clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y); @@ -4892,14 +5076,6 @@ w32_clip_to_row (w, row, hdc, whole_line_p) clip_rect.right = clip_rect.left + window_width; clip_rect.bottom = clip_rect.top + row->visible_height; - /* If clipping to the whole line, including trunc marks, extend - the rectangle to the left and increase its width. */ - if (whole_line_p) - { - clip_rect.left -= FRAME_X_LEFT_FRINGE_WIDTH (f); - clip_rect.right += FRAME_X_FRINGE_WIDTH (f); - } - w32_set_clip_rectangle (hdc, &clip_rect); } @@ -4914,37 +5090,47 @@ 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 (CANON_X_UNIT (f), wd); + 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, 0); + w32_clip_to_row (w, row, hdc); FrameRect (hdc, &rect, hb); DeleteObject (hb); w32_set_clip_rectangle (hdc, NULL); @@ -5010,7 +5196,7 @@ x_draw_bar_cursor (w, row, width, kind) hdc = get_frame_dc (f); - w32_clip_to_row (w, row, hdc, 0); + w32_clip_to_row (w, row, hdc); if (kind == BAR_CURSOR) { @@ -5073,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); @@ -5112,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: @@ -5230,73 +5427,91 @@ 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; + FRAME_COLUMN_WIDTH (f) = FONT_WIDTH (FRAME_FONT (f)); + FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (FRAME_FONT (f)); + + compute_fringe_widths (f, 1); + /* Compute the scroll bar width in character columns. */ - if (f->scroll_bar_pixel_width > 0) + if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0) { - int wid = FONT_WIDTH (FRAME_FONT (f)); - f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid; + int wid = FRAME_COLUMN_WIDTH (f); + FRAME_CONFIG_SCROLL_BAR_COLS (f) + = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid-1) / wid; } else { - int wid = FONT_WIDTH (FRAME_FONT (f)); - f->scroll_bar_cols = (14 + wid - 1) / wid; + int wid = FRAME_COLUMN_WIDTH (f); + FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid; } /* Now make the frame display the given font. */ if (FRAME_W32_WINDOW (f) != 0) { - frame_update_line_height (f); if (NILP (tip_frame) || XFRAME (tip_frame) != f) - x_set_window_size (f, 0, f->width, f->height); + x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f)); } - else - /* If we are setting a new frame's font for the first time, - there are no faces yet, so this font's height is the line height. */ - f->output_data.w32->line_height = FONT_HEIGHT (FRAME_FONT (f)); 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); } @@ -5323,7 +5538,7 @@ x_calc_absolute_position (f) struct frame *f; { POINT pt; - int flags = f->output_data.w32->size_hint_flags; + int flags = f->size_hint_flags; pt.x = pt.y = 0; @@ -5355,20 +5570,20 @@ x_calc_absolute_position (f) /* Treat negative positions as relative to the leftmost bottommost position that fits on the screen. */ if (flags & XNegative) - f->output_data.w32->left_pos = (FRAME_W32_DISPLAY_INFO (f)->width - - 2 * f->output_data.w32->border_width - pt.x - - PIXEL_WIDTH (f) - + f->output_data.w32->left_pos); + 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->output_data.w32->top_pos = (FRAME_W32_DISPLAY_INFO (f)->height - - 2 * f->output_data.w32->border_width - pt.y - - PIXEL_HEIGHT (f) - + f->output_data.w32->top_pos); + 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 are now relative to the top and left screen edges, so the flags should correspond. */ - f->output_data.w32->size_hint_flags &= ~ (XNegative | YNegative); + f->size_hint_flags &= ~ (XNegative | YNegative); } /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position, @@ -5387,22 +5602,22 @@ x_set_offset (f, xoff, yoff, change_gravity) if (change_gravity > 0) { - f->output_data.w32->top_pos = yoff; - f->output_data.w32->left_pos = xoff; - f->output_data.w32->size_hint_flags &= ~ (XNegative | YNegative); + f->top_pos = yoff; + f->left_pos = xoff; + f->size_hint_flags &= ~ (XNegative | YNegative); if (xoff < 0) - f->output_data.w32->size_hint_flags |= XNegative; + f->size_hint_flags |= XNegative; if (yoff < 0) - f->output_data.w32->size_hint_flags |= YNegative; - f->output_data.w32->win_gravity = NorthWestGravity; + f->size_hint_flags |= YNegative; + f->win_gravity = NorthWestGravity; } x_calc_absolute_position (f); BLOCK_INPUT; x_wm_set_size_hint (f, (long) 0, 0); - modified_left = f->output_data.w32->left_pos; - modified_top = f->output_data.w32->top_pos; + modified_left = f->left_pos; + modified_top = f->top_pos; my_set_window_pos (FRAME_W32_WINDOW (f), NULL, @@ -5419,108 +5634,28 @@ static void x_check_fullscreen (f) struct frame *f; { - if (f->output_data.w32->want_fullscreen & FULLSCREEN_BOTH) + if (f->want_fullscreen & FULLSCREEN_BOTH) { int width, height, ign; - x_real_positions (f, &f->output_data.w32->left_pos, - &f->output_data.w32->top_pos); + x_real_positions (f, &f->left_pos, &f->top_pos); x_fullscreen_adjust (f, &width, &height, &ign, &ign); /* We do not need to move the window, it shall be taken care of - when setting WM manager hints. - If the frame is visible already, the position is checked by - x_check_fullscreen_move. */ - if (f->width != width || f->height != height) + when setting WM manager hints. */ + if (FRAME_COLS (f) != width || FRAME_LINES (f) != height) { change_frame_size (f, height, width, 0, 1, 0); SET_FRAME_GARBAGED (f); cancel_mouse_face (f); /* Wait for the change of frame size to occur */ - f->output_data.w32->want_fullscreen |= FULLSCREEN_WAIT; + f->want_fullscreen |= FULLSCREEN_WAIT; } } } -/* If frame parameters are set after the frame is mapped, we need to move - the window. This is done in xfns.c. - Some window managers moves the window to the right position, some - moves the outer window manager window to the specified position. - Here we check that we are in the right spot. If not, make a second - move, assuming we are dealing with the second kind of window manager. */ -static void -x_check_fullscreen_move (f) - struct frame *f; -{ - if (f->output_data.w32->want_fullscreen & FULLSCREEN_MOVE_WAIT) - { - int expect_top = f->output_data.w32->top_pos; - int expect_left = f->output_data.w32->left_pos; - - if (f->output_data.w32->want_fullscreen & FULLSCREEN_HEIGHT) - expect_top = 0; - if (f->output_data.w32->want_fullscreen & FULLSCREEN_WIDTH) - expect_left = 0; - - if (expect_top != f->output_data.w32->top_pos - || expect_left != f->output_data.w32->left_pos) - x_set_offset (f, expect_left, expect_top, 1); - - /* Just do this once */ - f->output_data.w32->want_fullscreen &= ~FULLSCREEN_MOVE_WAIT; - } -} - - -/* Calculate fullscreen size. Return in *TOP_POS and *LEFT_POS the - wanted positions of the WM window (not emacs window). - Return in *WIDTH and *HEIGHT the wanted width and height of Emacs - window (FRAME_X_WINDOW). - */ -void -x_fullscreen_adjust (f, width, height, top_pos, left_pos) - struct frame *f; - int *width; - int *height; - int *top_pos; - int *left_pos; -{ - int newwidth = f->width, newheight = f->height; - - *top_pos = f->output_data.w32->top_pos; - *left_pos = f->output_data.w32->left_pos; - - if (f->output_data.w32->want_fullscreen & FULLSCREEN_HEIGHT) - { - int ph; - - ph = FRAME_X_DISPLAY_INFO (f)->height; - newheight = PIXEL_TO_CHAR_HEIGHT (f, ph); - ph = CHAR_TO_PIXEL_HEIGHT (f, newheight) - - f->output_data.w32->y_pixels_diff; - newheight = PIXEL_TO_CHAR_HEIGHT (f, ph); - *top_pos = 0; - } - - if (f->output_data.w32->want_fullscreen & FULLSCREEN_WIDTH) - { - int pw; - - pw = FRAME_X_DISPLAY_INFO (f)->width; - newwidth = PIXEL_TO_CHAR_WIDTH (f, pw); - pw = CHAR_TO_PIXEL_WIDTH (f, newwidth) - - f->output_data.w32->x_pixels_diff; - newwidth = PIXEL_TO_CHAR_WIDTH (f, pw); - *left_pos = 0; - } - - *width = newwidth; - *height = newheight; -} - - /* Call this to change the size of frame F's x-window. If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity for this size change and subsequent size changes. @@ -5537,17 +5672,15 @@ x_set_window_size (f, change_gravity, cols, rows) BLOCK_INPUT; check_frame_size (f, &rows, &cols); - f->output_data.w32->vertical_scroll_bar_extra - = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f) - ? 0 - : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.w32->font))); + f->scroll_bar_actual_width + = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f); compute_fringe_widths (f, 0); - pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols); - pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows); + pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols); + pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows); - f->output_data.w32->win_gravity = NorthWestGravity; + f->win_gravity = NorthWestGravity; x_wm_set_size_hint (f, (long) 0, 0); { @@ -5582,8 +5715,8 @@ x_set_window_size (f, change_gravity, cols, rows) We pass 1 for DELAY since we can't run Lisp code inside of a BLOCK_INPUT. */ change_frame_size (f, rows, cols, 0, 1, 0); - PIXEL_WIDTH (f) = pixelwidth; - PIXEL_HEIGHT (f) = pixelheight; + FRAME_PIXEL_WIDTH (f) = pixelwidth; + FRAME_PIXEL_HEIGHT (f) = pixelheight; /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to receive in the ConfigureNotify event; if we get what we asked @@ -5614,14 +5747,14 @@ x_set_mouse_position (f, x, y) { int pix_x, pix_y; - pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.w32->font) / 2; - pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.w32->line_height / 2; + pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2; + pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2; if (pix_x < 0) pix_x = 0; - if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f); + if (pix_x > FRAME_PIXEL_WIDTH (f)) pix_x = FRAME_PIXEL_WIDTH (f); if (pix_y < 0) pix_y = 0; - if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f); + if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f); x_set_mouse_pixel_position (f, pix_x, pix_y); } @@ -5789,7 +5922,7 @@ x_make_frame_visible (f) before the window gets really visible. */ if (! FRAME_ICONIFIED_P (f) && ! f->output_data.w32->asked_for_visible) - x_set_offset (f, f->output_data.w32->left_pos, f->output_data.w32->top_pos, 0); + x_set_offset (f, f->left_pos, f->top_pos, 0); f->output_data.w32->asked_for_visible = 1; @@ -5977,15 +6110,16 @@ x_wm_set_size_hint (f, flags, user_position) enter_crit (); - SetWindowLong (window, WND_FONTWIDTH_INDEX, FONT_WIDTH (f->output_data.w32->font)); - SetWindowLong (window, WND_LINEHEIGHT_INDEX, f->output_data.w32->line_height); - SetWindowLong (window, WND_BORDER_INDEX, f->output_data.w32->internal_border_width); - SetWindowLong (window, WND_SCROLLBAR_INDEX, f->output_data.w32->vertical_scroll_bar_extra); + SetWindowLong (window, WND_FONTWIDTH_INDEX, FRAME_COLUMN_WIDTH (f)); + SetWindowLong (window, WND_LINEHEIGHT_INDEX, FRAME_LINE_HEIGHT (f)); + SetWindowLong (window, WND_BORDER_INDEX, FRAME_INTERNAL_BORDER_WIDTH (f)); + SetWindowLong (window, WND_SCROLLBAR_INDEX, f->scroll_bar_actual_width); leave_crit (); } /* Window manager things */ +void x_wm_set_icon_position (f, icon_x, icon_y) struct frame *f; int icon_x, icon_y; @@ -6270,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 @@ -6363,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. */ @@ -6380,8 +6483,11 @@ void x_flush (struct frame * f) { /* Nothing to do */ } +extern frame_parm_handler w32_frame_parm_handlers[]; + static struct redisplay_interface w32_redisplay_interface = { + w32_frame_parm_handlers, x_produce_glyphs, x_write_glyphs, x_insert_glyphs, @@ -6397,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 */ @@ -6489,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. */ @@ -6525,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, @@ -6591,3 +6702,6 @@ the cursor have no effect. */); staticpro (&last_mouse_motion_frame); last_mouse_motion_frame = Qnil; } + +/* arch-tag: 5fa70624-ab86-499c-8a85-473958ee4646 + (do not change this comment) */