X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/f65f7603312547e51230192daf34349b8ac569a0..1ffb5a86a9f27bf8cfb459b09e7d7ca3e8696da5:/src/w32term.c diff --git a/src/w32term.c b/src/w32term.c index e7118caa0d..100af4ebc2 100644 --- a/src/w32term.c +++ b/src/w32term.c @@ -7,7 +7,7 @@ This file is part of GNU Emacs. GNU Emacs is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) +the Free Software Foundation; either version 3, or (at your option) any later version. GNU Emacs is distributed in the hope that it will be useful, @@ -218,10 +218,9 @@ extern int errno; extern EMACS_INT extra_keyboard_modifiers; static void x_update_window_end P_ ((struct window *, int, int)); -void w32_delete_display P_ ((struct w32_display_info *)); static void w32_handle_tool_bar_click P_ ((struct frame *, struct input_event *)); -void w32_define_cursor P_ ((Window, Cursor)); +static void w32_define_cursor P_ ((Window, Cursor)); void x_lower_frame P_ ((struct frame *)); void x_scroll_bar_clear P_ ((struct frame *)); @@ -230,14 +229,14 @@ void x_raise_frame P_ ((struct frame *)); void x_set_window_size P_ ((struct frame *, int, int, int)); void x_wm_set_window_state P_ ((struct frame *, int)); void x_wm_set_icon_pixmap P_ ((struct frame *, int)); -void w32_initialize P_ ((void)); +static void w32_initialize P_ ((void)); static void x_font_min_bounds P_ ((XFontStruct *, int *, int *)); int x_compute_min_glyph_bounds P_ ((struct frame *)); static void x_update_end P_ ((struct frame *)); static void w32_frame_up_to_date P_ ((struct frame *)); -static void w32_set_terminal_modes P_ ((void)); -static void w32_reset_terminal_modes P_ ((void)); -static void x_clear_frame P_ ((void)); +static void w32_set_terminal_modes P_ ((struct terminal *)); +static void w32_reset_terminal_modes P_ ((struct terminal *)); +static void x_clear_frame P_ ((struct frame *)); static void frame_highlight P_ ((struct frame *)); static void frame_unhighlight P_ ((struct frame *)); static void x_new_focus_frame P_ ((struct w32_display_info *, @@ -683,6 +682,60 @@ w32_draw_fringe_bitmap (w, row, p) hdc = get_frame_dc (f); + if (!p->overlay_p) + { + int bx = p->bx, by = p->by, nx = p->nx, ny = p->ny; + + /* If the fringe is adjacent to the left (right) scroll bar of a + leftmost (rightmost, respectively) window, then extend its + background to the gap between the fringe and the bar. */ + if ((WINDOW_LEFTMOST_P (w) + && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)) + || (WINDOW_RIGHTMOST_P (w) + && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))) + { + int sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w); + + if (sb_width > 0) + { + int left = WINDOW_SCROLL_BAR_AREA_X (w); + int width = (WINDOW_CONFIG_SCROLL_BAR_COLS (w) + * FRAME_COLUMN_WIDTH (f)); + + if (bx < 0) + { + /* Bitmap fills the fringe. */ + if (left + width == p->x) + bx = left + sb_width; + else if (p->x + p->wd == left) + bx = left; + if (bx >= 0) + { + int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w); + + nx = width - sb_width; + by = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height, + row->y)); + ny = row->visible_height; + } + } + else + { + if (left + width == bx) + { + bx = left + sb_width; + nx += width - sb_width; + } + else if (bx + nx == left) + nx += width - sb_width; + } + } + } + + if (bx >= 0 && nx > 0) + w32_fill_area (f, hdc, face->background, bx, by, nx, ny); + } + /* Must clip because of partially visible lines. */ rowY = WINDOW_TO_FRAME_PIXEL_Y (w, row->y); if (p->y < rowY) @@ -700,12 +753,6 @@ w32_draw_fringe_bitmap (w, row, p) else w32_clip_to_row (w, row, -1, hdc); - 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 && p->which < max_fringe_bmp) { HBITMAP pixmap = fringe_bmp[p->which]; @@ -801,7 +848,7 @@ w32_destroy_fringe_bitmap (which) rarely happens). */ static void -w32_set_terminal_modes (void) +w32_set_terminal_modes (struct terminal *term) { } @@ -809,7 +856,7 @@ w32_set_terminal_modes (void) the W32 windows go away, and suspending requires no action. */ static void -w32_reset_terminal_modes (void) +w32_reset_terminal_modes (struct terminal *term) { } @@ -2608,16 +2655,10 @@ w32_shift_glyphs_for_insert (f, x, y, width, height, shift_by) for X frames. */ static void -x_delete_glyphs (n) +x_delete_glyphs (f, n) + struct frame *f; register int n; { - struct frame *f; - - if (updating_frame) - f = updating_frame; - else - f = SELECTED_FRAME (); - if (! FRAME_W32_P (f)) return; @@ -2629,15 +2670,8 @@ x_delete_glyphs (n) frame. Otherwise clear the selected frame. */ static void -x_clear_frame () +x_clear_frame (struct frame *f) { - struct frame *f; - - if (updating_frame) - f = updating_frame; - else - f = SELECTED_FRAME (); - if (! FRAME_W32_P (f)) return; @@ -2664,18 +2698,14 @@ x_clear_frame () /* Make audible bell. */ static void -w32_ring_bell (void) +w32_ring_bell (struct frame *f) { - struct frame *f; - - f = SELECTED_FRAME (); - BLOCK_INPUT; if (FRAME_W32_P (f) && visible_bell) { int i; - HWND hwnd = FRAME_W32_WINDOW (SELECTED_FRAME ()); + HWND hwnd = FRAME_W32_WINDOW (f); for (i = 0; i < 5; i++) { @@ -2685,7 +2715,7 @@ w32_ring_bell (void) FlashWindow (hwnd, FALSE); } else - w32_sys_ring_bell (); + w32_sys_ring_bell (f); UNBLOCK_INPUT; } @@ -2712,16 +2742,10 @@ w32_set_terminal_window (n) lines or deleting -N lines at vertical position VPOS. */ static void -x_ins_del_lines (vpos, n) +x_ins_del_lines (f, vpos, n) + struct frame *f; int vpos, n; { - struct frame *f; - - if (updating_frame) - f = updating_frame; - else - f = SELECTED_FRAME (); - if (! FRAME_W32_P (f)) return; @@ -3278,7 +3302,7 @@ redo_mouse_highlight () HIWORD (last_mouse_motion_event.lParam)); } -void +static void w32_define_cursor (window, cursor) Window window; Cursor cursor; @@ -3638,6 +3662,7 @@ x_scroll_bar_create (w, top, left, width, height) XSETINT (bar->start, 0); XSETINT (bar->end, 0); bar->dragging = Qnil; + bar->fringe_extended_p = Qnil; /* Requires geometry to be set before call to create the real window */ @@ -3701,6 +3726,7 @@ w32_set_vertical_scroll_bar (w, portion, whole, position) struct scroll_bar *bar; int top, height, left, sb_left, width, sb_width; int window_y, window_height; + int fringe_extended_p; /* Get window dimensions. */ window_box (w, -1, 0, &window_y, 0, &window_height); @@ -3720,9 +3746,20 @@ w32_set_vertical_scroll_bar (w, portion, whole, position) /* Compute the left edge of the scroll bar. */ if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w)) - sb_left = left + width - sb_width - (width - sb_width) / 2; + sb_left = left + (WINDOW_RIGHTMOST_P (w) ? width - sb_width : 0); + else + sb_left = left + (WINDOW_LEFTMOST_P (w) ? 0 : width - sb_width); + + if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)) + fringe_extended_p = (WINDOW_LEFTMOST_P (w) + && WINDOW_LEFT_FRINGE_WIDTH (w) + && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w) + || WINDOW_LEFT_MARGIN_COLS (w) == 0)); else - sb_left = left + (width - sb_width) / 2; + fringe_extended_p = (WINDOW_RIGHTMOST_P (w) + && WINDOW_RIGHT_FRINGE_WIDTH (w) + && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w) + || WINDOW_RIGHT_MARGIN_COLS (w) == 0)); /* Does the scroll bar exist yet? */ if (NILP (w->vertical_scroll_bar)) @@ -3732,7 +3769,10 @@ w32_set_vertical_scroll_bar (w, portion, whole, position) if (width > 0 && height > 0) { hdc = get_frame_dc (f); - w32_clear_area (f, hdc, left, top, width, height); + if (fringe_extended_p) + w32_clear_area (f, hdc, sb_left, top, sb_width, height); + else + w32_clear_area (f, hdc, left, top, width, height); release_frame_dc (f, hdc); } UNBLOCK_INPUT; @@ -3751,7 +3791,8 @@ w32_set_vertical_scroll_bar (w, portion, whole, position) if ( XINT (bar->left) == sb_left && XINT (bar->top) == top && XINT (bar->width) == sb_width - && XINT (bar->height) == height ) + && XINT (bar->height) == height + && !NILP (bar->fringe_extended_p) == fringe_extended_p ) { /* Redraw after clear_frame. */ if (!my_show_window (f, hwnd, SW_NORMAL)) @@ -3768,11 +3809,10 @@ w32_set_vertical_scroll_bar (w, portion, whole, position) hdc = get_frame_dc (f); /* Since Windows scroll bars are smaller than the space reserved for them on the frame, we have to clear "under" them. */ - w32_clear_area (f, hdc, - left, - top, - width, - height); + if (fringe_extended_p) + w32_clear_area (f, hdc, sb_left, top, sb_width, height); + else + w32_clear_area (f, hdc, left, top, width, height); release_frame_dc (f, hdc); } /* Make sure scroll bar is "visible" before moving, to ensure the @@ -3802,6 +3842,8 @@ w32_set_vertical_scroll_bar (w, portion, whole, position) UNBLOCK_INPUT; } } + bar->fringe_extended_p = fringe_extended_p ? Qt : Qnil; + w32_set_scroll_bar_thumb (bar, portion, position, whole); XSETVECTOR (w->vertical_scroll_bar, bar); @@ -4336,7 +4378,7 @@ w32_read_socket (sd, expected, hold_quit) /* Window will be selected only when it is not selected now and last mouse movement event was not in it. Minibuffer window will be selected - iff it is active. */ + only when it is active. */ if (WINDOWP(window) && !EQ (window, last_window) && !EQ (window, selected_window)) @@ -5910,14 +5952,13 @@ x_free_frame_resources (f) /* Destroy the window of frame F. */ - +void x_destroy_window (f) struct frame *f; { struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f); x_free_frame_resources (f); - dpyinfo->reference_count--; } @@ -6177,6 +6218,116 @@ w32_make_rdb (xrm_option) return buffer; } +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, + x_clear_end_of_line, + x_scroll_run, + x_after_update_window_line, + x_update_window_begin, + x_update_window_end, + x_cursor_to, + x_flush, + 0, /* flush_display_optional */ + x_clear_window_mouse_face, + 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 */ + x_draw_glyph_string, + w32_define_frame_cursor, + w32_clear_frame_area, + w32_draw_window_cursor, + w32_draw_vertical_window_border, + w32_shift_glyphs_for_insert +}; + +static void x_delete_terminal (struct terminal *term); + +static struct terminal * +w32_create_terminal (struct w32_display_info *dpyinfo) +{ + struct terminal *terminal; + + terminal = create_terminal (); + + terminal->type = output_w32; + terminal->display_info.w32 = dpyinfo; + dpyinfo->terminal = terminal; + + /* MSVC does not type K&R functions with no arguments correctly, and + so we must explicitly cast them. */ + terminal->clear_frame_hook = x_clear_frame; + terminal->ins_del_lines_hook = x_ins_del_lines; + terminal->delete_glyphs_hook = x_delete_glyphs; + terminal->ring_bell_hook = w32_ring_bell; + terminal->reset_terminal_modes_hook = w32_reset_terminal_modes; + terminal->set_terminal_modes_hook = w32_set_terminal_modes; + terminal->update_begin_hook = x_update_begin; + terminal->update_end_hook = x_update_end; + terminal->set_terminal_window_hook = w32_set_terminal_window; + terminal->read_socket_hook = w32_read_socket; + terminal->frame_up_to_date_hook = w32_frame_up_to_date; + terminal->mouse_position_hook = w32_mouse_position; + terminal->frame_rehighlight_hook = w32_frame_rehighlight; + terminal->frame_raise_lower_hook = w32_frame_raise_lower; + // terminal->fullscreen_hook = XTfullscreen_hook; + terminal->set_vertical_scroll_bar_hook = w32_set_vertical_scroll_bar; + terminal->condemn_scroll_bars_hook = w32_condemn_scroll_bars; + terminal->redeem_scroll_bar_hook = w32_redeem_scroll_bar; + terminal->judge_scroll_bars_hook = w32_judge_scroll_bars; + + terminal->delete_frame_hook = x_destroy_window; + terminal->delete_terminal_hook = x_delete_terminal; + + terminal->rif = &w32_redisplay_interface; + terminal->scroll_region_ok = 1; /* We'll scroll partial frames. */ + terminal->char_ins_del_ok = 1; + terminal->line_ins_del_ok = 1; /* We'll just blt 'em. */ + terminal->fast_clear_end_of_line = 1; /* X does this well. */ + terminal->memory_below_frame = 0; /* We don't remember what scrolls + off the bottom. */ + + return terminal; +} + +static void +x_delete_terminal (struct terminal *terminal) +{ + struct w32_display_info *dpyinfo = terminal->display_info.w32; + int i; + + /* Protect against recursive calls. Fdelete_frame in + delete_terminal calls us back when it deletes our last frame. */ + if (terminal->deleted) + return; + + BLOCK_INPUT; + /* Free the fonts in the font table. */ + for (i = 0; i < dpyinfo->n_fonts; i++) + if (dpyinfo->font_table[i].name) + { + DeleteObject (((XFontStruct*)(dpyinfo->font_table[i].font))->hfont); + } + + x_delete_display (dpyinfo); + UNBLOCK_INPUT; +} + struct w32_display_info * w32_term_init (display_name, xrm_option, resource_name) Lisp_Object display_name; @@ -6184,6 +6335,7 @@ w32_term_init (display_name, xrm_option, resource_name) char *resource_name; { struct w32_display_info *dpyinfo; + struct terminal *terminal; HDC hdc; BLOCK_INPUT; @@ -6197,6 +6349,12 @@ w32_term_init (display_name, xrm_option, resource_name) w32_initialize_display_info (display_name); dpyinfo = &one_w32_display_info; + terminal = w32_create_terminal (dpyinfo); + + /* Set the name of the terminal. */ + terminal->name = (char *) xmalloc (SBYTES (display_name) + 1); + strncpy (terminal->name, SDATA (display_name), SBYTES (display_name)); + terminal->name[SBYTES (display_name)] = 0; dpyinfo->xrdb = xrm_option ? w32_make_rdb (xrm_option) : NULL; @@ -6226,6 +6384,9 @@ w32_term_init (display_name, xrm_option, resource_name) w32_defined_color (0, "black", &color, 1); } + /* Add the default keyboard. */ + add_keyboard_wait_descriptor (0); + /* Create Fringe Bitmaps and store them for later use. On W32, bitmaps are all unsigned short, as Windows requires @@ -6257,7 +6418,6 @@ w32_term_init (display_name, xrm_option, resource_name) } /* Get rid of display DPYINFO, assuming all frames are already gone. */ - void x_delete_display (dpyinfo) struct w32_display_info *dpyinfo; @@ -6308,74 +6468,9 @@ x_delete_display (dpyinfo) DWORD WINAPI w32_msg_worker (void * arg); -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, - x_clear_end_of_line, - x_scroll_run, - x_after_update_window_line, - x_update_window_begin, - x_update_window_end, - x_cursor_to, - x_flush, - 0, /* flush_display_optional */ - x_clear_window_mouse_face, - 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 */ - x_draw_glyph_string, - w32_define_frame_cursor, - w32_clear_frame_area, - w32_draw_window_cursor, - w32_draw_vertical_window_border, - w32_shift_glyphs_for_insert -}; - -void +static void w32_initialize () { - rif = &w32_redisplay_interface; - - /* MSVC does not type K&R functions with no arguments correctly, and - so we must explicitly cast them. */ - clear_frame_hook = (void (*)(void)) x_clear_frame; - ring_bell_hook = (void (*)(void)) w32_ring_bell; - update_begin_hook = x_update_begin; - update_end_hook = x_update_end; - - read_socket_hook = w32_read_socket; - - frame_up_to_date_hook = w32_frame_up_to_date; - - mouse_position_hook = w32_mouse_position; - frame_rehighlight_hook = w32_frame_rehighlight; - frame_raise_lower_hook = w32_frame_raise_lower; - set_vertical_scroll_bar_hook = w32_set_vertical_scroll_bar; - condemn_scroll_bars_hook = w32_condemn_scroll_bars; - redeem_scroll_bar_hook = w32_redeem_scroll_bar; - judge_scroll_bars_hook = w32_judge_scroll_bars; - - TTY_SCROLL_REGION_OK (CURTTY ()) = 1; /* we'll scroll partial frames */ - TTY_CHAR_INS_DEL_OK (CURTTY ()) = 1; - TTY_LINE_INS_DEL_OK (CURTTY ()) = 1; /* we'll just blt 'em */ - TTY_FAST_CLEAR_END_OF_LINE (CURTTY ()) = 1; /* X does this well */ - TTY_MEMORY_BELOW_FRAME (CURTTY ()) = 0; /* we don't remember what - scrolls off the - bottom */ baud_rate = 19200; w32_system_caret_hwnd = NULL;