diff options
Diffstat (limited to 'src/frame.c')
-rw-r--r-- | src/frame.c | 1507 |
1 files changed, 928 insertions, 579 deletions
diff --git a/src/frame.c b/src/frame.c index d9b33c638a1..2ce5a623853 100644 --- a/src/frame.c +++ b/src/frame.c @@ -51,71 +51,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include "msdos.h" #include "dosfns.h" #endif - -#ifdef HAVE_NS -Lisp_Object Qns_parse_geometry; -#endif - -Lisp_Object Qframep, Qframe_live_p; -Lisp_Object Qicon, Qmodeline; -Lisp_Object Qonly, Qnone; -Lisp_Object Qx, Qw32, Qpc, Qns; -Lisp_Object Qvisible; -Lisp_Object Qdisplay_type; -static Lisp_Object Qbackground_mode; -Lisp_Object Qnoelisp; - -static Lisp_Object Qx_frame_parameter; -Lisp_Object Qx_resource_name; -Lisp_Object Qterminal; - -/* Frame parameters (set or reported). */ - -Lisp_Object Qauto_raise, Qauto_lower; -Lisp_Object Qborder_color, Qborder_width; -Lisp_Object Qcursor_color, Qcursor_type; -Lisp_Object Qheight, Qwidth; -Lisp_Object Qleft, Qright; -Lisp_Object Qicon_left, Qicon_top, Qicon_type, Qicon_name; -Lisp_Object Qtooltip; -Lisp_Object Qinternal_border_width; -Lisp_Object Qright_divider_width, Qbottom_divider_width; -Lisp_Object Qmouse_color; -Lisp_Object Qminibuffer; -Lisp_Object Qscroll_bar_width, Qvertical_scroll_bars; -Lisp_Object Qvisibility; -Lisp_Object Qscroll_bar_foreground, Qscroll_bar_background; -Lisp_Object Qscreen_gamma; -Lisp_Object Qline_spacing; -static Lisp_Object Quser_position, Quser_size; -Lisp_Object Qwait_for_wm; -static Lisp_Object Qwindow_id; -#ifdef HAVE_X_WINDOWS -static Lisp_Object Qouter_window_id; +#ifdef USE_X_TOOLKIT +#include "widget.h" #endif -Lisp_Object Qparent_id; -Lisp_Object Qtitle, Qname; -static Lisp_Object Qexplicit_name; -Lisp_Object Qunsplittable; -Lisp_Object Qmenu_bar_lines, Qtool_bar_lines, Qtool_bar_position; -Lisp_Object Qleft_fringe, Qright_fringe; -Lisp_Object Qbuffer_predicate; -static Lisp_Object Qbuffer_list, Qburied_buffer_list; -Lisp_Object Qtty_color_mode; -Lisp_Object Qtty, Qtty_type; - -Lisp_Object Qfullscreen, Qfullwidth, Qfullheight, Qfullboth, Qmaximized; -Lisp_Object Qsticky; -Lisp_Object Qfont_backend; -Lisp_Object Qalpha; - -Lisp_Object Qface_set_after_frame_default; - -static Lisp_Object Qfocus_in_hook; -static Lisp_Object Qfocus_out_hook; -static Lisp_Object Qdelete_frame_functions; - -static Lisp_Object Qgeometry, Qworkarea, Qmm_size, Qframes, Qsource; /* The currently selected frame. */ @@ -129,6 +67,9 @@ static struct frame *last_nonminibuf_frame; /* False means there are no visible garbaged frames. */ bool frame_garbaged; +/* The default tool bar height for future frames. */ +int frame_default_tool_bar_height; + #ifdef HAVE_WINDOW_SYSTEM static void x_report_frame_params (struct frame *, Lisp_Object *); #endif @@ -163,19 +104,16 @@ decode_any_frame (register Lisp_Object frame) return XFRAME (frame); } +#ifdef HAVE_WINDOW_SYSTEM + bool window_system_available (struct frame *f) { - if (f) - return FRAME_WINDOW_P (f) || FRAME_MSDOS_P (f); - else -#ifdef HAVE_WINDOW_SYSTEM - return x_display_list != NULL; -#else - return 0; -#endif + return f ? FRAME_WINDOW_P (f) || FRAME_MSDOS_P (f) : x_display_list != NULL; } +#endif /* HAVE_WINDOW_SYSTEM */ + struct frame * decode_window_system_frame (Lisp_Object frame) { @@ -194,30 +132,34 @@ check_window_system (struct frame *f) : "Window system is not in use or not initialized"); } -static void -set_menu_bar_lines_1 (Lisp_Object window, int n) -{ - struct window *w = XWINDOW (window); - struct frame *f = XFRAME (WINDOW_FRAME (w)); - - w->top_line += n; - w->pixel_top += n * FRAME_LINE_HEIGHT (f); - w->total_lines -= n; - w->pixel_height -= n * FRAME_LINE_HEIGHT (f); - - /* Handle just the top child in a vertical split. */ - if (WINDOW_VERTICAL_COMBINATION_P (w)) - set_menu_bar_lines_1 (w->contents, n); - else if (WINDOW_HORIZONTAL_COMBINATION_P (w)) - /* Adjust all children in a horizontal split. */ - for (window = w->contents; !NILP (window); window = w->next) - { - w = XWINDOW (window); - set_menu_bar_lines_1 (window, n); - } +/* Return the value of frame parameter PROP in frame FRAME. */ + +Lisp_Object +get_frame_param (register struct frame *frame, Lisp_Object prop) +{ + register Lisp_Object tem; + + tem = Fassq (prop, frame->param_alist); + if (EQ (tem, Qnil)) + return tem; + return Fcdr (tem); } -void +/* Return 1 if `frame-inhibit-implied-resize' is non-nil or fullscreen + state of frame F would be affected by a vertical (horizontal if + HORIZONTAL is true) resize. PARAMETER is the symbol of the frame + parameter that is changed. */ +bool +frame_inhibit_resize (struct frame *f, bool horizontal, Lisp_Object parameter) +{ + return (EQ (frame_inhibit_implied_resize, Qt) + || (CONSP (frame_inhibit_implied_resize) + && !NILP (Fmemq (parameter, frame_inhibit_implied_resize))) + || !NILP (get_frame_param (f, Qfullscreen)) + || FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f)); +} + +static void set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) { int nlines; @@ -238,11 +180,11 @@ set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) if (nlines != olines) { windows_or_buffers_changed = 14; - FRAME_WINDOW_SIZES_CHANGED (f) = 1; FRAME_MENU_BAR_LINES (f) = nlines; FRAME_MENU_BAR_HEIGHT (f) = nlines * FRAME_LINE_HEIGHT (f); - set_menu_bar_lines_1 (f->root_window, nlines - olines); - adjust_frame_glyphs (f); + change_frame_size (f, FRAME_COLS (f), + FRAME_LINES (f) + olines - nlines, + 0, 1, 0, 0); } } @@ -325,6 +267,317 @@ predicates which report frame's specific UI-related capabilities. */) return type; } +/* Placeholder used by temacs -nw before window.el is loaded. */ +DEFUN ("frame-windows-min-size", Fframe_windows_min_size, + Sframe_windows_min_size, 4, 4, 0, + doc: /* */ + attributes: const) + (Lisp_Object frame, Lisp_Object horizontal, + Lisp_Object ignore, Lisp_Object pixelwise) +{ + return make_number (0); +} + +static int +frame_windows_min_size (Lisp_Object frame, Lisp_Object horizontal, + Lisp_Object ignore, Lisp_Object pixelwise) +{ + return XINT (call4 (Qframe_windows_min_size, frame, horizontal, + ignore, pixelwise)); +} + + +/* Make sure windows sizes of frame F are OK. new_width and new_height + are in pixels. A value of -1 means no change is requested for that + size (but the frame may still have to be resized to accommodate + windows with their minimum sizes). This can either issue a request + to resize the frame externally (via x_set_window_size), to resize the + frame internally (via resize_frame_windows) or do nothing at all. + + The argument INHIBIT can assume the following values: + + 0 means to unconditionally call x_set_window_size even if sizes + apparently do not change. Fx_create_frame uses this to pass the + initial size to the window manager. + + 1 means to call x_set_window_size if the outer frame size really + changes. Fset_frame_size, Fset_frame_height, ... use this. + + 2 means to call x_set_window_size provided frame_inhibit_resize + allows it. The menu and tool bar code use this ("3" won't work + here in general because menu and tool bar are often not counted in + the frame's text height). + + 3 means call x_set_window_size if window minimum sizes must be + preserved or frame_inhibit_resize allows it. x_set_left_fringe, + x_set_scroll_bar_width, x_new_font ... use (or should use) this. + + 4 means call x_set_window_size only if window minimum sizes must be + preserved. x_set_right_divider_width, x_set_border_width and the + code responsible for wrapping the tool bar use this. + + 5 means to never call x_set_window_size. change_frame_size uses + this. + + Note that even when x_set_window_size is not called, individual + windows may have to be resized (via `window--sanitize-window-sizes') + in order to support minimum size constraints. + + PRETEND is as for change_frame_size. PARAMETER, if non-nil, is the + symbol of the parameter changed (like `menu-bar-lines', `font', ...). + This is passed on to frame_inhibit_resize to let the latter decide on + a case-by-case basis whether the frame may be resized externally. */ +void +adjust_frame_size (struct frame *f, int new_width, int new_height, int inhibit, + bool pretend, Lisp_Object parameter) +{ + int unit_width = FRAME_COLUMN_WIDTH (f); + int unit_height = FRAME_LINE_HEIGHT (f); + int old_pixel_width = FRAME_PIXEL_WIDTH (f); + int old_pixel_height = FRAME_PIXEL_HEIGHT (f); + int old_cols = FRAME_COLS (f); + int old_lines = FRAME_LINES (f); + int new_pixel_width, new_pixel_height; + /* The following two values are calculated from the old frame pixel + sizes and any "new" settings for tool bar, menu bar and internal + borders. We do it this way to detect whether we have to call + x_set_window_size as consequence of the new settings. */ + int windows_width = FRAME_WINDOWS_WIDTH (f); + int windows_height = FRAME_WINDOWS_HEIGHT (f); + int min_windows_width, min_windows_height; + /* These are a bit tedious, maybe we should use a macro. */ + struct window *r = XWINDOW (FRAME_ROOT_WINDOW (f)); + int old_windows_width = WINDOW_PIXEL_WIDTH (r); + int old_windows_height + = (WINDOW_PIXEL_HEIGHT (r) + + (FRAME_HAS_MINIBUF_P (f) + ? WINDOW_PIXEL_HEIGHT (XWINDOW (FRAME_MINIBUF_WINDOW (f))) + : 0)); + int new_windows_width, new_windows_height; + int old_text_width = FRAME_TEXT_WIDTH (f); + int old_text_height = FRAME_TEXT_HEIGHT (f); + /* If a size is < 0 use the old value. */ + int new_text_width = (new_width >= 0) ? new_width : old_text_width; + int new_text_height = (new_height >= 0) ? new_height : old_text_height; + int new_cols, new_lines; + bool inhibit_horizontal, inhibit_vertical; + Lisp_Object frame; + + XSETFRAME (frame, f); + + /* `make-frame' initializes Vframe_adjust_size_history to (Qt) and + strips its car when exiting. Just in case make sure its size never + exceeds 100. */ + if (!NILP (Fconsp (Vframe_adjust_size_history)) + && EQ (Fcar (Vframe_adjust_size_history), Qt) + && XFASTINT (Fsafe_length (Vframe_adjust_size_history)) <= 100) + Vframe_adjust_size_history = + Fcons (Qt, Fcons (list5 (make_number (0), + make_number (new_text_width), + make_number (new_text_height), + make_number (inhibit), parameter), + Fcdr (Vframe_adjust_size_history))); + + /* The following two values are calculated from the old window body + sizes and any "new" settings for scroll bars, dividers, fringes and + margins (though the latter should have been processed already). */ + min_windows_width + = frame_windows_min_size (frame, Qt, (inhibit == 5) ? Qt : Qnil, Qt); + min_windows_height + = frame_windows_min_size (frame, Qnil, (inhibit == 5) ? Qt : Qnil, Qt); + + if (inhibit >= 2 && inhibit <= 4) + /* If INHIBIT is in [2..4] inhibit if the "old" window sizes stay + within the limits and either frame_inhibit_resize tells us to do + so or INHIBIT equals 4. */ + { + inhibit_horizontal = ((windows_width >= min_windows_width + && (inhibit == 4 + || frame_inhibit_resize (f, true, parameter))) + ? true : false); + inhibit_vertical = ((windows_height >= min_windows_height + && (inhibit == 4 + || frame_inhibit_resize (f, false, parameter))) + ? true : false); + } + else + /* Otherwise inhibit if INHIBIT equals 5. */ + inhibit_horizontal = inhibit_vertical = inhibit == 5; + + new_pixel_width = ((inhibit_horizontal && (inhibit < 5)) + ? old_pixel_width + : max (FRAME_TEXT_TO_PIXEL_WIDTH (f, new_text_width), + min_windows_width + + 2 * FRAME_INTERNAL_BORDER_WIDTH (f))); + new_windows_width = new_pixel_width - 2 * FRAME_INTERNAL_BORDER_WIDTH (f); + new_text_width = FRAME_PIXEL_TO_TEXT_WIDTH (f, new_pixel_width); + new_cols = new_text_width / unit_width; + + new_pixel_height = ((inhibit_vertical && (inhibit < 5)) + ? old_pixel_height + : max (FRAME_TEXT_TO_PIXEL_HEIGHT (f, new_text_height), + min_windows_height + + FRAME_TOP_MARGIN_HEIGHT (f) + + 2 * FRAME_INTERNAL_BORDER_WIDTH (f))); + new_windows_height = (new_pixel_height + - FRAME_TOP_MARGIN_HEIGHT (f) + - 2 * FRAME_INTERNAL_BORDER_WIDTH (f)); + new_text_height = FRAME_PIXEL_TO_TEXT_HEIGHT (f, new_pixel_height); + new_lines = new_text_height / unit_height; + +#ifdef HAVE_WINDOW_SYSTEM + if (FRAME_WINDOW_P (f) + && f->can_x_set_window_size + && ((!inhibit_horizontal + && (new_pixel_width != old_pixel_width + || inhibit == 0 || inhibit == 2)) + || (!inhibit_vertical + && (new_pixel_height != old_pixel_height + || inhibit == 0 || inhibit == 2)))) + /* We are either allowed to change the frame size or the minimum + sizes request such a change. Do not care for fixing minimum + sizes here, we do that eventually when we're called from + change_frame_size. */ + { + /* Make sure we respect fullheight and fullwidth. */ + if (inhibit_horizontal) + new_text_width = old_text_width; + else if (inhibit_vertical) + new_text_height = old_text_height; + + if (!NILP (Fconsp (Vframe_adjust_size_history)) + && EQ (Fcar (Vframe_adjust_size_history), Qt) + && XFASTINT (Fsafe_length (Vframe_adjust_size_history)) <= 100) + Vframe_adjust_size_history = + Fcons (Qt, Fcons (list5 (make_number (1), + make_number (new_text_width), + make_number (new_text_height), + make_number (new_cols), + make_number (new_lines)), + Fcdr (Vframe_adjust_size_history))); + + x_set_window_size (f, 0, new_text_width, new_text_height, 1); + f->resized_p = true; + + return; + } +#endif + + if (new_text_width == old_text_width + && new_text_height == old_text_height + && new_windows_width == old_windows_width + && new_windows_height == old_windows_height + && new_pixel_width == old_pixel_width + && new_pixel_height == old_pixel_height + && new_cols == old_cols + && new_lines == old_lines) + /* No change. Sanitize window sizes and return. */ + { + sanitize_window_sizes (frame, Qt); + sanitize_window_sizes (frame, Qnil); + + return; + } + + block_input (); + +#ifdef MSDOS + /* We only can set screen dimensions to certain values supported + by our video hardware. Try to find the smallest size greater + or equal to the requested dimensions. */ + dos_set_window_size (&new_lines, &new_cols); +#endif + + if (new_windows_width != old_windows_width) + { + resize_frame_windows (f, new_windows_width, 1, 1); + + /* MSDOS frames cannot PRETEND, as they change frame size by + manipulating video hardware. */ + if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f)) + FrameCols (FRAME_TTY (f)) = new_cols; + +#if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS) + if (WINDOWP (f->tool_bar_window)) + { + XWINDOW (f->tool_bar_window)->pixel_width = new_windows_width; + XWINDOW (f->tool_bar_window)->total_cols + = new_windows_width / unit_width; + } +#endif + } + + if (new_windows_height != old_windows_height + /* When the top margin has changed we have to recalculate the top + edges of all windows. No such calculation is necessary for the + left edges. */ + || WINDOW_TOP_PIXEL_EDGE (r) != FRAME_TOP_MARGIN_HEIGHT (f)) + { + resize_frame_windows (f, new_windows_height, 0, 1); + + /* MSDOS frames cannot PRETEND, as they change frame size by + manipulating video hardware. */ + if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f)) + FrameRows (FRAME_TTY (f)) = new_lines + FRAME_TOP_MARGIN (f); + } + + /* Assign new sizes. */ + FRAME_TEXT_WIDTH (f) = new_text_width; + FRAME_TEXT_HEIGHT (f) = new_text_height; + FRAME_PIXEL_WIDTH (f) = new_pixel_width; + FRAME_PIXEL_HEIGHT (f) = new_pixel_height; + SET_FRAME_COLS (f, new_cols); + SET_FRAME_LINES (f, new_lines); + + if (!NILP (Fconsp (Vframe_adjust_size_history)) + && EQ (Fcar (Vframe_adjust_size_history), Qt) + && XFASTINT (Fsafe_length (Vframe_adjust_size_history)) <= 100) + Vframe_adjust_size_history = + Fcons (Qt, Fcons (list5 (make_number (2), + make_number (new_text_width), + make_number (new_text_height), + make_number (new_cols), + make_number (new_lines)), + Fcdr (Vframe_adjust_size_history))); + + { + struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f)); + int text_area_x, text_area_y, text_area_width, text_area_height; + + window_box (w, TEXT_AREA, &text_area_x, &text_area_y, &text_area_width, + &text_area_height); + if (w->cursor.x >= text_area_x + text_area_width) + w->cursor.hpos = w->cursor.x = 0; + if (w->cursor.y >= text_area_y + text_area_height) + w->cursor.vpos = w->cursor.y = 0; + } + + /* Sanitize window sizes. */ + sanitize_window_sizes (frame, Qt); + sanitize_window_sizes (frame, Qnil); + + adjust_frame_glyphs (f); + calculate_costs (f); + SET_FRAME_GARBAGED (f); + + /* A frame was "resized" if one of its pixelsizes changed, even if its + X window wasn't resized at all. */ + f->resized_p = (new_pixel_width != old_pixel_width + || new_pixel_height != old_pixel_height); + + unblock_input (); + + run_window_configuration_change_hook (f); +} + +/* Allocate basically initialized frame. */ + +static struct frame * +allocate_frame (void) +{ + return ALLOCATE_ZEROED_PSEUDOVECTOR (struct frame, face_cache, PVEC_FRAME); +} + struct frame * make_frame (bool mini_p) { @@ -337,9 +590,11 @@ make_frame (bool mini_p) f = allocate_frame (); XSETFRAME (frame, f); +#ifdef USE_GTK /* Initialize Lisp data. Note that allocate_frame initializes all Lisp data to nil, so do it only for slots which should not be nil. */ fset_tool_bar_position (f, Qtop); +#endif /* Initialize non-Lisp data. Note that allocate_frame zeroes out all non-Lisp data, so do it only for slots which should not be zero. @@ -348,11 +603,18 @@ make_frame (bool mini_p) f->wants_modeline = true; f->redisplay = true; f->garbaged = true; - f->vertical_scroll_bar_type = vertical_scroll_bar_none; + f->can_x_set_window_size = false; + f->can_run_window_configuration_change_hook = false; + f->tool_bar_redisplayed_once = false; f->column_width = 1; /* !FRAME_WINDOW_P value. */ f->line_height = 1; /* !FRAME_WINDOW_P value. */ #ifdef HAVE_WINDOW_SYSTEM + f->vertical_scroll_bar_type = vertical_scroll_bar_none; + f->horizontal_scroll_bars = false; f->want_fullscreen = FULLSCREEN_NONE; +#if ! defined (USE_GTK) && ! defined (HAVE_NS) + f->last_tool_bar_item = -1; +#endif #endif root_window = make_window (); @@ -378,10 +640,10 @@ make_frame (bool mini_p) /* 10 is arbitrary, just so that there is "something there." - Correct size will be set up later with change_frame_size. */ + Correct size will be set up later with adjust_frame_size. */ SET_FRAME_COLS (f, 10); - FRAME_LINES (f) = 10; + SET_FRAME_LINES (f, 10); SET_FRAME_WIDTH (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f)); SET_FRAME_HEIGHT (f, FRAME_LINES (f) * FRAME_LINE_HEIGHT (f)); @@ -419,11 +681,15 @@ make_frame (bool mini_p) } if (mini_p) - set_window_buffer (mini_window, - (NILP (Vminibuffer_list) - ? get_minibuffer (0) - : Fcar (Vminibuffer_list)), - 0, 0); + { + set_window_buffer (mini_window, + (NILP (Vminibuffer_list) + ? get_minibuffer (0) + : Fcar (Vminibuffer_list)), + 0, 0); + /* No horizontal scroll bars in minibuffers. */ + wset_horizontal_scroll_bar (mw, Qnil); + } fset_root_window (f, root_window); fset_selected_window (f, root_window); @@ -567,7 +833,10 @@ make_initial_frame (void) FRAME_FOREGROUND_PIXEL (f) = FACE_TTY_DEFAULT_FG_COLOR; FRAME_BACKGROUND_PIXEL (f) = FACE_TTY_DEFAULT_BG_COLOR; - FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none; +#ifdef HAVE_WINDOW_SYSTEM + f->vertical_scroll_bar_type = vertical_scroll_bar_none; + f->horizontal_scroll_bars = false; +#endif /* The default value of menu-bar-mode is t. */ set_menu_bar_lines (f, make_number (1), Qnil); @@ -617,9 +886,15 @@ make_terminal_frame (struct terminal *terminal) FRAME_BACKGROUND_PIXEL (f) = FACE_TTY_DEFAULT_BG_COLOR; #endif /* not MSDOS */ - FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none; +#ifdef HAVE_WINDOW_SYSTEM + f->vertical_scroll_bar_type = vertical_scroll_bar_none; + f->horizontal_scroll_bars = false; +#endif + FRAME_MENU_BAR_LINES (f) = NILP (Vmenu_bar_mode) ? 0 : 1; + FRAME_LINES (f) = FRAME_LINES (f) - FRAME_MENU_BAR_LINES (f); FRAME_MENU_BAR_HEIGHT (f) = FRAME_MENU_BAR_LINES (f) * FRAME_LINE_HEIGHT (f); + FRAME_TEXT_HEIGHT (f) = FRAME_TEXT_HEIGHT (f) - FRAME_MENU_BAR_HEIGHT (f); /* Set the top frame to the newly created frame. */ if (FRAMEP (FRAME_TTY (f)->top_frame) @@ -701,7 +976,7 @@ affects all frames on the same terminal device. */) if (CONSP (terminal)) { terminal = XCDR (terminal); - t = get_terminal (terminal, 1); + t = decode_live_terminal (terminal); } #ifdef MSDOS if (t && t != the_only_display_info.terminal) @@ -716,22 +991,24 @@ affects all frames on the same terminal device. */) { char *name = 0, *type = 0; Lisp_Object tty, tty_type; + USE_SAFE_ALLOCA; tty = get_future_frame_param (Qtty, parms, (FRAME_TERMCAP_P (XFRAME (selected_frame)) ? FRAME_TTY (XFRAME (selected_frame))->name : NULL)); if (!NILP (tty)) - name = xlispstrdupa (tty); + SAFE_ALLOCA_STRING (name, tty); tty_type = get_future_frame_param (Qtty_type, parms, (FRAME_TERMCAP_P (XFRAME (selected_frame)) ? FRAME_TTY (XFRAME (selected_frame))->type : NULL)); if (!NILP (tty_type)) - type = xlispstrdupa (tty_type); + SAFE_ALLOCA_STRING (type, tty_type); t = init_tty (name, type, 0); /* Errors are not fatal. */ + SAFE_FREE (); } f = make_terminal_frame (t); @@ -739,7 +1016,7 @@ affects all frames on the same terminal device. */) { int width, height; get_tty_size (fileno (FRAME_TTY (f)->input), &width, &height); - change_frame_size (f, width, height, 0, 0, 0, 0); + adjust_frame_size (f, width, height - FRAME_MENU_BAR_LINES (f), 5, 0, Qnil); } adjust_frame_glyphs (f); @@ -870,8 +1147,8 @@ do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object nor frame's data. */ if (FRAME_COLS (f) != FrameCols (tty)) FrameCols (tty) = FRAME_COLS (f); - if (FRAME_LINES (f) != FrameRows (tty)) - FrameRows (tty) = FRAME_LINES (f); + if (FRAME_TOTAL_LINES (f) != FrameRows (tty)) + FrameRows (tty) = FRAME_TOTAL_LINES (f); } tty->top_frame = frame; } @@ -926,7 +1203,7 @@ to that frame. */) { /* Preserve prefix arg that the command loop just cleared. */ kset_prefix_arg (current_kboard, Vcurrent_prefix_arg); - Frun_hooks (1, &Qmouse_leave_buffer_hook); + run_hook (Qmouse_leave_buffer_hook); /* `switch-frame' implies a focus in. */ call1 (intern ("handle-focus-in"), event); return do_switch_frame (event, 0, 0, Qnil); @@ -1365,7 +1642,9 @@ delete_frame (Lisp_Object frame, Lisp_Object force) fset_buried_buffer_list (f, Qnil); free_font_driver_list (f); +#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) xfree (f->namebuf); +#endif xfree (f->decode_mode_spec_buffer); xfree (FRAME_INSERT_COST (f)); xfree (FRAME_DELETEN_COST (f)); @@ -1608,6 +1887,42 @@ and nil for X and Y. */) RETURN_UNGCPRO (retval); } +#ifdef HAVE_WINDOW_SYSTEM + +/* On frame F, convert character coordinates X and Y to pixel + coordinates *PIX_X and *PIX_Y. */ + +static void +frame_char_to_pixel_position (struct frame *f, int x, int y, + int *pix_x, int *pix_y) +{ + *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 > FRAME_PIXEL_WIDTH (f)) + *pix_x = FRAME_PIXEL_WIDTH (f); + + if (*pix_y < 0) + *pix_y = 0; + if (*pix_y > FRAME_PIXEL_HEIGHT (f)) + *pix_y = FRAME_PIXEL_HEIGHT (f); +} + +/* On frame F, reposition mouse pointer to character coordinates X and Y. */ + +static void +frame_set_mouse_position (struct frame *f, int x, int y) +{ + int pix_x, pix_y; + + frame_char_to_pixel_position (f, x, y, &pix_x, &pix_y); + frame_set_mouse_pixel_position (f, pix_x, pix_y); +} + +#endif /* HAVE_WINDOW_SYSTEM */ + DEFUN ("set-mouse-position", Fset_mouse_position, Sset_mouse_position, 3, 3, 0, doc: /* Move the mouse pointer to the center of character cell (X,Y) in FRAME. Coordinates are relative to the frame, not a window, @@ -1633,7 +1948,7 @@ before calling this function on it, like this. #ifdef HAVE_WINDOW_SYSTEM if (FRAME_WINDOW_P (XFRAME (frame))) /* Warping the mouse will cause enternotify and focus events. */ - x_set_mouse_position (XFRAME (frame), XINT (x), XINT (y)); + frame_set_mouse_position (XFRAME (frame), XINT (x), XINT (y)); #else #if defined (MSDOS) if (FRAME_MSDOS_P (XFRAME (frame))) @@ -1674,7 +1989,7 @@ before calling this function on it, like this. #ifdef HAVE_WINDOW_SYSTEM if (FRAME_WINDOW_P (XFRAME (frame))) /* Warping the mouse will cause enternotify and focus events. */ - x_set_mouse_pixel_position (XFRAME (frame), XINT (x), XINT (y)); + frame_set_mouse_pixel_position (XFRAME (frame), XINT (x), XINT (y)); #else #if defined (MSDOS) if (FRAME_MSDOS_P (XFRAME (frame))) @@ -1941,25 +2256,27 @@ If there is no window system support, this function does nothing. */) return Qnil; } - -/* Return the value of frame parameter PROP in frame FRAME. */ - -#ifdef HAVE_WINDOW_SYSTEM -#if !HAVE_NS && !HAVE_NTGUI -static -#endif -Lisp_Object -get_frame_param (register struct frame *frame, Lisp_Object prop) +DEFUN ("frame-can-run-window-configuration-change-hook", + Fcan_run_window_configuration_change_hook, + Scan_run_window_configuration_change_hook, 2, 2, 0, + doc: /* Whether `window-configuration-change-hook' is run for frame FRAME. +FRAME nil means use the selected frame. Second argument ALLOW non-nil +means functions on `window-configuration-change-hook' are called +whenever the window configuration of FRAME changes. ALLOW nil means +these functions are not called. + +This function is currently called by `face-set-after-frame-default' only +and should be otherwise used with utter care to avoid that running +functions on `window-configuration-change-hook' is impeded forever. */) + (Lisp_Object frame, Lisp_Object allow) { - register Lisp_Object tem; + struct frame *f = decode_live_frame (frame); - tem = Fassq (prop, frame->param_alist); - if (EQ (tem, Qnil)) - return tem; - return Fcdr (tem); + f->can_run_window_configuration_change_hook = NILP (allow) ? false : true; + return Qnil; } -#endif + /* Discard BUFFER from the buffer-list and buried-buffer-list of each frame. */ void @@ -2043,20 +2360,6 @@ set_term_frame_name (struct frame *f, Lisp_Object name) update_mode_lines = 16; } -#ifdef HAVE_NTGUI -void -set_frame_param (struct frame *f, Lisp_Object prop, Lisp_Object val) -{ - register Lisp_Object old_alist_elt; - - old_alist_elt = Fassq (prop, f->param_alist); - if (EQ (old_alist_elt, Qnil)) - fset_param_alist (f, Fcons (Fcons (prop, val), f->param_alist)); - else - Fsetcdr (old_alist_elt, val); -} -#endif - void store_frame_param (struct frame *f, Lisp_Object prop, Lisp_Object val) { @@ -2148,6 +2451,18 @@ store_frame_param (struct frame *f, Lisp_Object prop, Lisp_Object val) } } +/* Return color matches UNSPEC on frame F or nil if UNSPEC + is not an unspecified foreground or background color. */ + +static Lisp_Object +frame_unspecified_color (struct frame *f, Lisp_Object unspec) +{ + return (!strncmp (SSDATA (unspec), unspecified_bg, SBYTES (unspec)) + ? tty_color_name (f, FRAME_BACKGROUND_PIXEL (f)) + : (!strncmp (SSDATA (unspec), unspecified_fg, SBYTES (unspec)) + ? tty_color_name (f, FRAME_FOREGROUND_PIXEL (f)) : Qnil)); +} + DEFUN ("frame-parameters", Fframe_parameters, Sframe_parameters, 0, 1, 0, doc: /* Return the parameters-alist of frame FRAME. It is a list of elements of the form (PARM . VALUE), where PARM is a symbol. @@ -2168,8 +2483,6 @@ If FRAME is omitted or nil, return information on the currently selected frame. if (!FRAME_WINDOW_P (f)) { - int fg = FRAME_FOREGROUND_PIXEL (f); - int bg = FRAME_BACKGROUND_PIXEL (f); Lisp_Object elt; /* If the frame's parameter alist says the colors are @@ -2178,31 +2491,23 @@ If FRAME is omitted or nil, return information on the currently selected frame. elt = Fassq (Qforeground_color, alist); if (CONSP (elt) && STRINGP (XCDR (elt))) { - if (strncmp (SSDATA (XCDR (elt)), - unspecified_bg, - SCHARS (XCDR (elt))) == 0) - store_in_alist (&alist, Qforeground_color, tty_color_name (f, bg)); - else if (strncmp (SSDATA (XCDR (elt)), - unspecified_fg, - SCHARS (XCDR (elt))) == 0) - store_in_alist (&alist, Qforeground_color, tty_color_name (f, fg)); + elt = frame_unspecified_color (f, XCDR (elt)); + if (!NILP (elt)) + store_in_alist (&alist, Qforeground_color, elt); } else - store_in_alist (&alist, Qforeground_color, tty_color_name (f, fg)); + store_in_alist (&alist, Qforeground_color, + tty_color_name (f, FRAME_FOREGROUND_PIXEL (f))); elt = Fassq (Qbackground_color, alist); if (CONSP (elt) && STRINGP (XCDR (elt))) { - if (strncmp (SSDATA (XCDR (elt)), - unspecified_fg, - SCHARS (XCDR (elt))) == 0) - store_in_alist (&alist, Qbackground_color, tty_color_name (f, fg)); - else if (strncmp (SSDATA (XCDR (elt)), - unspecified_bg, - SCHARS (XCDR (elt))) == 0) - store_in_alist (&alist, Qbackground_color, tty_color_name (f, bg)); + elt = frame_unspecified_color (f, XCDR (elt)); + if (!NILP (elt)) + store_in_alist (&alist, Qbackground_color, elt); } else - store_in_alist (&alist, Qbackground_color, tty_color_name (f, bg)); + store_in_alist (&alist, Qbackground_color, + tty_color_name (f, FRAME_BACKGROUND_PIXEL (f))); store_in_alist (&alist, intern ("font"), build_string (FRAME_MSDOS_P (f) ? "ms-dos" @@ -2282,29 +2587,7 @@ If FRAME is nil, describe the currently selected frame. */) important when param_alist's notion of colors is "unspecified". We need to do the same here. */ if (STRINGP (value) && !FRAME_WINDOW_P (f)) - { - const char *color_name; - ptrdiff_t csz; - - if (EQ (parameter, Qbackground_color)) - { - color_name = SSDATA (value); - csz = SCHARS (value); - if (strncmp (color_name, unspecified_bg, csz) == 0) - value = tty_color_name (f, FRAME_BACKGROUND_PIXEL (f)); - else if (strncmp (color_name, unspecified_fg, csz) == 0) - value = tty_color_name (f, FRAME_FOREGROUND_PIXEL (f)); - } - else if (EQ (parameter, Qforeground_color)) - { - color_name = SSDATA (value); - csz = SCHARS (value); - if (strncmp (color_name, unspecified_fg, csz) == 0) - value = tty_color_name (f, FRAME_FOREGROUND_PIXEL (f)); - else if (strncmp (color_name, unspecified_bg, csz) == 0) - value = tty_color_name (f, FRAME_BACKGROUND_PIXEL (f)); - } - } + value = frame_unspecified_color (f, value); } else value = Fcdr (Fassq (parameter, Fframe_parameters (frame))); @@ -2455,7 +2738,7 @@ to `frame-height'). */) return make_number (FRAME_PIXEL_HEIGHT (f)); else #endif - return make_number (FRAME_LINES (f)); + return make_number (FRAME_TOTAL_LINES (f)); } DEFUN ("frame-pixel-width", Fframe_pixel_width, @@ -2472,7 +2755,7 @@ If FRAME is omitted or nil, the selected frame is used. */) return make_number (FRAME_PIXEL_WIDTH (f)); else #endif - return make_number (FRAME_COLS (f)); + return make_number (FRAME_TOTAL_COLS (f)); } DEFUN ("tool-bar-pixel-width", Ftool_bar_pixel_width, @@ -2507,12 +2790,19 @@ DEFUN ("frame-text-lines", Fframe_text_lines, Sframe_text_lines, 0, 1, 0, } DEFUN ("frame-total-cols", Fframe_total_cols, Sframe_total_cols, 0, 1, 0, - doc: /* Return total columns of FRAME. */) + doc: /* Return number of total columns of FRAME. */) (Lisp_Object frame) { return make_number (FRAME_TOTAL_COLS (decode_any_frame (frame))); } +DEFUN ("frame-total-lines", Fframe_total_lines, Sframe_total_lines, 0, 1, 0, + doc: /* Return number of total lines of FRAME. */) + (Lisp_Object frame) +{ + return make_number (FRAME_TOTAL_LINES (decode_any_frame (frame))); +} + DEFUN ("frame-text-width", Fframe_text_width, Sframe_text_width, 0, 1, 0, doc: /* Return text area width of FRAME in pixels. */) (Lisp_Object frame) @@ -2534,6 +2824,13 @@ DEFUN ("frame-scroll-bar-width", Fscroll_bar_width, Sscroll_bar_width, 0, 1, 0, return make_number (FRAME_SCROLL_BAR_AREA_WIDTH (decode_any_frame (frame))); } +DEFUN ("frame-scroll-bar-height", Fscroll_bar_height, Sscroll_bar_height, 0, 1, 0, + doc: /* Return scroll bar height of FRAME in pixels. */) + (Lisp_Object frame) +{ + return make_number (FRAME_SCROLL_BAR_AREA_HEIGHT (decode_any_frame (frame))); +} + DEFUN ("frame-fringe-width", Ffringe_width, Sfringe_width, 0, 1, 0, doc: /* Return fringe width of FRAME in pixels. */) (Lisp_Object frame) @@ -2561,110 +2858,79 @@ DEFUN ("frame-bottom-divider-width", Fbottom_divider_width, Sbottom_divider_widt { return make_number (FRAME_BOTTOM_DIVIDER_WIDTH (decode_any_frame (frame))); } - + DEFUN ("set-frame-height", Fset_frame_height, Sset_frame_height, 2, 4, 0, - doc: /* Specify that the frame FRAME has HEIGHT text lines. + doc: /* Set text height of frame FRAME to HEIGHT lines. Optional third arg PRETEND non-nil means that redisplay should use HEIGHT lines but that the idea of the actual height of the frame should -not be changed. Optional fourth argument PIXELWISE non-nil means that -FRAME should be HEIGHT pixels high. */) +not be changed. + +Optional fourth argument PIXELWISE non-nil means that FRAME should be +HEIGHT pixels high. Note: When `frame-resize-pixelwise' is nil, some +window managers may refuse to honor a HEIGHT that is not an integer +multiple of the default frame font height. */) (Lisp_Object frame, Lisp_Object height, Lisp_Object pretend, Lisp_Object pixelwise) { - register struct frame *f = decode_live_frame (frame); + struct frame *f = decode_live_frame (frame); + int pixel_height; CHECK_TYPE_RANGED_INTEGER (int, height); - /* I think this should be done with a hook. */ -#ifdef HAVE_WINDOW_SYSTEM - if (FRAME_WINDOW_P (f)) - { - if (NILP (pixelwise)) - { - if (XINT (height) != FRAME_LINES (f)) - x_set_window_size (f, 1, FRAME_COLS (f), XINT (height), 0); + pixel_height = (!NILP (pixelwise) + ? XINT (height) + : XINT (height) * FRAME_LINE_HEIGHT (f)); + adjust_frame_size (f, -1, pixel_height, 1, !NILP (pretend), Qheight); - do_pending_window_change (0); - } - else if (XINT (height) != FRAME_TEXT_HEIGHT (f)) - { - x_set_window_size (f, 1, FRAME_TEXT_WIDTH (f), XINT (height), 1); - do_pending_window_change (0); - } - } - else -#endif - change_frame_size (f, 0, XINT (height), !NILP (pretend), 0, 0, - NILP (pixelwise) ? 0 : 1); return Qnil; } DEFUN ("set-frame-width", Fset_frame_width, Sset_frame_width, 2, 4, 0, - doc: /* Specify that the frame FRAME has WIDTH columns. + doc: /* Set text width of frame FRAME to WIDTH columns. Optional third arg PRETEND non-nil means that redisplay should use WIDTH columns but that the idea of the actual width of the frame should not -be changed. Optional fourth argument PIXELWISE non-nil means that FRAME -should be WIDTH pixels wide. */) +be changed. + +Optional fourth argument PIXELWISE non-nil means that FRAME should be +WIDTH pixels wide. Note: When `frame-resize-pixelwise' is nil, some +window managers may refuse to honor a WIDTH that is not an integer +multiple of the default frame font width. */) (Lisp_Object frame, Lisp_Object width, Lisp_Object pretend, Lisp_Object pixelwise) { - register struct frame *f = decode_live_frame (frame); + struct frame *f = decode_live_frame (frame); + int pixel_width; CHECK_TYPE_RANGED_INTEGER (int, width); - /* I think this should be done with a hook. */ -#ifdef HAVE_WINDOW_SYSTEM - if (FRAME_WINDOW_P (f)) - { - if (NILP (pixelwise)) - { - if (XINT (width) != FRAME_COLS (f)) - x_set_window_size (f, 1, XINT (width), FRAME_LINES (f), 0); + pixel_width = (!NILP (pixelwise) + ? XINT (width) + : XINT (width) * FRAME_COLUMN_WIDTH (f)); + adjust_frame_size (f, pixel_width, -1, 1, !NILP (pretend), Qwidth); - do_pending_window_change (0); - } - else if (XINT (width) != FRAME_TEXT_WIDTH (f)) - { - x_set_window_size (f, 1, XINT (width), FRAME_TEXT_HEIGHT (f), 1); - do_pending_window_change (0); - } - } - else -#endif - change_frame_size (f, XINT (width), 0, !NILP (pretend), 0, 0, - NILP (pixelwise) ? 0 : 1); return Qnil; } DEFUN ("set-frame-size", Fset_frame_size, Sset_frame_size, 3, 4, 0, - doc: /* Sets size of FRAME to WIDTH by HEIGHT, measured in characters. -Optional argument PIXELWISE non-nil means to measure in pixels. */) + doc: /* Set text size of FRAME to WIDTH by HEIGHT, measured in characters. +Optional argument PIXELWISE non-nil means to measure in pixels. Note: +When `frame-resize-pixelwise' is nil, some window managers may refuse to +honor a WIDTH that is not an integer multiple of the default frame font +width or a HEIGHT that is not an integer multiple of the default frame +font height. */) (Lisp_Object frame, Lisp_Object width, Lisp_Object height, Lisp_Object pixelwise) { - register struct frame *f = decode_live_frame (frame); + struct frame *f = decode_live_frame (frame); + int pixel_width, pixel_height; CHECK_TYPE_RANGED_INTEGER (int, width); CHECK_TYPE_RANGED_INTEGER (int, height); - /* I think this should be done with a hook. */ -#ifdef HAVE_WINDOW_SYSTEM - if (FRAME_WINDOW_P (f)) - { - if (!NILP (pixelwise) - ? (XINT (width) != FRAME_TEXT_WIDTH (f) - || XINT (height) != FRAME_TEXT_HEIGHT (f) - || f->new_height || f->new_width) - : (XINT (width) != FRAME_COLS (f) - || XINT (height) != FRAME_LINES (f) - || f->new_height || f->new_width)) - { - x_set_window_size (f, 1, XINT (width), XINT (height), - NILP (pixelwise) ? 0 : 1); - do_pending_window_change (0); - } - } - else -#endif - change_frame_size (f, XINT (width), XINT (height), 0, 0, 0, - NILP (pixelwise) ? 0 : 1); + pixel_width = (!NILP (pixelwise) + ? XINT (width) + : XINT (width) * FRAME_COLUMN_WIDTH (f)); + pixel_height = (!NILP (pixelwise) + ? XINT (height) + : XINT (height) * FRAME_LINE_HEIGHT (f)); + adjust_frame_size (f, pixel_width, pixel_height, 1, 0, Qsize); return Qnil; } @@ -2706,94 +2972,50 @@ or bottommost possible position (that stays within the screen). */) struct frame_parm_table { const char *name; - Lisp_Object *variable; + int sym; }; static const struct frame_parm_table frame_parms[] = { - {"auto-raise", &Qauto_raise}, - {"auto-lower", &Qauto_lower}, - {"background-color", 0}, - {"border-color", &Qborder_color}, - {"border-width", &Qborder_width}, - {"cursor-color", &Qcursor_color}, - {"cursor-type", &Qcursor_type}, - {"font", 0}, - {"foreground-color", 0}, - {"icon-name", &Qicon_name}, - {"icon-type", &Qicon_type}, - {"internal-border-width", &Qinternal_border_width}, - {"right-divider-width", &Qright_divider_width}, - {"bottom-divider-width", &Qbottom_divider_width}, - {"menu-bar-lines", &Qmenu_bar_lines}, - {"mouse-color", &Qmouse_color}, - {"name", &Qname}, - {"scroll-bar-width", &Qscroll_bar_width}, - {"title", &Qtitle}, - {"unsplittable", &Qunsplittable}, - {"vertical-scroll-bars", &Qvertical_scroll_bars}, - {"visibility", &Qvisibility}, - {"tool-bar-lines", &Qtool_bar_lines}, - {"scroll-bar-foreground", &Qscroll_bar_foreground}, - {"scroll-bar-background", &Qscroll_bar_background}, - {"screen-gamma", &Qscreen_gamma}, - {"line-spacing", &Qline_spacing}, - {"left-fringe", &Qleft_fringe}, - {"right-fringe", &Qright_fringe}, - {"wait-for-wm", &Qwait_for_wm}, - {"fullscreen", &Qfullscreen}, - {"font-backend", &Qfont_backend}, - {"alpha", &Qalpha}, - {"sticky", &Qsticky}, - {"tool-bar-position", &Qtool_bar_position}, + {"auto-raise", SYMBOL_INDEX (Qauto_raise)}, + {"auto-lower", SYMBOL_INDEX (Qauto_lower)}, + {"background-color", -1}, + {"border-color", SYMBOL_INDEX (Qborder_color)}, + {"border-width", SYMBOL_INDEX (Qborder_width)}, + {"cursor-color", SYMBOL_INDEX (Qcursor_color)}, + {"cursor-type", SYMBOL_INDEX (Qcursor_type)}, + {"font", -1}, + {"foreground-color", -1}, + {"icon-name", SYMBOL_INDEX (Qicon_name)}, + {"icon-type", SYMBOL_INDEX (Qicon_type)}, + {"internal-border-width", SYMBOL_INDEX (Qinternal_border_width)}, + {"right-divider-width", SYMBOL_INDEX (Qright_divider_width)}, + {"bottom-divider-width", SYMBOL_INDEX (Qbottom_divider_width)}, + {"menu-bar-lines", SYMBOL_INDEX (Qmenu_bar_lines)}, + {"mouse-color", SYMBOL_INDEX (Qmouse_color)}, + {"name", SYMBOL_INDEX (Qname)}, + {"scroll-bar-width", SYMBOL_INDEX (Qscroll_bar_width)}, + {"scroll-bar-height", SYMBOL_INDEX (Qscroll_bar_height)}, + {"title", SYMBOL_INDEX (Qtitle)}, + {"unsplittable", SYMBOL_INDEX (Qunsplittable)}, + {"vertical-scroll-bars", SYMBOL_INDEX (Qvertical_scroll_bars)}, + {"horizontal-scroll-bars", SYMBOL_INDEX (Qhorizontal_scroll_bars)}, + {"visibility", SYMBOL_INDEX (Qvisibility)}, + {"tool-bar-lines", SYMBOL_INDEX (Qtool_bar_lines)}, + {"scroll-bar-foreground", SYMBOL_INDEX (Qscroll_bar_foreground)}, + {"scroll-bar-background", SYMBOL_INDEX (Qscroll_bar_background)}, + {"screen-gamma", SYMBOL_INDEX (Qscreen_gamma)}, + {"line-spacing", SYMBOL_INDEX (Qline_spacing)}, + {"left-fringe", SYMBOL_INDEX (Qleft_fringe)}, + {"right-fringe", SYMBOL_INDEX (Qright_fringe)}, + {"wait-for-wm", SYMBOL_INDEX (Qwait_for_wm)}, + {"fullscreen", SYMBOL_INDEX (Qfullscreen)}, + {"font-backend", SYMBOL_INDEX (Qfont_backend)}, + {"alpha", SYMBOL_INDEX (Qalpha)}, + {"sticky", SYMBOL_INDEX (Qsticky)}, + {"tool-bar-position", SYMBOL_INDEX (Qtool_bar_position)}, }; -#ifdef HAVE_NTGUI - -/* 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 (struct frame *f, int *width, int *height, int *top_pos, int *left_pos) -{ - int newwidth = FRAME_COLS (f); - int newheight = FRAME_LINES (f); - Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f); - - *top_pos = f->top_pos; - *left_pos = f->left_pos; - - if (f->want_fullscreen & FULLSCREEN_HEIGHT) - { - int ph; - - ph = x_display_pixel_height (dpyinfo); - newheight = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, ph); - ph = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, newheight) - f->y_pixels_diff; - newheight = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, ph); - *top_pos = 0; - } - - if (f->want_fullscreen & FULLSCREEN_WIDTH) - { - int pw; - - pw = x_display_pixel_width (dpyinfo); - newwidth = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pw); - pw = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, newwidth) - f->x_pixels_diff; - newwidth = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pw); - *left_pos = 0; - } - - *width = newwidth; - *height = newheight; -} - -#endif /* HAVE_NTGUI */ - #ifdef HAVE_WINDOW_SYSTEM /* Change the parameters of frame F as specified by ALIST. @@ -2810,7 +3032,7 @@ x_set_frame_parameters (struct frame *f, Lisp_Object alist) /* If both of these parameters are present, it's more efficient to set them both at once. So we wait until we've looked at the entire list before we set them. */ - int width = 0, height = 0; + int width IF_LINT (= 0), height IF_LINT (= 0); bool width_change = 0, height_change = 0; /* Same here. */ @@ -2827,14 +3049,14 @@ x_set_frame_parameters (struct frame *f, Lisp_Object alist) #ifdef HAVE_X_WINDOWS bool icon_left_no_change = 0, icon_top_no_change = 0; #endif - struct gcpro gcpro1, gcpro2; i = 0; for (tail = alist; CONSP (tail); tail = XCDR (tail)) i++; - parms = alloca (i * sizeof *parms); - values = alloca (i * sizeof *values); + USE_SAFE_ALLOCA; + SAFE_ALLOCA_LISP (parms, 2 * i); + values = parms + i; /* Extract parm names and values into those vectors. */ @@ -2851,10 +3073,6 @@ x_set_frame_parameters (struct frame *f, Lisp_Object alist) /* TAIL and ALIST are not used again below here. */ alist = tail = Qnil; - GCPRO2 (*parms, *values); - gcpro1.nvars = i; - gcpro2.nvars = i; - /* There is no need to gcpro LEFT, TOP, ICON_LEFT, or ICON_TOP, because their values appear in VALUES and strings are not valid. */ top = left = Qunbound; @@ -2883,8 +3101,7 @@ x_set_frame_parameters (struct frame *f, Lisp_Object alist) param_index = Fget (prop, Qx_frame_parameter); if (NATNUMP (param_index) - && (XFASTINT (param_index) - < sizeof (frame_parms)/sizeof (frame_parms[0])) + && XFASTINT (param_index) < ARRAYELTS (frame_parms) && FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)]) (*(FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])) (f, val, old_value); } @@ -2932,8 +3149,7 @@ x_set_frame_parameters (struct frame *f, Lisp_Object alist) param_index = Fget (prop, Qx_frame_parameter); if (NATNUMP (param_index) - && (XFASTINT (param_index) - < sizeof (frame_parms)/sizeof (frame_parms[0])) + && XFASTINT (param_index) < ARRAYELTS (frame_parms) && FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)]) (*(FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])) (f, val, old_value); } @@ -2988,15 +3204,11 @@ x_set_frame_parameters (struct frame *f, Lisp_Object alist) { Lisp_Object frame; - /* Make this 1, eventually. */ - check_frame_size (f, &width, &height, 1); - XSETFRAME (frame, f); - if ((width_change || height_change) - && (width != FRAME_TEXT_WIDTH (f) - || height != FRAME_TEXT_HEIGHT (f) - || f->new_height || f->new_width)) + if ((width_change && width != FRAME_TEXT_WIDTH (f)) + || (height_change && height != FRAME_TEXT_HEIGHT (f)) + || (f->can_x_set_window_size && (f->new_height || f->new_width))) { /* If necessary provide default values for HEIGHT and WIDTH. Do that here since otherwise a size change implied by an @@ -3089,7 +3301,7 @@ x_set_frame_parameters (struct frame *f, Lisp_Object alist) #endif /* HAVE_X_WINDOWS */ } - UNGCPRO; + SAFE_FREE (); } @@ -3141,6 +3353,14 @@ x_report_frame_params (struct frame *f, Lisp_Object *alistptr) for non-toolkit scroll bar. ruler-mode.el depends on this. */ : Qnil)); + store_in_alist (alistptr, Qscroll_bar_height, + (! FRAME_HAS_HORIZONTAL_SCROLL_BARS (f) + ? make_number (0) + : FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) > 0 + ? make_number (FRAME_CONFIG_SCROLL_BAR_HEIGHT (f)) + /* nil means "use default height" + for non-toolkit scroll bar. */ + : Qnil)); /* FRAME_X_WINDOW is not guaranteed to return an integer. E.g., on MS-Windows it returns a value whose type is HANDLE, which is actually a pointer. Explicit casting avoids compiler @@ -3170,7 +3390,7 @@ x_report_frame_params (struct frame *f, Lisp_Object *alistptr) tem = make_natnum ((uintptr_t) FRAME_X_OUTPUT (f)->parent_desc); store_in_alist (alistptr, Qexplicit_name, (f->explicit_name ? Qt : Qnil)); store_in_alist (alistptr, Qparent_id, tem); - store_in_alist (alistptr, Qtool_bar_position, f->tool_bar_position); + store_in_alist (alistptr, Qtool_bar_position, FRAME_TOOL_BAR_POSITION (f)); } @@ -3244,8 +3464,7 @@ x_set_screen_gamma (struct frame *f, Lisp_Object new_value, Lisp_Object old_valu { Lisp_Object parm_index = Fget (Qbackground_color, Qx_frame_parameter); if (NATNUMP (parm_index) - && (XFASTINT (parm_index) - < sizeof (frame_parms)/sizeof (frame_parms[0])) + && XFASTINT (parm_index) < ARRAYELTS (frame_parms) && FRAME_RIF (f)->frame_parm_handlers[XFASTINT (parm_index)]) (*FRAME_RIF (f)->frame_parm_handlers[XFASTINT (parm_index)]) (f, bgcolor, Qnil); @@ -3418,58 +3637,66 @@ x_set_font_backend (struct frame *f, Lisp_Object new_value, Lisp_Object old_valu } } - void -x_set_fringe_width (struct frame *f, Lisp_Object new_value, Lisp_Object old_value) +x_set_left_fringe (struct frame *f, Lisp_Object new_value, Lisp_Object old_value) { - compute_fringe_widths (f, 1); -#ifdef HAVE_X_WINDOWS - /* Must adjust this so window managers report correct number of columns. */ - if (FRAME_X_WINDOW (f) != 0) - x_wm_set_size_hint (f, 0, 0); -#endif + int unit = FRAME_COLUMN_WIDTH (f); + int old_width = FRAME_LEFT_FRINGE_WIDTH (f); + int new_width; + + new_width = (RANGED_INTEGERP (-INT_MAX, new_value, INT_MAX) + ? eabs (XINT (new_value)) : 8); + + if (new_width != old_width) + { + FRAME_LEFT_FRINGE_WIDTH (f) = new_width; + FRAME_FRINGE_COLS (f) /* Round up. */ + = (new_width + FRAME_RIGHT_FRINGE_WIDTH (f) + unit - 1) / unit; + + if (FRAME_X_WINDOW (f) != 0) + adjust_frame_size (f, -1, -1, 3, 0, Qleft_fringe); + + SET_FRAME_GARBAGED (f); + } } + void -x_set_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval) +x_set_right_fringe (struct frame *f, Lisp_Object new_value, Lisp_Object old_value) { - CHECK_TYPE_RANGED_INTEGER (int, arg); + int unit = FRAME_COLUMN_WIDTH (f); + int old_width = FRAME_RIGHT_FRINGE_WIDTH (f); + int new_width; - if (XINT (arg) == f->border_width) - return; + new_width = (RANGED_INTEGERP (-INT_MAX, new_value, INT_MAX) + ? eabs (XINT (new_value)) : 8); - if (FRAME_X_WINDOW (f) != 0) - error ("Cannot change the border width of a frame"); + if (new_width != old_width) + { + FRAME_RIGHT_FRINGE_WIDTH (f) = new_width; + FRAME_FRINGE_COLS (f) /* Round up. */ + = (new_width + FRAME_LEFT_FRINGE_WIDTH (f) + unit - 1) / unit; - f->border_width = XINT (arg); + if (FRAME_X_WINDOW (f) != 0) + adjust_frame_size (f, -1, -1, 3, 0, Qright_fringe); + + SET_FRAME_GARBAGED (f); + } } + void -x_set_internal_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval) +x_set_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval) { - int old = FRAME_INTERNAL_BORDER_WIDTH (f); - CHECK_TYPE_RANGED_INTEGER (int, arg); - FRAME_INTERNAL_BORDER_WIDTH (f) = XINT (arg); - if (FRAME_INTERNAL_BORDER_WIDTH (f) < 0) - FRAME_INTERNAL_BORDER_WIDTH (f) = 0; - -#ifdef USE_X_TOOLKIT - if (FRAME_X_OUTPUT (f)->edit_widget) - widget_store_internal_border (FRAME_X_OUTPUT (f)->edit_widget); -#endif - if (FRAME_INTERNAL_BORDER_WIDTH (f) == old) + if (XINT (arg) == f->border_width) return; if (FRAME_X_WINDOW (f) != 0) - { - x_set_window_size (f, 0, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 1); - SET_FRAME_GARBAGED (f); - do_pending_window_change (0); - } - else - SET_FRAME_GARBAGED (f); + error ("Cannot change the border width of a frame"); + + f->border_width = XINT (arg); } void @@ -3481,18 +3708,13 @@ x_set_right_divider_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval) FRAME_RIGHT_DIVIDER_WIDTH (f) = XINT (arg); if (FRAME_RIGHT_DIVIDER_WIDTH (f) < 0) FRAME_RIGHT_DIVIDER_WIDTH (f) = 0; - - if (FRAME_RIGHT_DIVIDER_WIDTH (f) == old) - return; - - if (FRAME_X_WINDOW (f) != 0) + if (FRAME_RIGHT_DIVIDER_WIDTH (f) != old) { - x_set_window_size (f, 0, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 1); + adjust_frame_size (f, -1, -1, 4, 0, Qright_divider_width); + adjust_frame_glyphs (f); SET_FRAME_GARBAGED (f); - do_pending_window_change (0); } - else - SET_FRAME_GARBAGED (f); + } void @@ -3504,18 +3726,12 @@ x_set_bottom_divider_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval FRAME_BOTTOM_DIVIDER_WIDTH (f) = XINT (arg); if (FRAME_BOTTOM_DIVIDER_WIDTH (f) < 0) FRAME_BOTTOM_DIVIDER_WIDTH (f) = 0; - - if (FRAME_BOTTOM_DIVIDER_WIDTH (f) == old) - return; - - if (FRAME_X_WINDOW (f) != 0) + if (FRAME_BOTTOM_DIVIDER_WIDTH (f) != old) { - x_set_window_size (f, 0, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 1); + adjust_frame_size (f, -1, -1, 4, 0, Qbottom_divider_width); + adjust_frame_glyphs (f); SET_FRAME_GARBAGED (f); - do_pending_window_change (0); } - else - SET_FRAME_GARBAGED (f); } void @@ -3556,7 +3772,7 @@ x_set_vertical_scroll_bars (struct frame *f, Lisp_Object arg, Lisp_Object oldval if ((EQ (arg, Qleft) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f)) || (EQ (arg, Qright) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f)) || (NILP (arg) && FRAME_HAS_VERTICAL_SCROLL_BARS (f)) - || (!NILP (arg) && ! FRAME_HAS_VERTICAL_SCROLL_BARS (f))) + || (!NILP (arg) && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))) { FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = (NILP (arg) @@ -3576,13 +3792,34 @@ x_set_vertical_scroll_bars (struct frame *f, Lisp_Object arg, Lisp_Object oldval However, if the window hasn't been created yet, we shouldn't call x_set_window_size. */ if (FRAME_X_WINDOW (f)) - x_set_window_size (f, 0, FRAME_TEXT_WIDTH (f), - FRAME_TEXT_HEIGHT (f), 1); - do_pending_window_change (0); + adjust_frame_size (f, -1, -1, 3, 0, Qvertical_scroll_bars); + + SET_FRAME_GARBAGED (f); } } void +x_set_horizontal_scroll_bars (struct frame *f, Lisp_Object arg, Lisp_Object oldval) +{ +#if USE_HORIZONTAL_SCROLL_BARS + if ((NILP (arg) && FRAME_HAS_HORIZONTAL_SCROLL_BARS (f)) + || (!NILP (arg) && !FRAME_HAS_HORIZONTAL_SCROLL_BARS (f))) + { + f->horizontal_scroll_bars = NILP (arg) ? false : true; + + /* We set this parameter before creating the X window for the + frame, so we can get the geometry right from the start. + However, if the window hasn't been created yet, we shouldn't + call x_set_window_size. */ + if (FRAME_X_WINDOW (f)) + adjust_frame_size (f, -1, -1, 3, 0, Qhorizontal_scroll_bars); + + SET_FRAME_GARBAGED (f); + } +#endif +} + +void x_set_scroll_bar_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval) { int unit = FRAME_COLUMN_WIDTH (f); @@ -3592,9 +3829,9 @@ x_set_scroll_bar_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval) x_set_scroll_bar_default_width (f); if (FRAME_X_WINDOW (f)) - x_set_window_size (f, 0, FRAME_TEXT_WIDTH (f), - FRAME_TEXT_HEIGHT (f), 1); - do_pending_window_change (0); + adjust_frame_size (f, -1, -1, 3, 0, Qscroll_bar_width); + + SET_FRAME_GARBAGED (f); } else if (RANGED_INTEGERP (1, arg, INT_MAX) && XFASTINT (arg) != FRAME_CONFIG_SCROLL_BAR_WIDTH (f)) @@ -3602,19 +3839,47 @@ x_set_scroll_bar_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval) FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = XFASTINT (arg); FRAME_CONFIG_SCROLL_BAR_COLS (f) = (XFASTINT (arg) + unit - 1) / unit; if (FRAME_X_WINDOW (f)) - x_set_window_size (f, 0, FRAME_TEXT_WIDTH (f), - FRAME_TEXT_HEIGHT (f), 1); - do_pending_window_change (0); + adjust_frame_size (f, -1, -1, 3, 0, Qscroll_bar_width); + + SET_FRAME_GARBAGED (f); } - /* Eventually remove the following call. It should have been done by - x_set_window_size already. */ - change_frame_size (f, 0, 0, 0, 0, 0, 1); XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.hpos = 0; XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.x = 0; } void +x_set_scroll_bar_height (struct frame *f, Lisp_Object arg, Lisp_Object oldval) +{ +#if USE_HORIZONTAL_SCROLL_BARS + int unit = FRAME_LINE_HEIGHT (f); + + if (NILP (arg)) + { + x_set_scroll_bar_default_height (f); + + if (FRAME_X_WINDOW (f)) + adjust_frame_size (f, -1, -1, 3, 0, Qscroll_bar_height); + + SET_FRAME_GARBAGED (f); + } + else if (RANGED_INTEGERP (1, arg, INT_MAX) + && XFASTINT (arg) != FRAME_CONFIG_SCROLL_BAR_HEIGHT (f)) + { + FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = XFASTINT (arg); + FRAME_CONFIG_SCROLL_BAR_LINES (f) = (XFASTINT (arg) + unit - 1) / unit; + if (FRAME_X_WINDOW (f)) + adjust_frame_size (f, -1, -1, 3, 0, Qscroll_bar_height); + + SET_FRAME_GARBAGED (f); + } + + XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.vpos = 0; + XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.y = 0; +#endif +} + +void x_set_alpha (struct frame *f, Lisp_Object arg, Lisp_Object oldval) { double alpha = 1.0; @@ -3769,10 +4034,6 @@ validate_x_resource_name (void) static Lisp_Object xrdb_get_resource (XrmDatabase rdb, Lisp_Object attribute, Lisp_Object class, Lisp_Object component, Lisp_Object subclass) { - register char *value; - char *name_key; - char *class_key; - CHECK_STRING (attribute); CHECK_STRING (class); @@ -3787,39 +4048,43 @@ xrdb_get_resource (XrmDatabase rdb, Lisp_Object attribute, Lisp_Object class, Li /* Allocate space for the components, the dots which separate them, and the final '\0'. Make them big enough for the worst case. */ - name_key = alloca (SBYTES (Vx_resource_name) - + (STRINGP (component) - ? SBYTES (component) : 0) - + SBYTES (attribute) - + 3); - - class_key = alloca (SBYTES (Vx_resource_class) - + SBYTES (class) - + (STRINGP (subclass) - ? SBYTES (subclass) : 0) - + 3); + ptrdiff_t name_keysize = (SBYTES (Vx_resource_name) + + (STRINGP (component) + ? SBYTES (component) : 0) + + SBYTES (attribute) + + 3); + + ptrdiff_t class_keysize = (SBYTES (Vx_resource_class) + + SBYTES (class) + + (STRINGP (subclass) + ? SBYTES (subclass) : 0) + + 3); + USE_SAFE_ALLOCA; + char *name_key = SAFE_ALLOCA (name_keysize + class_keysize); + char *class_key = name_key + name_keysize; /* Start with emacs.FRAMENAME for the name (the specific one) and with `Emacs' for the class key (the general one). */ - strcpy (name_key, SSDATA (Vx_resource_name)); - strcpy (class_key, SSDATA (Vx_resource_class)); + char *nz = lispstpcpy (name_key, Vx_resource_name); + char *cz = lispstpcpy (class_key, Vx_resource_class); - strcat (class_key, "."); - strcat (class_key, SSDATA (class)); + *cz++ = '.'; + cz = lispstpcpy (cz, class); if (!NILP (component)) { - strcat (class_key, "."); - strcat (class_key, SSDATA (subclass)); + *cz++ = '.'; + lispstpcpy (cz, subclass); - strcat (name_key, "."); - strcat (name_key, SSDATA (component)); + *nz++ = '.'; + nz = lispstpcpy (nz, component); } - strcat (name_key, "."); - strcat (name_key, SSDATA (attribute)); + *nz++ = '.'; + lispstpcpy (nz, attribute); - value = x_get_string_resource (rdb, name_key, class_key); + char *value = x_get_string_resource (rdb, name_key, class_key); + SAFE_FREE(); if (value && *value) return build_string (value); @@ -3871,8 +4136,10 @@ x_get_resource_string (const char *attribute, const char *class) /* Allocate space for the components, the dots which separate them, and the final '\0'. */ - char *name_key = SAFE_ALLOCA (invocation_namelen + strlen (attribute) + 2); - char *class_key = alloca ((sizeof (EMACS_CLASS) - 1) + strlen (class) + 2); + ptrdiff_t name_keysize = invocation_namelen + strlen (attribute) + 2; + ptrdiff_t class_keysize = sizeof (EMACS_CLASS) - 1 + strlen (class) + 2; + char *name_key = SAFE_ALLOCA (name_keysize + class_keysize); + char *class_key = name_key + name_keysize; esprintf (name_key, "%s.%s", SSDATA (Vinvocation_name), attribute); sprintf (class_key, "%s.%s", EMACS_CLASS, class); @@ -3899,7 +4166,7 @@ Lisp_Object x_get_arg (Display_Info *dpyinfo, Lisp_Object alist, Lisp_Object param, const char *attribute, const char *class, enum resource_types type) { - register Lisp_Object tem; + Lisp_Object tem; tem = Fassq (param, alist); @@ -3925,10 +4192,9 @@ x_get_arg (Display_Info *dpyinfo, Lisp_Object alist, Lisp_Object param, { if (attribute && dpyinfo) { - tem = display_x_get_resource (dpyinfo, - build_string (attribute), - build_string (class), - Qnil, Qnil); + AUTO_STRING (at, attribute); + AUTO_STRING (cl, class); + tem = display_x_get_resource (dpyinfo, at, cl, Qnil, Qnil); if (NILP (tem)) return Qunbound; @@ -4038,7 +4304,8 @@ x_default_parameter (struct frame *f, Lisp_Object alist, Lisp_Object prop, tem = x_frame_get_arg (f, alist, prop, xprop, xclass, type); if (EQ (tem, Qunbound)) tem = deflt; - x_set_frame_parameters (f, list1 (Fcons (prop, tem))); + AUTO_FRAME_ARG (arg, prop, tem); + x_set_frame_parameters (f, arg); return tem; } @@ -4215,7 +4482,7 @@ On Nextstep, this just calls `ns-parse-geometry'. */) long x_figure_window_size (struct frame *f, Lisp_Object parms, bool toolbar_p) { - register Lisp_Object tem0, tem1, tem2; + Lisp_Object height, width, user_size, top, left, user_position; long window_prompting = 0; Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f); @@ -4225,143 +4492,138 @@ x_figure_window_size (struct frame *f, Lisp_Object parms, bool toolbar_p) SET_FRAME_WIDTH (f, DEFAULT_COLS * FRAME_COLUMN_WIDTH (f)); SET_FRAME_COLS (f, DEFAULT_COLS); SET_FRAME_HEIGHT (f, DEFAULT_ROWS * FRAME_LINE_HEIGHT (f)); - FRAME_LINES (f) = DEFAULT_ROWS; + SET_FRAME_LINES (f, DEFAULT_ROWS); /* Window managers expect that if program-specified positions are not (0,0), they're intentional, not defaults. */ f->top_pos = 0; f->left_pos = 0; - /* Ensure that old new_width and new_height will not override the - values set here. */ - /* ++KFS: This was specific to W32, but seems ok for all platforms */ - f->new_width = f->new_height = f->new_pixelwise = 0; + /* Ensure that earlier new_width and new_height settings won't + override what we specify below. */ + f->new_width = f->new_height = 0; - tem0 = x_get_arg (dpyinfo, parms, Qheight, 0, 0, RES_TYPE_NUMBER); - tem1 = x_get_arg (dpyinfo, parms, Qwidth, 0, 0, RES_TYPE_NUMBER); - tem2 = x_get_arg (dpyinfo, parms, Quser_size, 0, 0, RES_TYPE_NUMBER); - if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound)) + height = x_get_arg (dpyinfo, parms, Qheight, 0, 0, RES_TYPE_NUMBER); + width = x_get_arg (dpyinfo, parms, Qwidth, 0, 0, RES_TYPE_NUMBER); + if (!EQ (width, Qunbound) || !EQ (height, Qunbound)) { - if (!EQ (tem0, Qunbound)) + if (!EQ (width, Qunbound)) { - CHECK_NUMBER (tem0); - if (! (0 <= XINT (tem0) && XINT (tem0) <= INT_MAX)) - xsignal1 (Qargs_out_of_range, tem0); - FRAME_LINES (f) = XINT (tem0); + CHECK_NUMBER (width); + if (! (0 <= XINT (width) && XINT (width) <= INT_MAX)) + xsignal1 (Qargs_out_of_range, width); + + SET_FRAME_WIDTH (f, XINT (width) * FRAME_COLUMN_WIDTH (f)); } - if (!EQ (tem1, Qunbound)) + + if (!EQ (height, Qunbound)) { - CHECK_NUMBER (tem1); - if (! (0 <= XINT (tem1) && XINT (tem1) <= INT_MAX)) - xsignal1 (Qargs_out_of_range, tem1); - SET_FRAME_COLS (f, XINT (tem1)); + CHECK_NUMBER (height); + if (! (0 <= XINT (height) && XINT (height) <= INT_MAX)) + xsignal1 (Qargs_out_of_range, height); + + SET_FRAME_HEIGHT (f, XINT (height) * FRAME_LINE_HEIGHT (f)); } - if (!NILP (tem2) && !EQ (tem2, Qunbound)) + + user_size = x_get_arg (dpyinfo, parms, Quser_size, 0, 0, RES_TYPE_NUMBER); + if (!NILP (user_size) && !EQ (user_size, Qunbound)) window_prompting |= USSize; else window_prompting |= PSize; } - - /* This used to be done _before_ calling x_figure_window_size, but - since the height is reset here, this was really a no-op. I - assume that moving it here does what Gerd intended (although he - no longer can remember what that was... ++KFS, 2003-03-25. */ - - /* Add the tool-bar height to the initial frame height so that the - user gets a text display area of the size he specified with -g or - via .Xdefaults. Later changes of the tool-bar height don't - change the frame size. This is done so that users can create - tall Emacs frames without having to guess how tall the tool-bar - will get. */ - if (toolbar_p && FRAME_TOOL_BAR_HEIGHT (f)) + /* Add a tool bar height to the initial frame height so that the user + gets a text display area of the size he specified with -g or via + .Xdefaults. Later changes of the tool bar height don't change the + frame size. This is done so that users can create tall Emacs + frames without having to guess how tall the tool bar will get. */ + if (toolbar_p && FRAME_TOOL_BAR_LINES (f)) { - int margin, relief, bar_height; - - relief = (tool_bar_button_relief >= 0 - ? tool_bar_button_relief - : DEFAULT_TOOL_BAR_BUTTON_RELIEF); - - if (RANGED_INTEGERP (1, Vtool_bar_button_margin, INT_MAX)) - margin = XFASTINT (Vtool_bar_button_margin); - else if (CONSP (Vtool_bar_button_margin) - && RANGED_INTEGERP (1, XCDR (Vtool_bar_button_margin), INT_MAX)) - margin = XFASTINT (XCDR (Vtool_bar_button_margin)); + if (frame_default_tool_bar_height) + FRAME_TOOL_BAR_HEIGHT (f) = frame_default_tool_bar_height; else - margin = 0; + { + int margin, relief; - /* PXW: We should be able to not round here. */ - bar_height = DEFAULT_TOOL_BAR_IMAGE_HEIGHT + 2 * margin + 2 * relief; - FRAME_LINES (f) += (bar_height + FRAME_LINE_HEIGHT (f) - 1) / FRAME_LINE_HEIGHT (f); - } + relief = (tool_bar_button_relief >= 0 + ? tool_bar_button_relief + : DEFAULT_TOOL_BAR_BUTTON_RELIEF); - compute_fringe_widths (f, 0); + if (RANGED_INTEGERP (1, Vtool_bar_button_margin, INT_MAX)) + margin = XFASTINT (Vtool_bar_button_margin); + else if (CONSP (Vtool_bar_button_margin) + && RANGED_INTEGERP (1, XCDR (Vtool_bar_button_margin), INT_MAX)) + margin = XFASTINT (XCDR (Vtool_bar_button_margin)); + else + margin = 0; - SET_FRAME_WIDTH (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f)); - SET_FRAME_HEIGHT(f, FRAME_LINES (f) * FRAME_LINE_HEIGHT (f)); + FRAME_TOOL_BAR_HEIGHT (f) + = DEFAULT_TOOL_BAR_IMAGE_HEIGHT + 2 * margin + 2 * relief; + } + } - tem0 = x_get_arg (dpyinfo, parms, Qtop, 0, 0, RES_TYPE_NUMBER); - tem1 = x_get_arg (dpyinfo, parms, Qleft, 0, 0, RES_TYPE_NUMBER); - tem2 = x_get_arg (dpyinfo, parms, Quser_position, 0, 0, RES_TYPE_NUMBER); - if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound)) + top = x_get_arg (dpyinfo, parms, Qtop, 0, 0, RES_TYPE_NUMBER); + left = x_get_arg (dpyinfo, parms, Qleft, 0, 0, RES_TYPE_NUMBER); + user_position = x_get_arg (dpyinfo, parms, Quser_position, 0, 0, RES_TYPE_NUMBER); + if (! EQ (top, Qunbound) || ! EQ (left, Qunbound)) { - if (EQ (tem0, Qminus)) + if (EQ (top, Qminus)) { f->top_pos = 0; window_prompting |= YNegative; } - else if (CONSP (tem0) && EQ (XCAR (tem0), Qminus) - && CONSP (XCDR (tem0)) - && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (tem0)), INT_MAX)) + else if (CONSP (top) && EQ (XCAR (top), Qminus) + && CONSP (XCDR (top)) + && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (top)), INT_MAX)) { - f->top_pos = - XINT (XCAR (XCDR (tem0))); + f->top_pos = - XINT (XCAR (XCDR (top))); window_prompting |= YNegative; } - else if (CONSP (tem0) && EQ (XCAR (tem0), Qplus) - && CONSP (XCDR (tem0)) - && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (tem0)))) + else if (CONSP (top) && EQ (XCAR (top), Qplus) + && CONSP (XCDR (top)) + && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (top)))) { - f->top_pos = XINT (XCAR (XCDR (tem0))); + f->top_pos = XINT (XCAR (XCDR (top))); } - else if (EQ (tem0, Qunbound)) + else if (EQ (top, Qunbound)) f->top_pos = 0; else { - CHECK_TYPE_RANGED_INTEGER (int, tem0); - f->top_pos = XINT (tem0); + CHECK_TYPE_RANGED_INTEGER (int, top); + f->top_pos = XINT (top); if (f->top_pos < 0) window_prompting |= YNegative; } - if (EQ (tem1, Qminus)) + if (EQ (left, Qminus)) { f->left_pos = 0; window_prompting |= XNegative; } - else if (CONSP (tem1) && EQ (XCAR (tem1), Qminus) - && CONSP (XCDR (tem1)) - && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (tem1)), INT_MAX)) + else if (CONSP (left) && EQ (XCAR (left), Qminus) + && CONSP (XCDR (left)) + && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (left)), INT_MAX)) { - f->left_pos = - XINT (XCAR (XCDR (tem1))); + f->left_pos = - XINT (XCAR (XCDR (left))); window_prompting |= XNegative; } - else if (CONSP (tem1) && EQ (XCAR (tem1), Qplus) - && CONSP (XCDR (tem1)) - && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (tem1)))) + else if (CONSP (left) && EQ (XCAR (left), Qplus) + && CONSP (XCDR (left)) + && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (left)))) { - f->left_pos = XINT (XCAR (XCDR (tem1))); + f->left_pos = XINT (XCAR (XCDR (left))); } - else if (EQ (tem1, Qunbound)) + else if (EQ (left, Qunbound)) f->left_pos = 0; else { - CHECK_TYPE_RANGED_INTEGER (int, tem1); - f->left_pos = XINT (tem1); + CHECK_TYPE_RANGED_INTEGER (int, left); + f->left_pos = XINT (left); if (f->left_pos < 0) window_prompting |= XNegative; } - if (!NILP (tem2) && ! EQ (tem2, Qunbound)) + if (!NILP (user_position) && ! EQ (user_position, Qunbound)) window_prompting |= USPosition; else window_prompting |= PPosition; @@ -4392,16 +4654,11 @@ x_figure_window_size (struct frame *f, Lisp_Object parms, bool toolbar_p) #endif /* HAVE_WINDOW_SYSTEM */ void -frame_make_pointer_invisible (void) +frame_make_pointer_invisible (struct frame *f) { if (! NILP (Vmake_pointer_invisible)) { - struct frame *f; - if (!FRAMEP (selected_frame) || !FRAME_LIVE_P (XFRAME (selected_frame))) - return; - - f = SELECTED_FRAME (); - if (f && !f->pointer_invisible + if (f && FRAME_LIVE_P (f) && !f->pointer_invisible && FRAME_TERMINAL (f)->toggle_invisible_pointer_hook) { f->mouse_moved = 0; @@ -4412,17 +4669,11 @@ frame_make_pointer_invisible (void) } void -frame_make_pointer_visible (void) +frame_make_pointer_visible (struct frame *f) { /* We don't check Vmake_pointer_invisible here in case the pointer was invisible when Vmake_pointer_invisible was set to nil. */ - struct frame *f; - - if (!FRAMEP (selected_frame) || !FRAME_LIVE_P (XFRAME (selected_frame))) - return; - - f = SELECTED_FRAME (); - if (f && f->pointer_invisible && f->mouse_moved + if (f && FRAME_LIVE_P (f) && f->pointer_invisible && f->mouse_moved && FRAME_TERMINAL (f)->toggle_invisible_pointer_hook) { FRAME_TERMINAL (f)->toggle_invisible_pointer_hook (f, 0); @@ -4519,6 +4770,7 @@ syms_of_frame (void) { DEFSYM (Qframep, "framep"); DEFSYM (Qframe_live_p, "frame-live-p"); + DEFSYM (Qframe_windows_min_size, "frame-windows-min-size"); DEFSYM (Qexplicit_name, "explicit-name"); DEFSYM (Qheight, "height"); DEFSYM (Qicon, "icon"); @@ -4531,8 +4783,6 @@ syms_of_frame (void) DEFSYM (Qicon_left, "icon-left"); DEFSYM (Qicon_top, "icon-top"); DEFSYM (Qtooltip, "tooltip"); - DEFSYM (Qleft, "left"); - DEFSYM (Qright, "right"); DEFSYM (Quser_position, "user-position"); DEFSYM (Quser_size, "user-size"); DEFSYM (Qwindow_id, "window-id"); @@ -4566,27 +4816,73 @@ syms_of_frame (void) DEFSYM (Qterminal, "terminal"); - DEFSYM (Qgeometry, "geometry"); DEFSYM (Qworkarea, "workarea"); DEFSYM (Qmm_size, "mm-size"); DEFSYM (Qframes, "frames"); DEFSYM (Qsource, "source"); + DEFSYM (Qframe_position, "frame-position"); + DEFSYM (Qframe_outer_size, "frame-outer-size"); + DEFSYM (Qexternal_border_size, "external-border-size"); + DEFSYM (Qtitle_height, "title-height"); + DEFSYM (Qmenu_bar_external, "menu-bar-external"); + DEFSYM (Qmenu_bar_size, "menu-bar-size"); + DEFSYM (Qtool_bar_external, "tool-bar-external"); + DEFSYM (Qtool_bar_size, "tool-bar-size"); + DEFSYM (Qframe_inner_size, "frame-inner-size"); + DEFSYM (Qchange_frame_size, "change-frame-size"); + DEFSYM (Qxg_frame_set_char_size, "xg-frame-set-char-size"); + DEFSYM (Qset_window_configuration, "set-window-configuration"); + DEFSYM (Qx_create_frame_1, "x-create-frame-1"); + DEFSYM (Qx_create_frame_2, "x-create-frame-2"); + #ifdef HAVE_NS DEFSYM (Qns_parse_geometry, "ns-parse-geometry"); #endif + DEFSYM (Qalpha, "alpha"); + DEFSYM (Qauto_lower, "auto-lower"); + DEFSYM (Qauto_raise, "auto-raise"); + DEFSYM (Qborder_color, "border-color"); + DEFSYM (Qborder_width, "border-width"); + DEFSYM (Qbottom_divider_width, "bottom-divider-width"); + DEFSYM (Qcursor_color, "cursor-color"); + DEFSYM (Qcursor_type, "cursor-type"); + DEFSYM (Qfont_backend, "font-backend"); + DEFSYM (Qfullscreen, "fullscreen"); + DEFSYM (Qhorizontal_scroll_bars, "horizontal-scroll-bars"); + DEFSYM (Qicon_name, "icon-name"); + DEFSYM (Qicon_type, "icon-type"); + DEFSYM (Qinternal_border_width, "internal-border-width"); + DEFSYM (Qleft_fringe, "left-fringe"); + DEFSYM (Qline_spacing, "line-spacing"); + DEFSYM (Qmenu_bar_lines, "menu-bar-lines"); + DEFSYM (Qmouse_color, "mouse-color"); + DEFSYM (Qname, "name"); + DEFSYM (Qright_divider_width, "right-divider-width"); + DEFSYM (Qright_fringe, "right-fringe"); + DEFSYM (Qscreen_gamma, "screen-gamma"); + DEFSYM (Qscroll_bar_background, "scroll-bar-background"); + DEFSYM (Qscroll_bar_foreground, "scroll-bar-foreground"); + DEFSYM (Qscroll_bar_height, "scroll-bar-height"); + DEFSYM (Qscroll_bar_width, "scroll-bar-width"); + DEFSYM (Qsticky, "sticky"); + DEFSYM (Qtitle, "title"); + DEFSYM (Qtool_bar_lines, "tool-bar-lines"); + DEFSYM (Qtool_bar_position, "tool-bar-position"); + DEFSYM (Qunsplittable, "unsplittable"); + DEFSYM (Qvertical_scroll_bars, "vertical-scroll-bars"); + DEFSYM (Qvisibility, "visibility"); + DEFSYM (Qwait_for_wm, "wait-for-wm"); + { int i; - for (i = 0; i < sizeof (frame_parms) / sizeof (frame_parms[0]); i++) + for (i = 0; i < ARRAYELTS (frame_parms); i++) { - Lisp_Object v = intern_c_string (frame_parms[i].name); - if (frame_parms[i].variable) - { - *frame_parms[i].variable = v; - staticpro (frame_parms[i].variable); - } + Lisp_Object v = (frame_parms[i].sym < 0 + ? intern_c_string (frame_parms[i].name) + : builtin_lisp_symbol (frame_parms[i].sym)); Fput (v, Qx_frame_parameter, make_number (i)); } } @@ -4639,7 +4935,7 @@ Setting this variable does not affect existing frames, only new ones. */); Vdefault_frame_alist = Qnil; DEFVAR_LISP ("default-frame-scroll-bars", Vdefault_frame_scroll_bars, - doc: /* Default position of scroll bars on this window-system. */); + doc: /* Default position of vertical scroll bars on this window-system. */); #ifdef HAVE_WINDOW_SYSTEM #if defined (HAVE_NTGUI) || defined (NS_IMPL_COCOA) || (defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS)) /* MS-Windows, Mac OS X, and GTK have scroll bars on the right by @@ -4756,16 +5052,66 @@ current values of `frame-char-height' and `frame-char-width'. If this is non-nil, no rounding occurs, hence frame sizes can increase/decrease by one pixel. -With some window managers you have to set this to non-nil in order to -fully maximize frames. To resize your initial frame pixelwise, -set this option to a non-nil value in your init file. */); +With some window managers you may have to set this to non-nil in order +to set the size of a frame in pixels, to maximize frames or to make them +fullscreen. To resize your initial frame pixelwise, set this option to +a non-nil value in your init file. */); frame_resize_pixelwise = 0; + DEFVAR_LISP ("frame-inhibit-implied-resize", frame_inhibit_implied_resize, + doc: /* Whether frames should be resized implicitly. +If this option is nil, setting font, menu bar, tool bar, internal +borders, fringes or scroll bars of a specific frame may resize the frame +in order to preserve the number of columns or lines it displays. If +this option is `t', no such resizing is done. Note that the size of +fullscreen and maximized frames, the height of fullheight frames and the +width of fullwidth frames never change implicitly. + +The value of this option can be also be a list of frame parameters. In +this case, resizing is inhibited when changing a parameter that appears +in that list. The parameters currently handled by this option include +`font', `font-backend', `internal-border-width', `menu-bar-lines' and +`tool-bar-lines'. + +Changing any of the parameters `scroll-bar-width', `scroll-bar-height', +`vertical-scroll-bars', `horizontal-scroll-bars', `left-fringe' and +`right-fringe' is handled as if the frame contained just one live +window. This means, for example, that removing vertical scroll bars on +a frame containing several side by side windows will shrink the frame +width by the width of one scroll bar provided this option is nil and +keep it unchanged if this option is either `t' or a list containing +`vertical-scroll-bars'. + +The default value is '(tool-bar-lines) on Lucid, Motif and Windows +\(which means that adding/removing a tool bar does not change the frame +height), nil on all other window systems including GTK+ (which means +that changing any of the parameters listed above may change the size of +the frame), and `t' otherwise (which means the frame size never changes +implicitly when there's no window system support). + +Note that when a frame is not large enough to accommodate a change of +any of the parameters listed above, Emacs may try to enlarge the frame +even if this option is non-nil. */); +#if defined (HAVE_WINDOW_SYSTEM) +#if defined (USE_LUCID) || defined (USE_MOTIF) || defined (HAVE_NTGUI) + frame_inhibit_implied_resize = list1 (Qtool_bar_lines); +#else + frame_inhibit_implied_resize = Qnil; +#endif +#else + frame_inhibit_implied_resize = Qt; +#endif + + DEFVAR_LISP ("frame-adjust-size-history", Vframe_adjust_size_history, + doc: /* History of frame size adjustments. */); + Vframe_adjust_size_history = Qnil; + staticpro (&Vframe_list); defsubr (&Sframep); defsubr (&Sframe_live_p); defsubr (&Swindow_system); + defsubr (&Sframe_windows_min_size); defsubr (&Smake_terminal_frame); defsubr (&Shandle_switch_frame); defsubr (&Sselect_frame); @@ -4791,6 +5137,7 @@ set this option to a non-nil value in your init file. */); defsubr (&Sraise_frame); defsubr (&Slower_frame); defsubr (&Sx_focus_frame); + defsubr (&Scan_run_window_configuration_change_hook); defsubr (&Sredirect_frame_focus); defsubr (&Sframe_focus); defsubr (&Sframe_parameters); @@ -4803,9 +5150,11 @@ set this option to a non-nil value in your init file. */); defsubr (&Sframe_text_cols); defsubr (&Sframe_text_lines); defsubr (&Sframe_total_cols); + defsubr (&Sframe_total_lines); defsubr (&Sframe_text_width); defsubr (&Sframe_text_height); defsubr (&Sscroll_bar_width); + defsubr (&Sscroll_bar_height); defsubr (&Sfringe_width); defsubr (&Sborder_width); defsubr (&Sright_divider_width); |