Mercurial > hg > xemacs-beta
annotate src/window.c @ 5127:a9c41067dd88 ben-lisp-object
more cleanups, terminology clarification, lots of doc work
-------------------- ChangeLog entries follow: --------------------
man/ChangeLog addition:
2010-03-05 Ben Wing <ben@xemacs.org>
* internals/internals.texi (Introduction to Allocation):
* internals/internals.texi (Integers and Characters):
* internals/internals.texi (Allocation from Frob Blocks):
* internals/internals.texi (lrecords):
* internals/internals.texi (Low-level allocation):
Rewrite section on allocation of Lisp objects to reflect the new
reality. Remove references to nonexistent XSETINT and XSETCHAR.
modules/ChangeLog addition:
2010-03-05 Ben Wing <ben@xemacs.org>
* postgresql/postgresql.c (allocate_pgconn):
* postgresql/postgresql.c (allocate_pgresult):
* postgresql/postgresql.h (struct Lisp_PGconn):
* postgresql/postgresql.h (struct Lisp_PGresult):
* ldap/eldap.c (allocate_ldap):
* ldap/eldap.h (struct Lisp_LDAP):
Same changes as in src/ dir. See large log there in ChangeLog,
but basically:
ALLOC_LISP_OBJECT -> ALLOC_NORMAL_LISP_OBJECT
LISP_OBJECT_HEADER -> NORMAL_LISP_OBJECT_HEADER
../hlo/src/ChangeLog addition:
2010-03-05 Ben Wing <ben@xemacs.org>
* alloc.c:
* alloc.c (old_alloc_sized_lcrecord):
* alloc.c (very_old_free_lcrecord):
* alloc.c (copy_lisp_object):
* alloc.c (zero_sized_lisp_object):
* alloc.c (zero_nonsized_lisp_object):
* alloc.c (lisp_object_storage_size):
* alloc.c (free_normal_lisp_object):
* alloc.c (FREE_FIXED_TYPE_WHEN_NOT_IN_GC):
* alloc.c (ALLOC_FROB_BLOCK_LISP_OBJECT):
* alloc.c (Fcons):
* alloc.c (noseeum_cons):
* alloc.c (make_float):
* alloc.c (make_bignum):
* alloc.c (make_bignum_bg):
* alloc.c (make_ratio):
* alloc.c (make_ratio_bg):
* alloc.c (make_ratio_rt):
* alloc.c (make_bigfloat):
* alloc.c (make_bigfloat_bf):
* alloc.c (size_vector):
* alloc.c (make_compiled_function):
* alloc.c (Fmake_symbol):
* alloc.c (allocate_extent):
* alloc.c (allocate_event):
* alloc.c (make_key_data):
* alloc.c (make_button_data):
* alloc.c (make_motion_data):
* alloc.c (make_process_data):
* alloc.c (make_timeout_data):
* alloc.c (make_magic_data):
* alloc.c (make_magic_eval_data):
* alloc.c (make_eval_data):
* alloc.c (make_misc_user_data):
* alloc.c (Fmake_marker):
* alloc.c (noseeum_make_marker):
* alloc.c (size_string_direct_data):
* alloc.c (make_uninit_string):
* alloc.c (make_string_nocopy):
* alloc.c (mark_lcrecord_list):
* alloc.c (alloc_managed_lcrecord):
* alloc.c (free_managed_lcrecord):
* alloc.c (sweep_lcrecords_1):
* alloc.c (malloced_storage_size):
* buffer.c (allocate_buffer):
* buffer.c (compute_buffer_usage):
* buffer.c (DEFVAR_BUFFER_LOCAL_1):
* buffer.c (nuke_all_buffer_slots):
* buffer.c (common_init_complex_vars_of_buffer):
* buffer.h (struct buffer_text):
* buffer.h (struct buffer):
* bytecode.c:
* bytecode.c (make_compiled_function_args):
* bytecode.c (size_compiled_function_args):
* bytecode.h (struct compiled_function_args):
* casetab.c (allocate_case_table):
* casetab.h (struct Lisp_Case_Table):
* charset.h (struct Lisp_Charset):
* chartab.c (fill_char_table):
* chartab.c (Fmake_char_table):
* chartab.c (make_char_table_entry):
* chartab.c (copy_char_table_entry):
* chartab.c (Fcopy_char_table):
* chartab.c (put_char_table):
* chartab.h (struct Lisp_Char_Table_Entry):
* chartab.h (struct Lisp_Char_Table):
* console-gtk-impl.h (struct gtk_device):
* console-gtk-impl.h (struct gtk_frame):
* console-impl.h (struct console):
* console-msw-impl.h (struct Lisp_Devmode):
* console-msw-impl.h (struct mswindows_device):
* console-msw-impl.h (struct msprinter_device):
* console-msw-impl.h (struct mswindows_frame):
* console-msw-impl.h (struct mswindows_dialog_id):
* console-stream-impl.h (struct stream_console):
* console-stream.c (stream_init_console):
* console-tty-impl.h (struct tty_console):
* console-tty-impl.h (struct tty_device):
* console-tty.c (allocate_tty_console_struct):
* console-x-impl.h (struct x_device):
* console-x-impl.h (struct x_frame):
* console.c (allocate_console):
* console.c (nuke_all_console_slots):
* console.c (DEFVAR_CONSOLE_LOCAL_1):
* console.c (common_init_complex_vars_of_console):
* data.c (make_weak_list):
* data.c (make_weak_box):
* data.c (make_ephemeron):
* database.c:
* database.c (struct Lisp_Database):
* database.c (allocate_database):
* database.c (finalize_database):
* device-gtk.c (allocate_gtk_device_struct):
* device-impl.h (struct device):
* device-msw.c:
* device-msw.c (mswindows_init_device):
* device-msw.c (msprinter_init_device):
* device-msw.c (finalize_devmode):
* device-msw.c (allocate_devmode):
* device-tty.c (allocate_tty_device_struct):
* device-x.c (allocate_x_device_struct):
* device.c:
* device.c (nuke_all_device_slots):
* device.c (allocate_device):
* dialog-msw.c (handle_question_dialog_box):
* elhash.c:
* elhash.c (struct Lisp_Hash_Table):
* elhash.c (finalize_hash_table):
* elhash.c (make_general_lisp_hash_table):
* elhash.c (Fcopy_hash_table):
* elhash.h (htentry):
* emacs.c (main_1):
* eval.c:
* eval.c (size_multiple_value):
* event-stream.c (finalize_command_builder):
* event-stream.c (allocate_command_builder):
* event-stream.c (free_command_builder):
* event-stream.c (event_stream_generate_wakeup):
* event-stream.c (event_stream_resignal_wakeup):
* event-stream.c (event_stream_disable_wakeup):
* event-stream.c (event_stream_wakeup_pending_p):
* events.h (struct Lisp_Timeout):
* events.h (struct command_builder):
* extents-impl.h:
* extents-impl.h (struct extent_auxiliary):
* extents-impl.h (struct extent_info):
* extents-impl.h (set_extent_no_chase_aux_field):
* extents-impl.h (set_extent_no_chase_normal_field):
* extents.c:
* extents.c (gap_array_marker):
* extents.c (gap_array):
* extents.c (extent_list_marker):
* extents.c (extent_list):
* extents.c (stack_of_extents):
* extents.c (gap_array_make_marker):
* extents.c (extent_list_make_marker):
* extents.c (allocate_extent_list):
* extents.c (SLOT):
* extents.c (mark_extent_auxiliary):
* extents.c (allocate_extent_auxiliary):
* extents.c (attach_extent_auxiliary):
* extents.c (size_gap_array):
* extents.c (finalize_extent_info):
* extents.c (allocate_extent_info):
* extents.c (uninit_buffer_extents):
* extents.c (allocate_soe):
* extents.c (copy_extent):
* extents.c (vars_of_extents):
* extents.h:
* faces.c (allocate_face):
* faces.h (struct Lisp_Face):
* faces.h (struct face_cachel):
* file-coding.c:
* file-coding.c (finalize_coding_system):
* file-coding.c (sizeof_coding_system):
* file-coding.c (Fcopy_coding_system):
* file-coding.h (struct Lisp_Coding_System):
* file-coding.h (MARKED_SLOT):
* fns.c (size_bit_vector):
* font-mgr.c:
* font-mgr.c (finalize_fc_pattern):
* font-mgr.c (print_fc_pattern):
* font-mgr.c (Ffc_pattern_p):
* font-mgr.c (Ffc_pattern_create):
* font-mgr.c (Ffc_name_parse):
* font-mgr.c (Ffc_name_unparse):
* font-mgr.c (Ffc_pattern_duplicate):
* font-mgr.c (Ffc_pattern_add):
* font-mgr.c (Ffc_pattern_del):
* font-mgr.c (Ffc_pattern_get):
* font-mgr.c (fc_config_create_using):
* font-mgr.c (fc_strlist_to_lisp_using):
* font-mgr.c (fontset_to_list):
* font-mgr.c (Ffc_config_p):
* font-mgr.c (Ffc_config_up_to_date):
* font-mgr.c (Ffc_config_build_fonts):
* font-mgr.c (Ffc_config_get_cache):
* font-mgr.c (Ffc_config_get_fonts):
* font-mgr.c (Ffc_config_set_current):
* font-mgr.c (Ffc_config_get_blanks):
* font-mgr.c (Ffc_config_get_rescan_interval):
* font-mgr.c (Ffc_config_set_rescan_interval):
* font-mgr.c (Ffc_config_app_font_add_file):
* font-mgr.c (Ffc_config_app_font_add_dir):
* font-mgr.c (Ffc_config_app_font_clear):
* font-mgr.c (size):
* font-mgr.c (Ffc_config_substitute):
* font-mgr.c (Ffc_font_render_prepare):
* font-mgr.c (Ffc_font_match):
* font-mgr.c (Ffc_font_sort):
* font-mgr.c (finalize_fc_config):
* font-mgr.c (print_fc_config):
* font-mgr.h:
* font-mgr.h (struct fc_pattern):
* font-mgr.h (XFC_PATTERN):
* font-mgr.h (struct fc_config):
* font-mgr.h (XFC_CONFIG):
* frame-gtk.c (allocate_gtk_frame_struct):
* frame-impl.h (struct frame):
* frame-msw.c (mswindows_init_frame_1):
* frame-x.c (allocate_x_frame_struct):
* frame.c (nuke_all_frame_slots):
* frame.c (allocate_frame_core):
* gc.c:
* gc.c (GC_CHECK_NOT_FREE):
* glyphs.c (finalize_image_instance):
* glyphs.c (allocate_image_instance):
* glyphs.c (Fcolorize_image_instance):
* glyphs.c (allocate_glyph):
* glyphs.c (unmap_subwindow_instance_cache_mapper):
* glyphs.c (register_ignored_expose):
* glyphs.h (struct Lisp_Image_Instance):
* glyphs.h (struct Lisp_Glyph):
* glyphs.h (struct glyph_cachel):
* glyphs.h (struct expose_ignore):
* gui.c (allocate_gui_item):
* gui.h (struct Lisp_Gui_Item):
* keymap.c (struct Lisp_Keymap):
* keymap.c (make_keymap):
* lisp.h:
* lisp.h (struct Lisp_String_Direct_Data):
* lisp.h (struct Lisp_String_Indirect_Data):
* lisp.h (struct Lisp_Vector):
* lisp.h (struct Lisp_Bit_Vector):
* lisp.h (DECLARE_INLINE_LISP_BIT_VECTOR):
* lisp.h (struct weak_box):
* lisp.h (struct ephemeron):
* lisp.h (struct weak_list):
* lrecord.h:
* lrecord.h (struct lrecord_implementation):
* lrecord.h (MC_ALLOC_CALL_FINALIZER):
* lrecord.h (struct lcrecord_list):
* lstream.c (finalize_lstream):
* lstream.c (sizeof_lstream):
* lstream.c (Lstream_new):
* lstream.c (Lstream_delete):
* lstream.h (struct lstream):
* marker.c:
* marker.c (finalize_marker):
* marker.c (compute_buffer_marker_usage):
* mule-charset.c:
* mule-charset.c (make_charset):
* mule-charset.c (compute_charset_usage):
* objects-impl.h (struct Lisp_Color_Instance):
* objects-impl.h (struct Lisp_Font_Instance):
* objects-tty-impl.h (struct tty_color_instance_data):
* objects-tty-impl.h (struct tty_font_instance_data):
* objects-tty.c (tty_initialize_color_instance):
* objects-tty.c (tty_initialize_font_instance):
* objects.c (finalize_color_instance):
* objects.c (Fmake_color_instance):
* objects.c (finalize_font_instance):
* objects.c (Fmake_font_instance):
* objects.c (reinit_vars_of_objects):
* opaque.c:
* opaque.c (sizeof_opaque):
* opaque.c (make_opaque_ptr):
* opaque.c (free_opaque_ptr):
* opaque.h:
* opaque.h (Lisp_Opaque):
* opaque.h (Lisp_Opaque_Ptr):
* print.c (printing_unreadable_lcrecord):
* print.c (external_object_printer):
* print.c (debug_p4):
* process.c (finalize_process):
* process.c (make_process_internal):
* procimpl.h (struct Lisp_Process):
* rangetab.c (Fmake_range_table):
* rangetab.c (Fcopy_range_table):
* rangetab.h (struct Lisp_Range_Table):
* scrollbar.c:
* scrollbar.c (create_scrollbar_instance):
* scrollbar.c (compute_scrollbar_instance_usage):
* scrollbar.h (struct scrollbar_instance):
* specifier.c (finalize_specifier):
* specifier.c (sizeof_specifier):
* specifier.c (set_specifier_caching):
* specifier.h (struct Lisp_Specifier):
* specifier.h (struct specifier_caching):
* symeval.h:
* symeval.h (SYMBOL_VALUE_MAGIC_P):
* symeval.h (DEFVAR_SYMVAL_FWD):
* symsinit.h:
* syntax.c (init_buffer_syntax_cache):
* syntax.h (struct syntax_cache):
* toolbar.c:
* toolbar.c (allocate_toolbar_button):
* toolbar.c (update_toolbar_button):
* toolbar.h (struct toolbar_button):
* tooltalk.c (struct Lisp_Tooltalk_Message):
* tooltalk.c (make_tooltalk_message):
* tooltalk.c (struct Lisp_Tooltalk_Pattern):
* tooltalk.c (make_tooltalk_pattern):
* ui-gtk.c:
* ui-gtk.c (allocate_ffi_data):
* ui-gtk.c (emacs_gtk_object_finalizer):
* ui-gtk.c (allocate_emacs_gtk_object_data):
* ui-gtk.c (allocate_emacs_gtk_boxed_data):
* ui-gtk.h:
* window-impl.h (struct window):
* window-impl.h (struct window_mirror):
* window.c (finalize_window):
* window.c (allocate_window):
* window.c (new_window_mirror):
* window.c (mark_window_as_deleted):
* window.c (make_dummy_parent):
* window.c (compute_window_mirror_usage):
* window.c (compute_window_usage):
Overall point of this change and previous ones in this repository:
(1) Introduce new, clearer terminology: everything other than int
or char is a "record" object, which comes in two types: "normal
objects" and "frob-block objects". Fix up all places that
referred to frob-block objects as "simple", "basic", etc.
(2) Provide an advertised interface for doing operations on Lisp
objects, including creating new types, that is clean and
consistent in its naming, uses the above-referenced terms and
avoids referencing "lrecords", "old lcrecords", etc., which should
hide under the surface.
(3) Make the size_in_bytes and finalizer methods take a
Lisp_Object rather than a void * for consistency with other methods.
(4) Separate finalizer method into finalizer and disksaver, so
that normal finalize methods don't have to worry about disksaving.
Other specifics:
(1) Renaming:
LISP_OBJECT_HEADER -> NORMAL_LISP_OBJECT_HEADER
ALLOC_LISP_OBJECT -> ALLOC_NORMAL_LISP_OBJECT
implementation->basic_p -> implementation->frob_block_p
ALLOCATE_FIXED_TYPE_AND_SET_IMPL -> ALLOC_FROB_BLOCK_LISP_OBJECT
*FCCONFIG*, wrap_fcconfig -> *FC_CONFIG*, wrap_fc_config
*FCPATTERN*, wrap_fcpattern -> *FC_PATTERN*, wrap_fc_pattern
(the last two changes make the naming of these macros consistent
with the naming of all other macros, since the objects are named
fc-config and fc-pattern with a hyphen)
(2) Lots of documentation fixes in lrecord.h.
(3) Eliminate macros for copying, freeing, zeroing objects, getting
their storage size. Instead, new functions:
zero_sized_lisp_object()
zero_nonsized_lisp_object()
lisp_object_storage_size()
free_normal_lisp_object()
(copy_lisp_object() already exists)
LISP_OBJECT_FROB_BLOCK_P() (actually a macro)
Eliminated:
free_lrecord()
zero_lrecord()
copy_lrecord()
copy_sized_lrecord()
old_copy_lcrecord()
old_copy_sized_lcrecord()
old_zero_lcrecord()
old_zero_sized_lcrecord()
LISP_OBJECT_STORAGE_SIZE()
COPY_SIZED_LISP_OBJECT()
COPY_SIZED_LCRECORD()
COPY_LISP_OBJECT()
ZERO_LISP_OBJECT()
FREE_LISP_OBJECT()
(4) Catch the remaining places where lrecord stuff was used directly
and use the advertised interface, e.g. alloc_sized_lrecord() ->
ALLOC_SIZED_LISP_OBJECT().
(5) Make certain statically-declared pseudo-objects
(buffer_local_flags, console_local_flags) have their lheader
initialized correctly, so things like copy_lisp_object() can work
on them. Make extent_auxiliary_defaults a proper heap object
Vextent_auxiliary_defaults, and make extent auxiliaries dumpable
so that this object can be dumped. allocate_extent_auxiliary()
now just creates the object, and attach_extent_auxiliary()
creates an extent auxiliary and attaches to an extent, like the
old allocate_extent_auxiliary().
(6) Create EXTENT_AUXILIARY_SLOTS macro, similar to the foo-slots.h
files but in a macro instead of a file. The purpose is to avoid
duplication when iterating over all the slots in an extent auxiliary.
Use it.
(7) In lstream.c, don't zero out object after allocation because
allocation routines take care of this.
(8) In marker.c, fix a mistake in computing marker overhead.
(9) In print.c, clean up printing_unreadable_lcrecord(),
external_object_printer() to avoid lots of ifdef NEW_GC's.
(10) Separate toolbar-button allocation into a separate
allocate_toolbar_button() function for use in the example code
in lrecord.h.
author | Ben Wing <ben@xemacs.org> |
---|---|
date | Fri, 05 Mar 2010 04:08:17 -0600 |
parents | 2a462149bd6a |
children | 7be849cb8828 |
rev | line source |
---|---|
428 | 1 /* Window creation, deletion and examination for XEmacs. |
2 Copyright (C) 1985-1987, 1992-1995 Free Software Foundation, Inc. | |
3 Copyright (C) 1994, 1995 Board of Trustees, University of Illinois. | |
5043 | 4 Copyright (C) 1995, 1996, 2002, 2010 Ben Wing. |
428 | 5 Copyright (C) 1996 Chuck Thompson. |
6 | |
7 This file is part of XEmacs. | |
8 | |
9 XEmacs is free software; you can redistribute it and/or modify it | |
10 under the terms of the GNU General Public License as published by the | |
11 Free Software Foundation; either version 2, or (at your option) any | |
12 later version. | |
13 | |
14 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
17 for more details. | |
18 | |
19 You should have received a copy of the GNU General Public License | |
20 along with XEmacs; see the file COPYING. If not, write to | |
21 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
22 Boston, MA 02111-1307, USA. */ | |
23 | |
24 /* Synched up with: FSF 19.30. */ | |
25 /* Beginning to diverge significantly. */ | |
26 | |
853 | 27 /* Authorship: |
28 | |
29 Based on code from pre-release FSF 19, c. 1991. | |
30 Significantly reworked by Chuck Thompson, 1993-1996. | |
31 window mirror stuff added by Chuck Thompson c. 1993. | |
32 various cleanup by Ben Wing c. 1995 (window slots, window init code, | |
33 memory usage, synch. up to FSF 19.30, other). | |
34 Unknown work by Andy Piper. | |
35 new window-width/height fns. by Ben Wing, Mar 2000. */ | |
36 | |
428 | 37 /* This file has been Mule-ized. */ |
38 | |
39 #include <config.h> | |
40 #include "lisp.h" | |
41 | |
42 #include "buffer.h" | |
800 | 43 #include "commands.h" |
872 | 44 #include "device-impl.h" |
800 | 45 #include "elhash.h" |
428 | 46 #include "faces.h" |
872 | 47 #include "frame-impl.h" |
800 | 48 #include "glyphs.h" |
49 #include "gutter.h" | |
428 | 50 #include "objects.h" |
51 #include "redisplay.h" | |
872 | 52 #include "window-impl.h" |
428 | 53 |
1149 | 54 Lisp_Object Qwindowp, Qwindow_live_p; |
428 | 55 Lisp_Object Qdisplay_buffer; |
56 | |
57 #ifdef MEMORY_USAGE_STATS | |
58 Lisp_Object Qface_cache, Qglyph_cache, Qline_start_cache, Qother_redisplay; | |
59 #ifdef HAVE_SCROLLBARS | |
60 Lisp_Object Qscrollbar_instances; | |
61 #endif | |
62 #endif | |
63 | |
1979 | 64 extern int allow_deletion_of_last_visible_frame; |
65 | |
428 | 66 EXFUN (Fnext_window, 4); |
67 | |
68 static int window_pixel_width_to_char_width (struct window *w, | |
69 int pixel_width, | |
70 int include_margins_p); | |
71 static int window_char_width_to_pixel_width (struct window *w, | |
72 int char_width, | |
73 int include_margins_p); | |
74 static int window_pixel_height_to_char_height (struct window *w, | |
75 int pixel_height, | |
76 int include_gutters_p); | |
77 static int window_char_height_to_pixel_height (struct window *w, | |
78 int char_height, | |
79 int include_gutters_p); | |
444 | 80 static void change_window_height (Lisp_Object window, int delta, |
81 Lisp_Object horizontalp, int inpixels); | |
428 | 82 |
83 /* Thickness of shadow border around 3d modelines. */ | |
84 Lisp_Object Vmodeline_shadow_thickness; | |
85 | |
86 /* Whether vertical dividers are draggable and displayed */ | |
87 Lisp_Object Vvertical_divider_always_visible_p; | |
88 | |
89 /* Whether a modeline should be displayed. */ | |
90 Lisp_Object Vhas_modeline_p; | |
91 | |
92 /* Thickness of shadow border around vertical dividers. */ | |
93 Lisp_Object Vvertical_divider_shadow_thickness; | |
94 | |
95 /* Divider surface width (not counting 3-d borders) */ | |
96 Lisp_Object Vvertical_divider_line_width; | |
97 | |
442 | 98 /* Spacing between outer edge of divider border and window edge */ |
428 | 99 Lisp_Object Vvertical_divider_spacing; |
100 | |
101 /* How much to scroll by per-line. */ | |
102 Lisp_Object Vwindow_pixel_scroll_increment; | |
103 | |
104 /* Scroll if point lands on the bottom line and that line is partially | |
105 clipped. */ | |
106 int scroll_on_clipped_lines; | |
107 | |
108 /* The minibuffer window of the selected frame. | |
109 Note that you cannot test for minibufferness of an arbitrary window | |
110 by comparing against this; but you can test for minibufferness of | |
111 the selected window. */ | |
112 Lisp_Object minibuf_window; | |
113 | |
114 /* Non-nil means it is the window for C-M-v to scroll | |
115 when the minibuffer is selected. */ | |
116 Lisp_Object Vminibuffer_scroll_window; | |
117 | |
118 /* Non-nil means this is the buffer whose window C-M-v should scroll. */ | |
119 Lisp_Object Vother_window_scroll_buffer; | |
120 | |
121 /* Non-nil means it's the function to call to display temp buffers. */ | |
122 Lisp_Object Vtemp_buffer_show_function; | |
123 | |
124 /* If a window gets smaller than either of these, it is removed. */ | |
458 | 125 Fixnum window_min_height; |
126 Fixnum window_min_width; | |
428 | 127 |
128 /* Number of lines of continuity in scrolling by screenfuls. */ | |
458 | 129 Fixnum next_screen_context_lines; |
428 | 130 |
1149 | 131 Lisp_Object Qcurrent_window_configuration, Qset_window_configuration; |
428 | 132 |
707 | 133 Lisp_Object Qtruncate_partial_width_windows; |
134 | |
428 | 135 #define SET_LAST_MODIFIED(w, cache_too) \ |
136 do { \ | |
137 (w)->last_modified[CURRENT_DISP] = Qzero; \ | |
138 (w)->last_modified[DESIRED_DISP] = Qzero; \ | |
139 (w)->last_modified[CMOTION_DISP] = Qzero; \ | |
140 if (cache_too) \ | |
141 (w)->line_cache_last_updated = Qzero; \ | |
142 } while (0) | |
143 | |
144 #define SET_LAST_FACECHANGE(w) \ | |
145 do { \ | |
146 (w)->last_facechange[CURRENT_DISP] = Qzero; \ | |
147 (w)->last_facechange[DESIRED_DISP] = Qzero; \ | |
148 (w)->last_facechange[CMOTION_DISP] = Qzero; \ | |
149 } while (0) | |
150 | |
151 | |
1204 | 152 |
153 static const struct memory_description int_description_1[] = { | |
154 { XD_END } | |
155 }; | |
156 | |
157 static const struct sized_memory_description int_description = { | |
158 sizeof (int), | |
159 int_description_1 | |
160 }; | |
161 | |
162 static const struct memory_description int_dynarr_description_1[] = { | |
163 XD_DYNARR_DESC (int_dynarr, &int_description), | |
164 { XD_END } | |
165 }; | |
166 | |
167 static const struct sized_memory_description int_dynarr_description = { | |
168 sizeof (int_dynarr), | |
169 int_dynarr_description_1 | |
170 }; | |
171 | |
172 static const struct memory_description face_cachel_description_1[] = { | |
2367 | 173 { XD_BLOCK_PTR, offsetof (face_cachel, merged_faces), |
2551 | 174 1, { &int_dynarr_description } }, |
1204 | 175 { XD_LISP_OBJECT, offsetof (face_cachel, face) }, |
176 { XD_LISP_OBJECT, offsetof (face_cachel, foreground) }, | |
177 { XD_LISP_OBJECT, offsetof (face_cachel, background) }, | |
178 { XD_LISP_OBJECT_ARRAY, offsetof (face_cachel, font), NUM_LEADING_BYTES }, | |
179 { XD_LISP_OBJECT, offsetof (face_cachel, display_table) }, | |
180 { XD_LISP_OBJECT, offsetof (face_cachel, background_pixmap) }, | |
181 { XD_END } | |
182 }; | |
183 | |
3092 | 184 #ifdef NEW_GC |
5118
e0db3c197671
merge up to latest default branch, doesn't compile yet
Ben Wing <ben@xemacs.org>
diff
changeset
|
185 DEFINE_DUMPABLE_INTERNAL_LISP_OBJECT ("face-cachel", face_cachel, |
e0db3c197671
merge up to latest default branch, doesn't compile yet
Ben Wing <ben@xemacs.org>
diff
changeset
|
186 0, face_cachel_description_1, |
e0db3c197671
merge up to latest default branch, doesn't compile yet
Ben Wing <ben@xemacs.org>
diff
changeset
|
187 Lisp_Face_Cachel); |
3092 | 188 #endif /* NEW_GC */ |
189 | |
1204 | 190 static const struct sized_memory_description face_cachel_description = { |
191 sizeof (face_cachel), | |
192 face_cachel_description_1 | |
193 }; | |
194 | |
195 static const struct memory_description face_cachel_dynarr_description_1[] = { | |
3092 | 196 #ifdef NEW_GC |
197 XD_LISP_DYNARR_DESC (face_cachel_dynarr, &face_cachel_description), | |
198 #else /* not NEW_GC */ | |
1204 | 199 XD_DYNARR_DESC (face_cachel_dynarr, &face_cachel_description), |
3092 | 200 #endif /* not NEW_GC */ |
1204 | 201 { XD_END } |
202 }; | |
203 | |
3092 | 204 #ifdef NEW_GC |
5118
e0db3c197671
merge up to latest default branch, doesn't compile yet
Ben Wing <ben@xemacs.org>
diff
changeset
|
205 DEFINE_DUMPABLE_INTERNAL_LISP_OBJECT ("face-cachel-dynarr", face_cachel_dynarr, |
e0db3c197671
merge up to latest default branch, doesn't compile yet
Ben Wing <ben@xemacs.org>
diff
changeset
|
206 0, face_cachel_dynarr_description_1, |
e0db3c197671
merge up to latest default branch, doesn't compile yet
Ben Wing <ben@xemacs.org>
diff
changeset
|
207 face_cachel_dynarr); |
3092 | 208 #else /* not NEW_GC */ |
1204 | 209 static const struct sized_memory_description face_cachel_dynarr_description = { |
210 sizeof (face_cachel_dynarr), | |
211 face_cachel_dynarr_description_1 | |
212 }; | |
3092 | 213 #endif /* not NEW_GC */ |
1204 | 214 |
215 static const struct memory_description glyph_cachel_description_1[] = { | |
216 { XD_LISP_OBJECT, offsetof (glyph_cachel, glyph) }, | |
217 { XD_END } | |
218 }; | |
219 | |
3092 | 220 #ifdef NEW_GC |
5118
e0db3c197671
merge up to latest default branch, doesn't compile yet
Ben Wing <ben@xemacs.org>
diff
changeset
|
221 DEFINE_DUMPABLE_INTERNAL_LISP_OBJECT ("glyph-cachel", glyph_cachel, |
e0db3c197671
merge up to latest default branch, doesn't compile yet
Ben Wing <ben@xemacs.org>
diff
changeset
|
222 0, glyph_cachel_description_1, |
e0db3c197671
merge up to latest default branch, doesn't compile yet
Ben Wing <ben@xemacs.org>
diff
changeset
|
223 Lisp_Glyph_Cachel); |
3092 | 224 #endif /* NEW_GC */ |
225 | |
1204 | 226 static const struct sized_memory_description glyph_cachel_description = { |
227 sizeof (glyph_cachel), | |
228 glyph_cachel_description_1 | |
229 }; | |
230 | |
231 static const struct memory_description glyph_cachel_dynarr_description_1[] = { | |
3092 | 232 #ifdef NEW_GC |
233 XD_LISP_DYNARR_DESC (glyph_cachel_dynarr, &glyph_cachel_description), | |
234 #else /* not NEW_GC */ | |
1204 | 235 XD_DYNARR_DESC (glyph_cachel_dynarr, &glyph_cachel_description), |
3092 | 236 #endif /* not NEW_GC */ |
1204 | 237 { XD_END } |
238 }; | |
239 | |
3092 | 240 #ifdef NEW_GC |
5118
e0db3c197671
merge up to latest default branch, doesn't compile yet
Ben Wing <ben@xemacs.org>
diff
changeset
|
241 DEFINE_DUMPABLE_INTERNAL_LISP_OBJECT ("glyph-cachel-dynarr", |
e0db3c197671
merge up to latest default branch, doesn't compile yet
Ben Wing <ben@xemacs.org>
diff
changeset
|
242 glyph_cachel_dynarr, 0, |
e0db3c197671
merge up to latest default branch, doesn't compile yet
Ben Wing <ben@xemacs.org>
diff
changeset
|
243 glyph_cachel_dynarr_description_1, |
e0db3c197671
merge up to latest default branch, doesn't compile yet
Ben Wing <ben@xemacs.org>
diff
changeset
|
244 glyph_cachel_dynarr); |
3092 | 245 #else /* not NEW_GC */ |
1204 | 246 static const struct sized_memory_description glyph_cachel_dynarr_description = { |
247 sizeof (glyph_cachel_dynarr), | |
248 glyph_cachel_dynarr_description_1 | |
249 }; | |
3092 | 250 #endif /* not NEW_GC */ |
1204 | 251 |
252 static const struct memory_description line_start_cache_description_1[] = { | |
253 { XD_END } | |
254 }; | |
255 | |
256 static const struct sized_memory_description line_start_cache_description = { | |
257 sizeof (line_start_cache), | |
258 line_start_cache_description_1 | |
259 }; | |
260 | |
261 static const struct memory_description line_start_cache_dynarr_description_1[] = { | |
262 XD_DYNARR_DESC (line_start_cache_dynarr, &line_start_cache_description), | |
263 { XD_END } | |
264 }; | |
265 | |
266 static const struct sized_memory_description line_start_cache_dynarr_description = { | |
267 sizeof (line_start_cache_dynarr), | |
268 line_start_cache_dynarr_description_1 | |
269 }; | |
270 | |
271 static const struct memory_description window_description [] = { | |
272 #define WINDOW_SLOT(slot) { XD_LISP_OBJECT, offsetof (struct window, slot) }, | |
273 #define WINDOW_SLOT_ARRAY(slot, size) \ | |
274 { XD_LISP_OBJECT_ARRAY, offsetof (struct window, slot), size }, | |
275 #include "winslots.h" | |
276 | |
3092 | 277 #ifdef NEW_GC |
278 { XD_LISP_OBJECT, offsetof (struct window, face_cachels) }, | |
279 { XD_LISP_OBJECT, offsetof (struct window, glyph_cachels) }, | |
280 #else /* not NEW_GC */ | |
2367 | 281 { XD_BLOCK_PTR, offsetof (struct window, face_cachels), |
2551 | 282 1, { &face_cachel_dynarr_description } }, |
2367 | 283 { XD_BLOCK_PTR, offsetof (struct window, glyph_cachels), |
2551 | 284 1, { &glyph_cachel_dynarr_description } }, |
3092 | 285 #endif /* not NEW_GC */ |
2367 | 286 { XD_BLOCK_PTR, offsetof (struct window, line_start_cache), |
2775 | 287 1, { &line_start_cache_dynarr_description }, XD_FLAG_NO_KKCC }, |
1204 | 288 { XD_END } |
289 }; | |
428 | 290 |
291 static Lisp_Object | |
292 mark_window (Lisp_Object obj) | |
293 { | |
294 struct window *window = XWINDOW (obj); | |
295 | |
296 mark_face_cachels (window->face_cachels); | |
297 mark_glyph_cachels (window->glyph_cachels); | |
298 | |
617 | 299 #define WINDOW_SLOT(slot) mark_object (window->slot); |
428 | 300 #include "winslots.h" |
301 | |
302 return Qnil; | |
303 } | |
304 | |
305 static void | |
2286 | 306 print_window (Lisp_Object obj, Lisp_Object printcharfun, |
307 int UNUSED (escapeflag)) | |
428 | 308 { |
4846 | 309 Lisp_Object buf; |
310 | |
428 | 311 if (print_readably) |
4846 | 312 printing_unreadable_lcrecord (obj, 0); |
428 | 313 |
4952
19a72041c5ed
Mule-izing, various fixes related to char * arguments
Ben Wing <ben@xemacs.org>
parents:
4932
diff
changeset
|
314 write_ascstring (printcharfun, "#<window"); |
4846 | 315 buf = XWINDOW_BUFFER (obj); |
316 if (EQ (buf, Qt)) | |
4952
19a72041c5ed
Mule-izing, various fixes related to char * arguments
Ben Wing <ben@xemacs.org>
parents:
4932
diff
changeset
|
317 write_ascstring (printcharfun, " during creation"); |
4846 | 318 else if (!NILP (buf)) |
428 | 319 { |
4846 | 320 |
321 Lisp_Object name = XBUFFER (buf)->name; | |
800 | 322 write_fmt_string_lisp (printcharfun, " on %S", 1, name); |
428 | 323 } |
800 | 324 write_fmt_string (printcharfun, " 0x%x>", XWINDOW (obj)->header.uid); |
428 | 325 } |
326 | |
327 static void | |
5127
a9c41067dd88
more cleanups, terminology clarification, lots of doc work
Ben Wing <ben@xemacs.org>
parents:
5126
diff
changeset
|
328 finalize_window (Lisp_Object obj) |
428 | 329 { |
5127
a9c41067dd88
more cleanups, terminology clarification, lots of doc work
Ben Wing <ben@xemacs.org>
parents:
5126
diff
changeset
|
330 struct window *w = XWINDOW (obj); |
428 | 331 |
332 if (w->line_start_cache) | |
333 { | |
334 Dynarr_free (w->line_start_cache); | |
335 w->line_start_cache = 0; | |
336 } | |
337 | |
338 if (w->face_cachels) | |
339 { | |
340 int i; | |
341 | |
342 for (i = 0; i < Dynarr_length (w->face_cachels); i++) | |
343 { | |
344 struct face_cachel *cachel = Dynarr_atp (w->face_cachels, i); | |
345 if (cachel->merged_faces) | |
346 { | |
347 Dynarr_free (cachel->merged_faces); | |
348 cachel->merged_faces = 0; | |
349 } | |
350 } | |
351 Dynarr_free (w->face_cachels); | |
352 w->face_cachels = 0; | |
353 } | |
354 | |
355 if (w->glyph_cachels) | |
356 { | |
357 Dynarr_free (w->glyph_cachels); | |
358 w->glyph_cachels = 0; | |
359 } | |
360 } | |
361 | |
844 | 362 /* These caches map buffers to markers. They are key-weak so that entries |
363 remain around as long as the buffers do. */ | |
364 | |
365 static Lisp_Object | |
366 make_saved_buffer_point_cache (void) | |
367 { | |
368 return make_lisp_hash_table (20, HASH_TABLE_KEY_WEAK, HASH_TABLE_EQ); | |
369 } | |
370 | |
5118
e0db3c197671
merge up to latest default branch, doesn't compile yet
Ben Wing <ben@xemacs.org>
diff
changeset
|
371 DEFINE_NODUMP_LISP_OBJECT ("window", window, |
5124
623d57b7fbe8
separate regular and disksave finalization, print method fixes.
Ben Wing <ben@xemacs.org>
parents:
5120
diff
changeset
|
372 mark_window, print_window, finalize_window, |
623d57b7fbe8
separate regular and disksave finalization, print method fixes.
Ben Wing <ben@xemacs.org>
parents:
5120
diff
changeset
|
373 0, 0, window_description, struct window); |
428 | 374 |
375 #define INIT_DISP_VARIABLE(field, initialization) \ | |
376 p->field[CURRENT_DISP] = initialization; \ | |
377 p->field[DESIRED_DISP] = initialization; \ | |
378 p->field[CMOTION_DISP] = initialization; | |
379 | |
380 /* We have an implicit assertion that the first two elements (default | |
381 and modeline faces) are always present in the face_element_cache. | |
382 Normally redisplay ensures this. However, it is possible for a | |
383 window to get created and functions which reference these values | |
384 called before redisplay works with the window for the first time. | |
385 All callers of allocate_window should therefore call | |
386 reset_face_cachels on the created window. We can't do it | |
387 here because the window must have its frame pointer set or | |
388 reset_face_cachels will fail. */ | |
389 Lisp_Object | |
390 allocate_window (void) | |
391 { | |
5127
a9c41067dd88
more cleanups, terminology clarification, lots of doc work
Ben Wing <ben@xemacs.org>
parents:
5126
diff
changeset
|
392 Lisp_Object obj = ALLOC_NORMAL_LISP_OBJECT (window); |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3078
diff
changeset
|
393 struct window *p = XWINDOW (obj); |
617 | 394 |
395 #define WINDOW_SLOT(slot) p->slot = Qnil; | |
396 #include "winslots.h" | |
397 | |
428 | 398 INIT_DISP_VARIABLE (start, Fmake_marker ()); |
399 INIT_DISP_VARIABLE (pointm, Fmake_marker ()); | |
400 p->sb_point = Fmake_marker (); | |
844 | 401 p->saved_point_cache = make_saved_buffer_point_cache (); |
402 p->saved_last_window_start_cache = make_saved_buffer_point_cache (); | |
428 | 403 p->use_time = Qzero; |
404 INIT_DISP_VARIABLE (last_modified, Qzero); | |
405 INIT_DISP_VARIABLE (last_point, Fmake_marker ()); | |
406 INIT_DISP_VARIABLE (last_start, Fmake_marker ()); | |
407 INIT_DISP_VARIABLE (last_facechange, Qzero); | |
3092 | 408 #ifdef NEW_GC |
409 p->face_cachels = Dynarr_lisp_new (face_cachel, | |
410 &lrecord_face_cachel_dynarr, | |
411 &lrecord_face_cachel); | |
412 p->glyph_cachels = Dynarr_lisp_new (glyph_cachel, | |
413 &lrecord_glyph_cachel_dynarr, | |
414 &lrecord_glyph_cachel); | |
415 #else /* not NEW_GC */ | |
428 | 416 p->face_cachels = Dynarr_new (face_cachel); |
417 p->glyph_cachels = Dynarr_new (glyph_cachel); | |
3092 | 418 #endif /* not NEW_GC */ |
428 | 419 p->line_start_cache = Dynarr_new (line_start_cache); |
450 | 420 p->subwindow_instance_cache = make_image_instance_cache_hash_table (); |
421 | |
428 | 422 p->line_cache_last_updated = Qzero; |
442 | 423 |
428 | 424 p->windows_changed = 1; |
425 p->shadow_thickness_changed = 1; | |
426 | |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3078
diff
changeset
|
427 return obj; |
428 | 428 } |
429 #undef INIT_DISP_VARIABLE | |
430 | |
617 | 431 /************************************************************************/ |
432 /* Window mirror structure */ | |
433 /************************************************************************/ | |
434 | |
428 | 435 /* |
436 * The redisplay structures used to be stored with each window. While | |
437 * they are logically something associated with frames they can't be | |
438 * stored there with a redisplay which handles variable height lines. | |
439 * Lines in horizontally split windows might not line up. So they get | |
440 * stored with the windows. | |
441 * | |
442 * The problem with this is window configurations. When restoring a | |
443 * window configuration it now becomes problematic to do an | |
444 * incremental redisplay. The solution is to store the redisplay | |
445 * structures with the frame as they should be but laid out in the | |
446 * same manner as the window structure. Thus is born the window | |
447 * mirror. | |
448 * | |
449 * It also becomes a convenient place to stick scrollbar instances | |
450 * since they extrapolate out to having the same problem described for | |
451 * the display structures. | |
452 */ | |
453 | |
617 | 454 /* NOTE: The window-mirror structure formerly was not a Lisp object, and |
455 marking was handled specially. I've gotten recurring crashes, however, | |
456 using the mouse wheel under Windows, where either the window mirror | |
457 accessed through a scrollbar instance, or the frame pointed to by that | |
458 window mirror, gets garbaged. Things are tricky under windows because | |
459 the scrollbar instances are stored in HWND-specific data. Furthermore, | |
460 we have scrollbar-instance caches to complicate things. Both of these | |
461 make it very difficult (for me at least, not being intimately familiar | |
462 with the redisplay code) to track exactly when and where a particular | |
463 window mirror or scrollbar instance has pointers to it, or whether a | |
464 window mirror might have a dead frame or buffer in it (i.e. not | |
465 necessarily gc-protected by being on a global list). By far the safest | |
466 thing, then, is to make both structures Lisp objects and not explicitly | |
467 xfree() them. This should make no practical difference in memory usage | |
468 because neither structure is created very often (only when windows are | |
469 created or deleted). --ben */ | |
470 | |
1204 | 471 static const struct memory_description window_mirror_description [] = { |
472 { XD_LISP_OBJECT, offsetof (struct window_mirror, frame) }, | |
473 { XD_LISP_OBJECT, offsetof (struct window_mirror, next) }, | |
474 { XD_LISP_OBJECT, offsetof (struct window_mirror, hchild) }, | |
475 { XD_LISP_OBJECT, offsetof (struct window_mirror, vchild) }, | |
476 | |
2367 | 477 { XD_BLOCK_PTR, offsetof (struct window_mirror, current_display_lines), |
2551 | 478 1, { &display_line_dynarr_description } }, |
2367 | 479 { XD_BLOCK_PTR, offsetof (struct window_mirror, desired_display_lines), |
2551 | 480 1, { &display_line_dynarr_description } }, |
1204 | 481 |
482 { XD_LISP_OBJECT, offsetof (struct window_mirror, buffer) }, | |
483 | |
484 #ifdef HAVE_SCROLLBARS | |
485 { XD_LISP_OBJECT, offsetof (struct window_mirror, | |
486 scrollbar_vertical_instance) }, | |
487 { XD_LISP_OBJECT, offsetof (struct window_mirror, | |
488 scrollbar_horizontal_instance) }, | |
489 #endif /* HAVE_SCROLLBARS */ | |
490 | |
934 | 491 { XD_END } |
492 }; | |
493 | |
617 | 494 static Lisp_Object |
495 mark_window_mirror (Lisp_Object obj) | |
496 { | |
497 struct window_mirror *mir = XWINDOW_MIRROR (obj); | |
498 | |
499 if (mir->current_display_lines) | |
500 mark_redisplay_structs (mir->current_display_lines); | |
501 if (mir->desired_display_lines) | |
502 mark_redisplay_structs (mir->desired_display_lines); | |
503 | |
504 if (mir->hchild) | |
505 mark_object (wrap_window_mirror (mir->hchild)); | |
506 if (mir->vchild) | |
507 mark_object (wrap_window_mirror (mir->vchild)); | |
508 | |
509 if (mir->frame) | |
510 mark_object (wrap_frame (mir->frame)); | |
511 if (mir->buffer) | |
512 mark_object (wrap_buffer (mir->buffer)); | |
513 | |
514 #ifdef HAVE_SCROLLBARS | |
515 if (mir->scrollbar_vertical_instance) | |
516 mark_object (wrap_scrollbar_instance (mir->scrollbar_vertical_instance)); | |
517 if (mir->scrollbar_horizontal_instance) | |
518 mark_object (wrap_scrollbar_instance (mir->scrollbar_horizontal_instance)); | |
519 #endif /* HAVE_SCROLLBARS */ | |
520 if (mir->next) | |
521 return wrap_window_mirror (mir->next); | |
522 else | |
523 return Qnil; | |
524 } | |
525 | |
5124
623d57b7fbe8
separate regular and disksave finalization, print method fixes.
Ben Wing <ben@xemacs.org>
parents:
5120
diff
changeset
|
526 DEFINE_NODUMP_INTERNAL_LISP_OBJECT ("window-mirror", window_mirror, |
623d57b7fbe8
separate regular and disksave finalization, print method fixes.
Ben Wing <ben@xemacs.org>
parents:
5120
diff
changeset
|
527 mark_window_mirror, |
623d57b7fbe8
separate regular and disksave finalization, print method fixes.
Ben Wing <ben@xemacs.org>
parents:
5120
diff
changeset
|
528 window_mirror_description, |
623d57b7fbe8
separate regular and disksave finalization, print method fixes.
Ben Wing <ben@xemacs.org>
parents:
5120
diff
changeset
|
529 struct window_mirror); |
617 | 530 |
428 | 531 /* Create a new window mirror structure and associated redisplay |
532 structs. */ | |
533 static struct window_mirror * | |
534 new_window_mirror (struct frame *f) | |
535 { | |
5127
a9c41067dd88
more cleanups, terminology clarification, lots of doc work
Ben Wing <ben@xemacs.org>
parents:
5126
diff
changeset
|
536 Lisp_Object obj = ALLOC_NORMAL_LISP_OBJECT (window_mirror); |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3078
diff
changeset
|
537 struct window_mirror *t = XWINDOW_MIRROR (obj); |
428 | 538 |
539 t->frame = f; | |
540 t->current_display_lines = Dynarr_new (display_line); | |
541 t->desired_display_lines = Dynarr_new (display_line); | |
542 | |
543 return t; | |
544 } | |
545 | |
546 /* Synchronize the mirror structure with a given window structure. | |
547 This is normally called from update_frame_window_mirror with a | |
548 starting window of f->root_window. */ | |
549 static struct window_mirror * | |
550 update_mirror_internal (Lisp_Object win, struct window_mirror *mir) | |
551 { | |
552 if (NILP (win)) | |
553 { | |
554 if (mir) | |
555 { | |
556 free_window_mirror (mir); | |
557 mir = NULL; | |
558 } | |
559 return mir; | |
560 } | |
561 else | |
562 if (!mir) | |
563 mir = new_window_mirror (XFRAME (XWINDOW (win)->frame)); | |
564 | |
1204 | 565 mir->next = update_mirror_internal (XWINDOW (win)->next, mir->next); |
428 | 566 mir->hchild = update_mirror_internal (XWINDOW (win)->hchild, mir->hchild); |
567 mir->vchild = update_mirror_internal (XWINDOW (win)->vchild, mir->vchild); | |
568 | |
569 /* | |
570 * If the redisplay structs are not empty and the mirror has | |
571 * children, then this mirror structure was formerly being used for | |
572 * display but is no longer. Reset its current display structs so | |
573 * that redisplay doesn't accidentally think they are accurate if it | |
574 * is later used for display purposes once again. Also, mark the | |
575 * scrollbar instance as not active. | |
576 */ | |
577 if (mir->vchild || mir->hchild) | |
578 { | |
579 /* The redisplay structures are big. Leaving them around in | |
580 non-leaf windows can add up to a lot of wasted space. So | |
581 don't do it. */ | |
582 free_display_structs (mir); | |
583 mir->current_display_lines = Dynarr_new (display_line); | |
584 mir->desired_display_lines = Dynarr_new (display_line); | |
585 | |
586 #ifdef HAVE_SCROLLBARS | |
587 update_window_scrollbars (XWINDOW (win), mir, 0, 0); | |
588 #endif | |
589 mir->buffer = NULL; | |
590 } | |
591 | |
592 return mir; | |
593 } | |
594 | |
595 /* Given a window mirror, determine which real window it contains the | |
596 redisplay structures for. */ | |
597 static Lisp_Object | |
598 real_window_internal (Lisp_Object win, struct window_mirror *rmir, | |
599 struct window_mirror *mir) | |
600 { | |
601 for (; !NILP (win) && rmir ; win = XWINDOW (win)->next, rmir = rmir->next) | |
602 { | |
603 if (mir == rmir) | |
604 return win; | |
605 if (!NILP (XWINDOW (win)->vchild)) | |
606 { | |
607 Lisp_Object retval = | |
608 real_window_internal (XWINDOW (win)->vchild, rmir->vchild, mir); | |
609 if (!NILP (retval)) | |
610 return retval; | |
611 } | |
612 if (!NILP (XWINDOW (win)->hchild)) | |
613 { | |
614 Lisp_Object retval = | |
615 real_window_internal (XWINDOW (win)->hchild, rmir->hchild, mir); | |
616 if (!NILP (retval)) | |
617 return retval; | |
618 } | |
619 } | |
620 | |
621 return Qnil; | |
622 } | |
623 | |
624 /* Given a real window, find the mirror structure which contains its | |
625 redisplay structures. */ | |
626 static struct window_mirror * | |
627 find_window_mirror_internal (Lisp_Object win, struct window_mirror *rmir, | |
628 struct window *w) | |
629 { | |
630 for (; !NILP (win); win = XWINDOW (win)->next, rmir = rmir->next) | |
631 { | |
632 if (w == XWINDOW (win)) | |
633 return rmir; | |
634 | |
635 if (!NILP (XWINDOW (win)->vchild)) | |
636 { | |
637 struct window_mirror *retval = | |
638 find_window_mirror_internal (XWINDOW (win)->vchild, | |
639 rmir->vchild, w); | |
640 if (retval) return retval; | |
641 } | |
642 | |
643 if (!NILP (XWINDOW (win)->hchild)) | |
644 { | |
645 struct window_mirror *retval = | |
646 find_window_mirror_internal (XWINDOW (win)->hchild, | |
647 rmir->hchild, w); | |
648 if (retval) return retval; | |
649 } | |
650 } | |
651 | |
652 return 0; | |
653 } | |
654 | |
655 /* Update the mirror structure for the given frame. */ | |
656 void | |
657 update_frame_window_mirror (struct frame *f) | |
658 { | |
617 | 659 f->root_mirror = |
660 wrap_window_mirror (update_mirror_internal | |
661 (f->root_window, | |
662 NILP (f->root_mirror) ? 0 : | |
663 XWINDOW_MIRROR (f->root_mirror))); | |
428 | 664 f->mirror_dirty = 0; |
665 } | |
666 | |
667 /* Free a given mirror structure along with all of its children as | |
668 well as their associated display structures. */ | |
669 void | |
670 free_window_mirror (struct window_mirror *mir) | |
671 { | |
672 while (mir) | |
673 { | |
674 if (mir->hchild) free_window_mirror (mir->hchild); | |
675 if (mir->vchild) free_window_mirror (mir->vchild); | |
676 #ifdef HAVE_SCROLLBARS | |
677 release_window_mirror_scrollbars (mir); | |
678 #endif | |
679 free_display_structs (mir); | |
680 mir = mir->next; | |
617 | 681 /* not worth calling free_managed_lcrecord() -- window mirrors |
682 are not created that frequently and it's dangerous. we don't | |
683 know for sure that there aren't other pointers around -- e.g. | |
684 in a scrollbar instance. */ | |
428 | 685 } |
686 } | |
687 | |
688 /* Given a mirror structure, return the window it mirrors. Calls | |
689 real_window_internal to do most of the work. */ | |
690 Lisp_Object | |
691 real_window (struct window_mirror *mir, int no_abort) | |
692 { | |
617 | 693 Lisp_Object retval = |
694 real_window_internal (mir->frame->root_window, | |
695 XWINDOW_MIRROR (mir->frame->root_mirror), mir); | |
5050
6f2158fa75ed
Fix quick-build, use asserts() in place of ABORT()
Ben Wing <ben@xemacs.org>
parents:
4967
diff
changeset
|
696 assert (!NILP (retval) || no_abort); |
428 | 697 |
698 return retval; | |
699 } | |
700 | |
701 /* Given a real window, return its mirror structure. Calls | |
702 find_window_mirror_internal to do all of the work. */ | |
703 struct window_mirror * | |
704 find_window_mirror (struct window *w) | |
705 { | |
706 struct frame *f = XFRAME (w->frame); | |
707 if (f->mirror_dirty) | |
708 update_frame_window_mirror (f); | |
617 | 709 return find_window_mirror_internal (f->root_window, |
710 XWINDOW_MIRROR (f->root_mirror), w); | |
428 | 711 } |
712 | |
713 /***************************************************************************** | |
714 find_window_by_pixel_pos | |
715 | |
716 Given a pixel position relative to a frame, find the window at that | |
717 position. | |
718 ****************************************************************************/ | |
719 struct window * | |
720 find_window_by_pixel_pos (int pix_x, int pix_y, Lisp_Object win) | |
721 { | |
722 if (NILP (win)) | |
723 return 0; | |
724 | |
725 for (; !NILP (win); win = XWINDOW (win)->next) | |
726 { | |
727 struct window *w; | |
728 | |
729 if (!NILP (XWINDOW (win)->vchild)) | |
730 { | |
731 w = find_window_by_pixel_pos (pix_x, pix_y, XWINDOW (win)->vchild); | |
732 if (w) return w; | |
733 } | |
734 if (!NILP (XWINDOW (win)->hchild)) | |
735 { | |
736 w = find_window_by_pixel_pos (pix_x, pix_y, XWINDOW (win)->hchild); | |
737 if (w) return w; | |
738 } | |
739 w = XWINDOW (win); | |
740 if (pix_x >= WINDOW_LEFT (w) | |
741 && pix_x <= WINDOW_RIGHT (w) | |
742 && pix_y >= WINDOW_TOP (w) | |
743 && pix_y <= WINDOW_BOTTOM (w)) | |
744 return w; | |
745 } | |
746 return NULL; | |
747 } | |
748 | |
749 /* Return a pointer to the display structures for the given window. */ | |
750 display_line_dynarr * | |
751 window_display_lines (struct window *w, int which) | |
752 { | |
753 struct window_mirror *t; | |
754 | |
755 if (XFRAME (w->frame)->mirror_dirty) | |
756 update_frame_window_mirror (XFRAME (w->frame)); | |
757 t = find_window_mirror (w); | |
5050
6f2158fa75ed
Fix quick-build, use asserts() in place of ABORT()
Ben Wing <ben@xemacs.org>
parents:
4967
diff
changeset
|
758 assert (t); |
428 | 759 |
760 if (which == CURRENT_DISP) | |
761 return t->current_display_lines; | |
762 else if (which == DESIRED_DISP) | |
763 return t->desired_display_lines; | |
764 else if (which == CMOTION_DISP) | |
765 /* The CMOTION_DISP display lines are global. */ | |
766 return cmotion_display_lines; | |
767 else | |
2500 | 768 ABORT (); |
428 | 769 |
770 return 0; /* shut up compiler */ | |
771 } | |
772 | |
773 struct buffer * | |
774 window_display_buffer (struct window *w) | |
775 { | |
776 struct window_mirror *t; | |
777 | |
778 if (XFRAME (w->frame)->mirror_dirty) | |
779 update_frame_window_mirror (XFRAME (w->frame)); | |
780 t = find_window_mirror (w); | |
5050
6f2158fa75ed
Fix quick-build, use asserts() in place of ABORT()
Ben Wing <ben@xemacs.org>
parents:
4967
diff
changeset
|
781 assert (t); |
428 | 782 |
783 return t->buffer; | |
784 } | |
785 | |
786 void | |
787 set_window_display_buffer (struct window *w, struct buffer *b) | |
788 { | |
789 struct window_mirror *t; | |
790 | |
791 if (XFRAME (w->frame)->mirror_dirty) | |
792 update_frame_window_mirror (XFRAME (w->frame)); | |
793 t = find_window_mirror (w); | |
5050
6f2158fa75ed
Fix quick-build, use asserts() in place of ABORT()
Ben Wing <ben@xemacs.org>
parents:
4967
diff
changeset
|
794 assert (t); |
428 | 795 |
796 t->buffer = b; | |
797 } | |
798 | |
799 | |
800 /* Determining a window's position based solely on its pixel | |
801 positioning doesn't work. Instead, we do it the intelligent way, | |
802 by checking its positioning in the window hierarchy. */ | |
803 int | |
804 window_is_leftmost (struct window *w) | |
805 { | |
806 Lisp_Object parent, current_ancestor, window; | |
807 | |
793 | 808 window = wrap_window (w); |
428 | 809 |
810 parent = XWINDOW (window)->parent; | |
811 current_ancestor = window; | |
812 | |
813 while (!NILP (parent)) | |
814 { | |
815 if (!NILP (XWINDOW (parent)->hchild) && | |
816 !EQ (XWINDOW (parent)->hchild, current_ancestor)) | |
817 return 0; | |
818 | |
819 current_ancestor = parent; | |
820 parent = XWINDOW (parent)->parent; | |
821 } | |
822 | |
823 return 1; | |
824 } | |
825 | |
826 int | |
827 window_is_rightmost (struct window *w) | |
828 { | |
829 Lisp_Object parent, current_ancestor, window; | |
830 | |
793 | 831 window = wrap_window (w); |
428 | 832 |
833 parent = XWINDOW (window)->parent; | |
834 current_ancestor = window; | |
835 | |
836 while (!NILP (parent)) | |
837 { | |
838 if (!NILP (XWINDOW (parent)->hchild) | |
839 && !NILP (XWINDOW (current_ancestor)->next)) | |
840 return 0; | |
841 | |
842 current_ancestor = parent; | |
843 parent = XWINDOW (parent)->parent; | |
844 } | |
845 | |
846 return 1; | |
847 } | |
848 | |
849 static int | |
850 window_full_width_p (struct window *w) | |
851 { | |
852 return window_is_leftmost (w) && window_is_rightmost (w); | |
853 } | |
854 | |
855 int | |
856 window_is_highest (struct window *w) | |
857 { | |
858 Lisp_Object parent, current_ancestor, window; | |
859 | |
793 | 860 window = wrap_window (w); |
428 | 861 |
862 parent = XWINDOW (window)->parent; | |
863 current_ancestor = window; | |
864 | |
865 while (!NILP (parent)) | |
866 { | |
867 if (!NILP (XWINDOW (parent)->vchild) && | |
868 !EQ (XWINDOW (parent)->vchild, current_ancestor)) | |
869 return 0; | |
870 | |
871 current_ancestor = parent; | |
872 parent = XWINDOW (parent)->parent; | |
873 } | |
874 | |
875 /* This is really to catch the minibuffer but we make it generic in | |
876 case we ever change things around to let the minibuffer be on top. */ | |
877 if (NILP (XWINDOW (current_ancestor)->prev)) | |
878 return 1; | |
879 else | |
880 return 0; | |
881 } | |
882 | |
883 int | |
884 window_is_lowest (struct window *w) | |
885 { | |
886 Lisp_Object parent, current_ancestor, window; | |
887 | |
793 | 888 window = wrap_window (w); |
428 | 889 |
890 parent = XWINDOW (window)->parent; | |
891 current_ancestor = window; | |
892 | |
893 while (!NILP (parent)) | |
894 { | |
895 if (!NILP (XWINDOW (parent)->vchild) | |
896 && !NILP (XWINDOW (current_ancestor)->next)) | |
897 return 0; | |
898 | |
899 current_ancestor = parent; | |
900 parent = XWINDOW (parent)->parent; | |
901 } | |
902 | |
903 return 1; | |
904 } | |
905 | |
906 #if 0 /* not currently used */ | |
907 | |
908 static int | |
909 window_full_height_p (struct window *w) | |
910 { | |
911 return window_is_highest (w) && window_is_lowest (w); | |
912 } | |
913 | |
914 #endif | |
915 | |
916 int | |
917 window_truncation_on (struct window *w) | |
918 { | |
919 /* Minibuffer windows are never truncated. | |
440 | 920 #### is this the right way ? */ |
428 | 921 if (MINI_WINDOW_P (w)) |
922 return 0; | |
923 | |
924 /* Horizontally scrolled windows are truncated. */ | |
925 if (w->hscroll) | |
926 return 1; | |
927 | |
928 /* If truncate_partial_width_windows is true and the window is not | |
929 the full width of the frame it is truncated. */ | |
707 | 930 if (!NILP (symbol_value_in_buffer (Qtruncate_partial_width_windows, |
931 w->buffer)) | |
428 | 932 && !(window_is_leftmost (w) && window_is_rightmost (w))) |
933 return 1; | |
934 | |
935 /* If the window's buffer's value of truncate_lines is non-nil, then | |
936 the window is truncated. */ | |
937 if (!NILP (XBUFFER (w->buffer)->truncate_lines)) | |
938 return 1; | |
939 | |
940 return 0; | |
941 } | |
942 | |
943 DEFUN ("window-truncated-p", Fwindow_truncated_p, 0, 1, 0, /* | |
442 | 944 Returns non-nil if text in the window is truncated. |
428 | 945 */ |
946 (window)) | |
947 { | |
948 struct window *w = decode_window (window); | |
949 | |
950 return window_truncation_on (w) ? Qt : Qnil; | |
951 } | |
952 | |
953 | |
954 static int | |
955 have_undivided_common_edge (struct window *w_right, void *closure) | |
956 { | |
957 struct window *w_left = (struct window *) closure; | |
958 return (WINDOW_RIGHT (w_left) == WINDOW_LEFT (w_right) | |
959 && WINDOW_TOP (w_left) < WINDOW_BOTTOM (w_right) | |
960 && WINDOW_TOP (w_right) < WINDOW_BOTTOM (w_left) | |
961 #ifdef HAVE_SCROLLBARS | |
962 && (NILP (w_right->scrollbar_on_left_p) | |
963 || NILP (w_right->vertical_scrollbar_visible_p) | |
964 || ZEROP (w_right->scrollbar_width)) | |
965 #endif | |
966 ); | |
967 } | |
968 | |
969 static int | |
970 window_needs_vertical_divider_1 (struct window *w) | |
971 { | |
972 /* Never if we're on the right */ | |
973 if (window_is_rightmost (w)) | |
974 return 0; | |
975 | |
976 /* Always if draggable */ | |
977 if (!NILP (w->vertical_divider_always_visible_p)) | |
978 return 1; | |
979 | |
980 #ifdef HAVE_SCROLLBARS | |
981 /* Our right scrollbar is enough to separate us at the right */ | |
982 if (NILP (w->scrollbar_on_left_p) | |
983 && !NILP (w->vertical_scrollbar_visible_p) | |
984 && !ZEROP (w->scrollbar_width)) | |
985 return 0; | |
986 #endif | |
987 | |
988 /* Ok. to determine whether we need a divider on the left, we must | |
989 check that our right neighbor windows have scrollbars on their | |
990 left sides. We must check all such windows which have common | |
991 left edge with our window's right edge. */ | |
992 return map_windows (XFRAME (WINDOW_FRAME (w)), | |
993 have_undivided_common_edge, (void*)w); | |
994 } | |
995 | |
996 int | |
997 window_needs_vertical_divider (struct window *w) | |
998 { | |
999 if (!w->need_vertical_divider_valid_p) | |
1000 { | |
1001 w->need_vertical_divider_p = | |
1002 window_needs_vertical_divider_1 (w); | |
1003 w->need_vertical_divider_valid_p = 1; | |
1004 } | |
1005 return w->need_vertical_divider_p; | |
1006 } | |
1007 | |
1008 /* Called from invalidate_vertical_divider_cache_in_frame */ | |
1009 int | |
1010 invalidate_vertical_divider_cache_in_window (struct window *w, | |
2286 | 1011 void *UNUSED (unused)) |
428 | 1012 { |
1013 w->need_vertical_divider_valid_p = 0; | |
1014 return 0; | |
1015 } | |
1016 | |
1017 /* Calculate width of vertical divider, including its shadows | |
1018 and spacing. The returned value is effectively the distance | |
1019 between adjacent window edges. This function does not check | |
1020 whether a window needs a vertical divider, so the returned | |
1021 value is a "theoretical" one */ | |
1022 int | |
1023 window_divider_width (struct window *w) | |
1024 { | |
1025 /* the shadow thickness can be negative. This means that the divider | |
1026 will have a depressed look */ | |
1027 | |
1028 if (FRAME_WIN_P (XFRAME (WINDOW_FRAME (w)))) | |
1029 return | |
1030 XINT (w->vertical_divider_line_width) | |
1031 + 2 * XINT (w->vertical_divider_spacing) | |
1032 + 2 * abs (XINT (w->vertical_divider_shadow_thickness)); | |
1033 else | |
1034 return XINT (w->vertical_divider_line_width) == 0 ? 0 : 1; | |
1035 } | |
1036 | |
1037 int | |
4932 | 1038 window_scrollbar_width (struct window * USED_IF_SCROLLBARS (w)) |
428 | 1039 { |
1040 #ifdef HAVE_SCROLLBARS | |
1041 if (!WINDOW_WIN_P (w) | |
1042 || MINI_WINDOW_P (w) | |
1043 || NILP (w->buffer) | |
1044 || NILP (w->vertical_scrollbar_visible_p)) | |
1045 /* #### when does NILP (w->buffer) happen? */ | |
1046 return 0; | |
1047 | |
1048 return XINT (w->scrollbar_width); | |
1049 #else | |
1050 return 0; | |
1051 #endif /* HAVE_SCROLLBARS */ | |
1052 } | |
1053 | |
1054 /* Horizontal scrollbars are only active on windows with truncation | |
1055 turned on. */ | |
1056 int | |
4932 | 1057 window_scrollbar_height (struct window * USED_IF_SCROLLBARS (w)) |
428 | 1058 { |
1059 #ifdef HAVE_SCROLLBARS | |
1060 if (!WINDOW_WIN_P (w) | |
1061 || MINI_WINDOW_P (w) | |
1062 || NILP (w->buffer) | |
1063 || NILP (w->horizontal_scrollbar_visible_p) | |
1064 || !window_truncation_on (w)) | |
1065 return 0; | |
1066 | |
1067 return XINT (w->scrollbar_height); | |
1068 #else | |
1069 return 0; | |
1070 #endif /* HAVE_SCROLLBARS */ | |
1071 } | |
1072 | |
1073 int | |
1074 window_modeline_height (struct window *w) | |
1075 { | |
1076 struct frame *f = XFRAME (w->frame); | |
1077 int modeline_height; | |
1078 | |
1079 if (MINI_WINDOW_P (w) || NILP (w->buffer)) | |
1080 { | |
1081 modeline_height = 0; | |
1082 } | |
1083 else if (!WINDOW_HAS_MODELINE_P (w)) | |
1084 { | |
1085 if (window_scrollbar_height (w)) | |
1086 modeline_height = 0; | |
1087 else | |
1088 { | |
1089 modeline_height = FRAMEMETH (f, divider_height, ()); | |
1090 | |
1091 if (!EQ (Qzero, w->modeline_shadow_thickness) && FRAME_WIN_P (f)) | |
1092 modeline_height += (2 * MODELINE_SHADOW_THICKNESS (w)); | |
1093 } | |
1094 } | |
1095 else | |
1096 { | |
1097 if (noninteractive) | |
1098 modeline_height = 0; | |
1099 else | |
1100 { | |
1101 display_line_dynarr *dla; | |
1102 | |
1103 /* We don't force a regeneration of the modeline here. | |
1104 Instead it is now a precondition that any function calling | |
1105 this should make sure that one of these structures is | |
1106 up-to-date. In practice this only affects two internal | |
1107 redisplay functions, regenerate_window and | |
1108 regenerate_window_point_center. */ | |
1109 /* We check DESIRED_DISP because if it is valid it is more | |
1110 up-to-date than CURRENT_DISP. For calls to this outside | |
1111 of redisplay it doesn't matter which structure we check | |
1112 since there is a redisplay condition that these | |
1113 structures be identical outside of redisplay. */ | |
1114 dla = window_display_lines (w, DESIRED_DISP); | |
4967 | 1115 if (dla && Dynarr_length (dla) && Dynarr_begin (dla)->modeline) |
1116 modeline_height = (Dynarr_begin (dla)->ascent + | |
1117 Dynarr_begin (dla)->descent); | |
428 | 1118 else |
1119 { | |
1120 dla = window_display_lines (w, CURRENT_DISP); | |
4967 | 1121 if (dla && Dynarr_length (dla) && Dynarr_begin (dla)->modeline) |
1122 modeline_height = (Dynarr_begin (dla)->ascent + | |
1123 Dynarr_begin (dla)->descent); | |
428 | 1124 else |
1125 /* This should be an abort except I'm not yet 100% | |
1126 confident that it won't ever get hit (though I | |
1127 haven't been able to trigger it). It is extremely | |
1128 unlikely to cause any noticeable problem and even if | |
1129 it does it will be a minor display glitch. */ | |
1130 /* #### Bullshit alert. It does get hit and it causes | |
1131 noticeable glitches. real_current_modeline_height | |
1132 is a kludge to fix this for 19.14. */ | |
1133 modeline_height = real_current_modeline_height (w); | |
1134 } | |
1135 | |
1136 if (!EQ (Qzero, w->modeline_shadow_thickness) && FRAME_WIN_P (f)) | |
1137 modeline_height += (2 * MODELINE_SHADOW_THICKNESS (w)); | |
1138 } | |
1139 } | |
1140 | |
1141 return modeline_height; | |
1142 } | |
1143 | |
1144 /***************************************************************************** | |
1145 margin_width_internal | |
1146 | |
1147 For a given window, return the width in pixels of the specified margin. | |
1148 ****************************************************************************/ | |
1149 static int | |
1150 margin_width_internal (struct window *w, int left_margin) | |
1151 { | |
1152 int window_cwidth = window_char_width (w, 1); | |
1153 int margin_cwidth; | |
1154 int font_width; | |
1155 Lisp_Object window; | |
1156 | |
1157 /* We might be getting called on a non-leaf. */ | |
1158 if (NILP (w->buffer)) | |
1159 return 0; | |
1160 | |
1161 /* The minibuffer never has margins. */ | |
1162 if (MINI_WINDOW_P (w)) | |
1163 return 0; | |
1164 | |
793 | 1165 window = wrap_window (w); |
428 | 1166 margin_cwidth = (left_margin ? XINT (w->left_margin_width) : |
1167 XINT (w->right_margin_width)); | |
1168 | |
5047
07dcc7000bbf
put width before height consistently, fix a real bug found in the process
Ben Wing <ben@xemacs.org>
parents:
5043
diff
changeset
|
1169 default_face_width_and_height (window, &font_width, 0); |
428 | 1170 |
1171 /* The left margin takes precedence over the right margin so we | |
1172 subtract its width from the space available for the right | |
1173 margin. */ | |
1174 if (!left_margin) | |
1175 window_cwidth -= XINT (w->left_margin_width); | |
1176 | |
1177 /* The margin cannot be wider than the window is. We allow the | |
1178 value to be bigger since it is possible for the user to enlarge | |
1179 the window such that the left margin value would no longer be too | |
1180 big, but we won't return a value that is larger. */ | |
1181 if (margin_cwidth > window_cwidth) | |
1182 margin_cwidth = window_cwidth; | |
1183 | |
1184 /* At the user level the margin is always specified in characters. | |
1185 Internally however it is manipulated in terms of pixels. */ | |
1186 return margin_cwidth * font_width; | |
1187 } | |
1188 | |
1189 int | |
1190 window_left_margin_width (struct window *w) | |
1191 { | |
1192 return margin_width_internal (w, 1); | |
1193 } | |
1194 | |
1195 int | |
1196 window_right_margin_width (struct window *w) | |
1197 { | |
1198 return margin_width_internal (w, 0); | |
1199 } | |
1200 | |
1201 /***************************************************************************** | |
1202 Window Gutters | |
1203 | |
1204 The gutters of a window are those areas in the boundary defined by | |
1205 w->pixel_top, w->pixel_left, w->pixel_height and w->pixel_width which | |
1206 do not contain text. Items which may be in the gutters include | |
1207 scrollbars, toolbars and modelines. The margin areas are not | |
1208 included. This is an exception made because redisplay special cases | |
1209 the handling of those areas in many places in such a way that | |
1210 including them in the gutter area would make life difficult. | |
1211 | |
1212 The size functions refer to height for the bottom and top gutters and | |
1213 width for the left and right gutters. The starting position | |
1214 functions refer to the Y coord for bottom and top gutters and the X | |
1215 coord for left and right gutters. All starting positions are | |
1216 relative to the frame, not the window. | |
1217 ****************************************************************************/ | |
1218 | |
442 | 1219 static int |
1220 window_top_window_gutter_height (struct window *w) | |
1221 { | |
428 | 1222 if (!NILP (w->hchild) || !NILP (w->vchild)) |
1223 return 0; | |
1224 | |
1225 #ifdef HAVE_SCROLLBARS | |
1226 if (!NILP (w->scrollbar_on_top_p)) | |
442 | 1227 return window_scrollbar_height (w); |
428 | 1228 else |
1229 #endif | |
442 | 1230 return 0; |
428 | 1231 } |
1232 | |
1233 int | |
442 | 1234 window_top_gutter_height (struct window *w) |
1235 { | |
1236 return window_top_window_gutter_height (w); | |
1237 } | |
1238 | |
1239 static int | |
1240 window_bottom_window_gutter_height (struct window *w) | |
1241 { | |
1242 int gutter; | |
428 | 1243 |
1244 if (!NILP (w->hchild) || !NILP (w->vchild)) | |
1245 return 0; | |
1246 | |
442 | 1247 gutter = window_modeline_height (w); |
428 | 1248 |
1249 #ifdef HAVE_SCROLLBARS | |
1250 if (NILP (w->scrollbar_on_top_p)) | |
1251 return window_scrollbar_height (w) + gutter; | |
1252 else | |
1253 #endif | |
1254 return gutter; | |
1255 } | |
1256 | |
1257 int | |
442 | 1258 window_bottom_gutter_height (struct window *w) |
1259 { | |
1260 return window_bottom_window_gutter_height (w); | |
1261 } | |
1262 | |
1263 static int | |
4932 | 1264 window_left_window_gutter_width (struct window *w, |
1265 int USED_IF_SCROLLBARS (modeline)) | |
442 | 1266 { |
428 | 1267 if (!NILP (w->hchild) || !NILP (w->vchild)) |
1268 return 0; | |
1269 | |
1270 #ifdef HAVE_SCROLLBARS | |
1271 if (!modeline && !NILP (w->scrollbar_on_left_p)) | |
442 | 1272 return window_scrollbar_width (w); |
428 | 1273 #endif |
1274 | |
442 | 1275 return 0; |
428 | 1276 } |
1277 | |
1278 int | |
442 | 1279 window_left_gutter_width (struct window *w, int modeline) |
1280 { | |
1281 return window_left_window_gutter_width (w, modeline); | |
1282 } | |
1283 | |
1284 static int | |
4932 | 1285 window_right_window_gutter_width (struct window *w, |
1286 int USED_IF_SCROLLBARS (modeline)) | |
442 | 1287 { |
1288 int gutter = 0; | |
428 | 1289 |
1290 if (!NILP (w->hchild) || !NILP (w->vchild)) | |
1291 return 0; | |
1292 | |
1293 #ifdef HAVE_SCROLLBARS | |
1294 if (!modeline && NILP (w->scrollbar_on_left_p)) | |
1295 gutter += window_scrollbar_width (w); | |
1296 #endif | |
1297 | |
1298 if (window_needs_vertical_divider (w)) | |
1299 gutter += window_divider_width (w); | |
1300 | |
1301 return gutter; | |
1302 } | |
1303 | |
442 | 1304 int |
1305 window_right_gutter_width (struct window *w, int modeline) | |
1306 { | |
1307 return window_right_window_gutter_width (w, modeline); | |
1308 } | |
1309 | |
1310 static int | |
1311 window_pixel_height (struct window* w) | |
1312 { | |
1313 return WINDOW_HEIGHT (w); | |
1314 } | |
1315 | |
428 | 1316 |
1317 DEFUN ("windowp", Fwindowp, 1, 1, 0, /* | |
444 | 1318 Return t if OBJECT is a window. |
428 | 1319 */ |
444 | 1320 (object)) |
1321 { | |
1322 return WINDOWP (object) ? Qt : Qnil; | |
428 | 1323 } |
1324 | |
1325 DEFUN ("window-live-p", Fwindow_live_p, 1, 1, 0, /* | |
444 | 1326 Return t if OBJECT is a window which is currently visible. |
428 | 1327 */ |
444 | 1328 (object)) |
1329 { | |
1330 return WINDOWP (object) && WINDOW_LIVE_P (XWINDOW (object)) | |
1331 ? Qt : Qnil; | |
428 | 1332 } |
1333 | |
1334 DEFUN ("selected-window", Fselected_window, 0, 1, 0, /* | |
1335 Return the window that the cursor now appears in and commands apply to. | |
1336 If the optional argument CON-DEV-OR-FRAME is specified and is a frame, return | |
1337 the selected window used by that frame. If CON-DEV-OR-FRAME is a device, | |
1338 then the selected frame on that device will be used. If CON-DEV-OR-FRAME | |
1339 is a console, the selected frame on that console's selected device will | |
1340 be used. Otherwise, the selected frame is used. | |
1341 */ | |
1342 (con_dev_or_frame)) | |
1343 { | |
1344 if (NILP (con_dev_or_frame) && NILP (Fselected_device (Qnil))) | |
1345 return Qnil; /* happens at startup */ | |
1346 | |
1347 { | |
1348 struct frame *f = decode_frame_or_selected (con_dev_or_frame); | |
1349 return FRAME_SELECTED_WINDOW (f); | |
1350 } | |
1351 } | |
1352 | |
1353 DEFUN ("last-nonminibuf-window", Flast_nonminibuf_window, 0, 1, 0, /* | |
1354 Return the last selected window that is not a minibuffer window. | |
1355 If the optional argument CON-DEV-OR-FRAME is specified and is a frame, | |
1356 return the last non-minibuffer window used by that frame. If | |
1357 CON-DEV-OR-FRAME is a device, then the selected frame on that device | |
1358 will be used. If CON-DEV-OR-FRAME is a console, the selected frame on | |
1359 that console's selected device will be used. Otherwise, the selected | |
1360 frame is used. | |
1361 */ | |
1362 (con_dev_or_frame)) | |
1363 { | |
1364 if (NILP (con_dev_or_frame) && NILP (Fselected_device (Qnil))) | |
1365 return Qnil; /* happens at startup */ | |
1366 | |
1367 { | |
1368 struct frame *f = decode_frame_or_selected (con_dev_or_frame); | |
1369 return FRAME_LAST_NONMINIBUF_WINDOW (f); | |
1370 } | |
1371 } | |
1372 | |
1373 DEFUN ("minibuffer-window", Fminibuffer_window, 0, 1, 0, /* | |
1374 Return the window used now for minibuffers. | |
1375 If the optional argument CON-DEV-OR-FRAME is specified and is a frame, return | |
1376 the minibuffer window used by that frame. If CON-DEV-OR-FRAME is a device, | |
1377 then the selected frame on that device will be used. If CON-DEV-OR-FRAME | |
1378 is a console, the selected frame on that console's selected device will | |
1379 be used. Otherwise, the selected frame is used. | |
1380 */ | |
1381 (con_dev_or_frame)) | |
1382 { | |
1383 return FRAME_MINIBUF_WINDOW (decode_frame_or_selected (con_dev_or_frame)); | |
1384 } | |
1385 | |
438 | 1386 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, 0, 1, 0, /* |
428 | 1387 Return non-nil if WINDOW is a minibuffer window. |
1388 */ | |
1389 (window)) | |
1390 { | |
1391 return MINI_WINDOW_P (decode_window (window)) ? Qt : Qnil; | |
1392 } | |
1393 | |
1394 DEFUN ("window-first-hchild", Fwindow_first_hchild, 1, 1, 0, /* | |
1395 Return the first horizontal child of WINDOW, or nil. | |
1396 */ | |
1397 (window)) | |
1398 { | |
1399 return decode_window (window)->hchild; | |
1400 } | |
1401 | |
1402 DEFUN ("window-first-vchild", Fwindow_first_vchild, 1, 1, 0, /* | |
1403 Return the first vertical child of WINDOW, or nil. | |
1404 */ | |
1405 (window)) | |
1406 { | |
1407 return decode_window (window)->vchild; | |
1408 } | |
1409 | |
1410 DEFUN ("window-next-child", Fwindow_next_child, 1, 1, 0, /* | |
1411 Return the next window on the same level as WINDOW, or nil. | |
1412 */ | |
1413 (window)) | |
1414 { | |
1415 return decode_window (window)->next; | |
1416 } | |
1417 | |
1418 DEFUN ("window-previous-child", Fwindow_previous_child, 1, 1, 0, /* | |
1419 Return the previous window on the same level as WINDOW, or nil. | |
1420 */ | |
1421 (window)) | |
1422 { | |
1423 return decode_window (window)->prev; | |
1424 } | |
1425 | |
1426 DEFUN ("window-parent", Fwindow_parent, 1, 1, 0, /* | |
1427 Return the parent of WINDOW, or nil. | |
1428 */ | |
1429 (window)) | |
1430 { | |
1431 return decode_window (window)->parent; | |
1432 } | |
1433 | |
1434 DEFUN ("window-lowest-p", Fwindow_lowest_p, 1, 1, 0, /* | |
1435 Return non-nil if WINDOW is along the bottom of its frame. | |
1436 */ | |
1437 (window)) | |
1438 { | |
1439 return window_is_lowest (decode_window (window)) ? Qt : Qnil; | |
1440 } | |
1441 | |
1442 DEFUN ("window-highest-p", Fwindow_highest_p, 1, 1, 0, /* | |
1443 Return non-nil if WINDOW is along the top of its frame. | |
1444 */ | |
1445 (window)) | |
1446 { | |
1447 return window_is_highest (decode_window (window)) ? Qt : Qnil; | |
1448 } | |
1449 | |
1450 DEFUN ("window-leftmost-p", Fwindow_leftmost_p, 1, 1, 0, /* | |
1451 Return non-nil if WINDOW is along the left edge of its frame. | |
1452 */ | |
1453 (window)) | |
1454 { | |
1455 return window_is_leftmost (decode_window (window)) ? Qt : Qnil; | |
1456 } | |
1457 | |
1458 DEFUN ("window-rightmost-p", Fwindow_rightmost_p, 1, 1, 0, /* | |
1459 Return non-nil if WINDOW is along the right edge of its frame. | |
1460 */ | |
1461 (window)) | |
1462 { | |
1463 return window_is_rightmost (decode_window (window)) ? Qt : Qnil; | |
1464 } | |
1465 | |
1708 | 1466 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p, 0, 3, 0, /* |
1467 Returns t if position POS is currently on the frame in WINDOW. | |
428 | 1468 Returns nil if that position is scrolled vertically out of view. |
1708 | 1469 If a character is only partially visible, nil is returned, unless the |
1470 optional argument PARTIALLY is non-nil. | |
428 | 1471 POS defaults to point in WINDOW's buffer; WINDOW, to the selected window. |
1472 */ | |
1708 | 1473 (pos, window, partially)) |
428 | 1474 { |
1475 struct window *w = decode_window (window); | |
665 | 1476 Charbpos top = marker_position (w->start[CURRENT_DISP]); |
1477 Charbpos posint; | |
428 | 1478 struct buffer *buf = XBUFFER (w->buffer); |
1479 | |
1480 if (NILP (pos)) | |
1481 posint = BUF_PT (buf); | |
1482 else | |
1483 { | |
1484 CHECK_INT_COERCE_MARKER (pos); | |
1485 posint = XINT (pos); | |
1486 } | |
1487 | |
1488 if (posint < top || posint > BUF_ZV (buf)) | |
1489 return Qnil; | |
1490 | |
1491 /* w->start can be out of range. If it is, do something reasonable. */ | |
1492 if (top < BUF_BEGV (buf) || top > BUF_ZV (buf)) | |
1493 return Qnil; | |
1494 | |
1708 | 1495 return point_would_be_visible (w, top, posint, !NILP (partially)) |
1496 ? Qt : Qnil; | |
428 | 1497 } |
1498 | |
1499 | |
1500 struct window * | |
1501 decode_window (Lisp_Object window) | |
1502 { | |
1503 if (NILP (window)) | |
1504 return XWINDOW (Fselected_window (Qnil)); | |
1505 | |
1506 CHECK_LIVE_WINDOW (window); | |
1507 return XWINDOW (window); | |
1508 } | |
1509 | |
872 | 1510 int |
1511 window_live_p (struct window *w) | |
1512 { | |
1513 return WINDOW_LIVE_P (w); | |
1514 } | |
1515 | |
1516 Lisp_Object | |
1517 window_frame (struct window *w) | |
1518 { | |
1519 return WINDOW_FRAME (w); | |
1520 } | |
1521 | |
1522 Lisp_Object | |
1523 window_buffer (struct window *w) | |
1524 { | |
1525 return WINDOW_BUFFER (w); | |
1526 } | |
1527 | |
428 | 1528 DEFUN ("window-buffer", Fwindow_buffer, 0, 1, 0, /* |
1529 Return the buffer that WINDOW is displaying. | |
1530 */ | |
1531 (window)) | |
1532 { | |
1533 return decode_window (window)->buffer; | |
1534 } | |
1535 | |
1536 DEFUN ("window-frame", Fwindow_frame, 0, 1, 0, /* | |
1537 Return the frame that window WINDOW is on. | |
1538 */ | |
1539 (window)) | |
1540 { | |
1541 return decode_window (window)->frame; | |
1542 } | |
1543 | |
1544 DEFUN ("window-height", Fwindow_height, 0, 1, 0, /* | |
1545 Return the number of default lines in WINDOW. | |
1546 This actually works by dividing the window's pixel height (including | |
1547 the modeline and horizontal scrollbar, if any) by the height of the | |
1548 default font; therefore, the number of displayed lines will probably | |
1549 be different. | |
1550 Use `window-height' to get consistent results in geometry calculations. | |
1551 Use `window-displayed-height' to get the actual number of lines | |
1552 currently displayed in a window. | |
442 | 1553 |
1554 The names are somewhat confusing; here's a table to help out: | |
1555 | |
1556 width height | |
1557 ------------------------------------------------------------------------- | |
1558 w/o gutters | |
1559 (rows/columns) window-width window-text-area-height | |
1560 (pixels) window-text-area-pixel-width window-text-area-pixel-height | |
1561 | |
1562 with gutters | |
1563 (rows/columns) window-full-width window-height | |
1564 (pixels) window-pixel-width window-pixel-height | |
1565 | |
1566 actually displayed | |
1567 (rows/columns) ---- window-displayed-height | |
1568 (pixels) ---- window-displayed-text-pixel-height | |
428 | 1569 */ |
1570 (window)) | |
1571 { | |
1572 return make_int (window_char_height (decode_window (window), 1)); | |
1573 } | |
1574 | |
1575 DEFUN ("window-displayed-height", Fwindow_displayed_height, 0, 1, 0, /* | |
1576 Return the number of lines currently displayed in WINDOW. | |
1577 This counts the actual number of lines displayed in WINDOW | |
1578 \(as opposed to `window-height'). The modeline and horizontal | |
1579 scrollbar do not count as lines. If there is some blank space | |
1580 between the end of the buffer and the end of the window, this | |
1581 function pretends that there are lines of text in the default | |
1582 font there. | |
1583 */ | |
1584 (window)) | |
1585 { | |
1586 return make_int (window_displayed_height (decode_window (window))); | |
1587 } | |
1588 | |
1589 DEFUN ("window-pixel-height", Fwindow_pixel_height, 0, 1, 0, /* | |
1590 Return the height of WINDOW in pixels. Defaults to current window. | |
1591 This includes the window's modeline and horizontal scrollbar (if any). | |
1592 */ | |
1593 (window)) | |
1594 { | |
442 | 1595 return make_int (window_pixel_height (decode_window (window))); |
1596 } | |
1597 | |
1598 DEFUN ("window-text-area-height", Fwindow_text_area_height, 0, 1, 0, /* | |
1599 Return the number of default lines in the text area of WINDOW. | |
1600 This actually works by dividing the window's text area pixel height (i.e. | |
1601 excluding the modeline and horizontal scrollbar, if any) by the height of the | |
1602 default font; therefore, the number of displayed lines will probably | |
1603 be different. | |
1604 See also `window-height' and `window-displayed-height'. | |
1605 */ | |
1606 (window)) | |
1607 { | |
1608 return make_int (window_char_height (decode_window (window), 0)); | |
428 | 1609 } |
1610 | |
1611 DEFUN ("window-text-area-pixel-height", | |
1612 Fwindow_text_area_pixel_height, 0, 1, 0, /* | |
1613 Return the height in pixels of the text-displaying portion of WINDOW. | |
1614 Unlike `window-pixel-height', the space occupied by the modeline and | |
1615 horizontal scrollbar, if any, is not counted. | |
1616 */ | |
1617 (window)) | |
1618 { | |
1619 struct window *w = decode_window (window); | |
1620 | |
1621 return make_int (WINDOW_TEXT_HEIGHT (w)); | |
1622 } | |
1623 | |
1624 DEFUN ("window-displayed-text-pixel-height", | |
1625 Fwindow_displayed_text_pixel_height, 0, 2, 0, /* | |
1626 Return the height in pixels of the text displayed in WINDOW. | |
1627 Unlike `window-text-area-pixel-height', any blank space below the | |
1628 end of the buffer is not included. If optional argument NOCLIPPED | |
1629 is non-nil, do not include space occupied by clipped lines. | |
1630 */ | |
1631 (window, noclipped)) | |
1632 { | |
1633 struct window *w; | |
665 | 1634 Charbpos start, eobuf; |
428 | 1635 int defheight; |
1636 int hlimit, height, prev_height = -1; | |
1637 int line; | |
1638 int elt, nelt, i; | |
1639 int needed; | |
1640 line_start_cache_dynarr *cache; | |
1641 | |
1642 if (NILP (window)) | |
1643 window = Fselected_window (Qnil); | |
1644 | |
1645 CHECK_LIVE_WINDOW (window); | |
1646 w = XWINDOW (window); | |
1647 | |
1648 start = marker_position (w->start[CURRENT_DISP]); | |
1649 hlimit = WINDOW_TEXT_HEIGHT (w); | |
1650 eobuf = BUF_ZV (XBUFFER (w->buffer)); | |
1651 | |
5047
07dcc7000bbf
put width before height consistently, fix a real bug found in the process
Ben Wing <ben@xemacs.org>
parents:
5043
diff
changeset
|
1652 default_face_width_and_height (window, NULL, &defheight); |
428 | 1653 |
1654 /* guess lines needed in line start cache + a few extra */ | |
1655 needed = (hlimit + defheight-1) / defheight + 3; | |
1656 | |
1657 while (1) { | |
1658 elt = point_in_line_start_cache (w, start, needed); | |
1659 assert (elt >= 0); /* in the cache */ | |
1660 | |
1661 cache = w->line_start_cache; | |
1662 nelt = Dynarr_length (cache); | |
1663 | |
1664 height = 0; | |
1665 for (i = elt; i < nelt; i++) { | |
1666 line = Dynarr_atp (cache, i)->height; | |
1667 | |
1668 if (height + line > hlimit) | |
1669 return make_int (!NILP (noclipped) ? height : hlimit); | |
1670 | |
1671 height += line; | |
1672 | |
1673 if (height == hlimit || Dynarr_atp (cache, i)->end >= eobuf) | |
1674 return make_int (height); | |
1675 } | |
1676 | |
1677 /* get here => need more cache lines. try again. */ | |
1678 assert(height > prev_height); /* progress? */ | |
1679 prev_height = height; | |
1680 | |
1681 needed += ((hlimit - height)*(nelt - elt) + height-1)/height + 3; | |
1682 } | |
1683 | |
1204 | 1684 RETURN_NOT_REACHED(make_int (0)); /* shut up compiler */ |
428 | 1685 } |
1686 | |
1687 DEFUN ("window-width", Fwindow_width, 0, 1, 0, /* | |
1688 Return the number of display columns in WINDOW. | |
442 | 1689 This is the width that is usable columns available for text in WINDOW, |
1690 and does not include vertical scrollbars, dividers, or the like. See also | |
1691 `window-full-width' and `window-height'. | |
428 | 1692 */ |
1693 (window)) | |
1694 { | |
1695 return make_int (window_char_width (decode_window (window), 0)); | |
1696 } | |
1697 | |
442 | 1698 DEFUN ("window-full-width", Fwindow_full_width, 0, 1, 0, /* |
1699 Return the total number of columns in WINDOW. | |
1700 This is like `window-width' but includes vertical scrollbars, dividers, | |
1701 etc. | |
1702 */ | |
1703 (window)) | |
1704 { | |
1705 return make_int (window_char_width (decode_window (window), 1)); | |
1706 } | |
1707 | |
428 | 1708 DEFUN ("window-pixel-width", Fwindow_pixel_width, 0, 1, 0, /* |
1709 Return the width of WINDOW in pixels. Defaults to current window. | |
1710 */ | |
1711 (window)) | |
1712 { | |
1713 return make_int (decode_window (window)->pixel_width); | |
1714 } | |
1715 | |
1716 DEFUN ("window-text-area-pixel-width", | |
1717 Fwindow_text_area_pixel_width, 0, 1, 0, /* | |
1718 Return the width in pixels of the text-displaying portion of WINDOW. | |
1719 Unlike `window-pixel-width', the space occupied by the vertical | |
1720 scrollbar or divider, if any, is not counted. | |
1721 */ | |
1722 (window)) | |
1723 { | |
1724 struct window *w = decode_window (window); | |
1725 | |
1726 return make_int (WINDOW_TEXT_WIDTH (w)); | |
1727 } | |
1728 | |
1729 DEFUN ("window-hscroll", Fwindow_hscroll, 0, 1, 0, /* | |
1730 Return the number of columns by which WINDOW is scrolled from left margin. | |
1731 */ | |
1732 (window)) | |
1733 { | |
1734 return make_int (decode_window (window)->hscroll); | |
1735 } | |
1736 | |
1737 DEFUN ("modeline-hscroll", Fmodeline_hscroll, 0, 1, 0, /* | |
442 | 1738 Return the horizontal scrolling amount of WINDOW's modeline. |
438 | 1739 If the window has no modeline, return nil. |
428 | 1740 */ |
1741 (window)) | |
1742 { | |
1743 struct window *w = decode_window (window); | |
1744 | |
438 | 1745 return (WINDOW_HAS_MODELINE_P (w)) ? make_int ((int) w->modeline_hscroll) : |
1746 Qnil; | |
428 | 1747 } |
1748 | |
1749 DEFUN ("set-modeline-hscroll", Fset_modeline_hscroll, 2, 2, 0, /* | |
442 | 1750 Set the horizontal scrolling amount of WINDOW's modeline to NCOL. |
438 | 1751 If NCOL is negative, it will silently be forced to 0. |
1752 If the window has no modeline, return nil. Otherwise, return the actual | |
1753 value that was set. | |
428 | 1754 */ |
1755 (window, ncol)) | |
1756 { | |
1757 struct window *w = decode_window (window); | |
1758 | |
1759 if (WINDOW_HAS_MODELINE_P (w)) | |
1760 { | |
438 | 1761 Charcount ncols; |
1762 | |
428 | 1763 CHECK_INT (ncol); |
438 | 1764 ncols = (XINT (ncol) <= 0) ? 0 : (Charcount) XINT (ncol); |
1765 if (ncols != w->modeline_hscroll) | |
1766 { | |
1767 MARK_MODELINE_CHANGED; | |
1768 w->modeline_hscroll = ncols; | |
1769 } | |
1770 return make_int ((int) ncols); | |
428 | 1771 } |
438 | 1772 |
428 | 1773 return Qnil; |
1774 } | |
1775 | |
1776 DEFUN ("set-window-hscroll", Fset_window_hscroll, 2, 2, 0, /* | |
1777 Set number of columns WINDOW is scrolled from left margin to NCOL. | |
1778 NCOL should be zero or positive. | |
1779 */ | |
1780 (window, ncol)) | |
1781 { | |
1782 struct window *w; | |
1783 int ncols; | |
1784 | |
1785 CHECK_INT (ncol); | |
1786 ncols = XINT (ncol); | |
1787 if (ncols < 0) ncols = 0; | |
1788 w = decode_window (window); | |
1789 if (w->hscroll != ncols) | |
1790 MARK_CLIP_CHANGED; /* FSF marks differently but we aren't FSF. */ | |
1791 w->hscroll = ncols; | |
1792 return ncol; | |
1793 } | |
1794 | |
1795 DEFUN ("window-pixel-edges", Fwindow_pixel_edges, 0, 1, 0, /* | |
1796 Return a list of the pixel edge coordinates of WINDOW. | |
444 | 1797 The returned list is of the form (LEFT TOP RIGHT BOTTOM), |
1798 all relative to 0, 0 at the top left corner of WINDOW's frame. | |
1799 The frame toolbars, menubars and gutters are considered to be outside | |
1800 of this area, while the scrollbars are considered to be inside. | |
428 | 1801 */ |
1802 (window)) | |
1803 { | |
1804 struct window *w = decode_window (window); | |
1805 struct frame *f = XFRAME (w->frame); | |
1806 | |
442 | 1807 int left = |
1808 w->pixel_left - FRAME_LEFT_BORDER_END (f) - FRAME_LEFT_GUTTER_BOUNDS (f); | |
1809 int top = | |
1810 w->pixel_top - FRAME_TOP_BORDER_END (f) - FRAME_TOP_GUTTER_BOUNDS (f); | |
428 | 1811 |
1812 return list4 (make_int (left), | |
1813 make_int (top), | |
1814 make_int (left + w->pixel_width), | |
1815 make_int (top + w->pixel_height)); | |
1816 } | |
1817 | |
1818 DEFUN ("window-text-area-pixel-edges", | |
1819 Fwindow_text_area_pixel_edges, 0, 1, 0, /* | |
1820 Return a list of the pixel edge coordinates of the text area of WINDOW. | |
444 | 1821 The returned list is of the form (LEFT TOP RIGHT BOTTOM), |
1822 all relative to 0, 0 at the top left corner of the total area allocated | |
1823 to the window, which includes the scrollbars. | |
428 | 1824 */ |
1825 (window)) | |
1826 { | |
1827 struct window *w = decode_window (window); | |
1828 | |
1829 int left = window_left_gutter_width (w, /* modeline = */ 0); | |
1830 int top = window_top_gutter_height (w); | |
1831 int right = WINDOW_WIDTH (w) - window_right_gutter_width (w, 0); | |
1832 int bottom = WINDOW_HEIGHT (w) - window_bottom_gutter_height (w); | |
1833 | |
1834 return list4 (make_int (left), | |
1835 make_int (top), | |
1836 make_int (right), | |
1837 make_int (bottom)); | |
1838 } | |
1839 | |
1840 DEFUN ("window-point", Fwindow_point, 0, 1, 0, /* | |
1841 Return current value of point in WINDOW. | |
442 | 1842 For a non-selected window, this is the value point would have |
428 | 1843 if that window were selected. |
1844 | |
1845 Note that, when WINDOW is the selected window and its buffer | |
1846 is also currently selected, the value returned is the same as (point). | |
1847 It would be more strictly correct to return the `top-level' value | |
1848 of point, outside of any save-excursion forms. | |
444 | 1849 But that value is hard to find. |
428 | 1850 */ |
1851 (window)) | |
1852 { | |
1853 struct window *w = decode_window (window); | |
1854 | |
1855 /* The special check for current buffer is necessary for this | |
1856 function to work as defined when called within an excursion. */ | |
1857 if (w == XWINDOW (Fselected_window (XFRAME (w->frame)->device)) | |
1858 && current_buffer == XBUFFER (w->buffer)) | |
1859 return Fpoint (Qnil); | |
1860 return Fmarker_position (w->pointm[CURRENT_DISP]); | |
1861 } | |
1862 | |
1863 DEFUN ("window-start", Fwindow_start, 0, 1, 0, /* | |
1864 Return position at which display currently starts in WINDOW. | |
1865 This is updated by redisplay or by calling `set-window-start'. | |
1866 */ | |
1867 (window)) | |
1868 { | |
1869 return Fmarker_position (decode_window (window)->start[CURRENT_DISP]); | |
1870 } | |
1871 | |
1872 DEFUN ("window-end", Fwindow_end, 0, 2, 0, /* | |
1873 Return position at which display currently ends in WINDOW. | |
1874 This is updated by redisplay, when it runs to completion. | |
444 | 1875 Simply changing the buffer text or setting `window-start' does not |
1876 update this value. WINDOW defaults to the selected window. | |
1877 | |
1878 If optional arg GUARANTEE is non-nil, the return value is guaranteed | |
1879 to be the same value as this function would return at the end of the | |
1880 next full redisplay assuming nothing else changes in the meantime. | |
1881 This function is potentially much slower with this flag set. | |
428 | 1882 */ |
1883 (window, guarantee)) | |
1884 { | |
1885 struct window *w = decode_window (window); | |
1886 | |
1887 if (NILP (guarantee)) | |
1888 { | |
1889 Lisp_Object buf; | |
1890 buf = w->buffer; | |
1891 CHECK_BUFFER (buf); | |
1892 return make_int (BUF_Z (XBUFFER (buf)) - w->window_end_pos[CURRENT_DISP]); | |
1893 } | |
1894 else | |
1895 { | |
665 | 1896 Charbpos startp = marker_position (w->start[CURRENT_DISP]); |
428 | 1897 return make_int (end_of_last_line (w, startp)); |
1898 } | |
1899 } | |
1900 | |
442 | 1901 DEFUN ("window-last-line-visible-height", Fwindow_last_line_visible_height, 0, 1, 0, /* |
1902 Return pixel height of visible part of last window line if it is clipped. | |
1903 If the last line is not clipped, return nil. | |
1904 */ | |
1905 (window)) | |
1906 { | |
1907 struct window *w = decode_window (window); | |
1908 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP); | |
1909 int num_lines = Dynarr_length (dla); | |
1910 struct display_line *dl; | |
1911 | |
1912 /* No lines - no clipped lines */ | |
4967 | 1913 if (num_lines == 0 || (num_lines == 1 && Dynarr_begin (dla)->modeline)) |
442 | 1914 return Qnil; |
1915 | |
1916 dl = Dynarr_atp (dla, num_lines - 1); | |
1917 if (dl->clip == 0) | |
1918 return Qnil; | |
1919 | |
1920 return make_int (dl->ascent + dl->descent - dl->clip); | |
1921 } | |
1922 | |
428 | 1923 DEFUN ("set-window-point", Fset_window_point, 2, 2, 0, /* |
1924 Make point value in WINDOW be at position POS in WINDOW's buffer. | |
1161 | 1925 If WINDOW is the selected window, and window's buffer is the current |
1926 buffer, this actually changes the buffer's point instead of the window's | |
1927 point. (The equivalence of the selected window's point with its buffer's | |
1928 point is maintained throughout XEmacs. However, enforcing the additional | |
1929 restriction on the current buffer is "bug compatible" with FSF and is | |
1930 perhaps more logical.) | |
428 | 1931 */ |
1932 (window, pos)) | |
1933 { | |
1934 struct window *w = decode_window (window); | |
1935 | |
1936 CHECK_INT_COERCE_MARKER (pos); | |
1161 | 1937 |
844 | 1938 /* Don't dereference selected-window because there may not |
1939 be one -- e.g. at startup */ | |
1161 | 1940 if (EQ (wrap_window (w), Fselected_window (Qnil)) |
1941 && EQ (w->buffer, Fcurrent_buffer ())) | |
1942 Fgoto_char (pos, Qnil); | |
428 | 1943 else |
1944 set_marker_restricted (w->pointm[CURRENT_DISP], pos, w->buffer); | |
1945 | |
1946 MARK_POINT_CHANGED; | |
1947 return pos; | |
1948 } | |
1949 | |
1950 DEFUN ("set-window-start", Fset_window_start, 2, 3, 0, /* | |
1951 Make display in WINDOW start at position POS in WINDOW's buffer. | |
1952 Optional third arg NOFORCE non-nil inhibits next redisplay | |
1953 from overriding motion of point in order to display at this exact start. | |
1954 */ | |
1955 (window, pos, noforce)) | |
1956 { | |
1957 struct window *w = decode_window (window); | |
1958 | |
1959 CHECK_INT_COERCE_MARKER (pos); | |
1960 set_marker_restricted (w->start[CURRENT_DISP], pos, w->buffer); | |
1961 /* this is not right, but much easier than doing what is right. */ | |
1962 /* w->start_at_line_beg = 0; */ | |
1963 /* WTF is the above supposed to mean? GE */ | |
1964 w->start_at_line_beg = beginning_of_line_p (XBUFFER (w->buffer), | |
1965 marker_position (w->start[CURRENT_DISP])); | |
1966 if (NILP (noforce)) | |
1967 w->force_start = 1; | |
1968 w->redo_modeline = 1; | |
1969 SET_LAST_MODIFIED (w, 0); | |
1970 SET_LAST_FACECHANGE (w); | |
1971 | |
1972 MARK_WINDOWS_CHANGED (w); | |
1973 | |
1974 return pos; | |
1975 } | |
1976 | |
1977 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, 1, 1, 0, /* | |
1978 Return WINDOW's dedicated object, usually t or nil. | |
1979 See also `set-window-dedicated-p'. | |
1980 */ | |
1981 (window)) | |
1982 { | |
1983 return decode_window (window)->dedicated; | |
1984 } | |
1985 | |
1986 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p, 2, 2, 0, /* | |
1987 Control whether WINDOW is dedicated to the buffer it displays. | |
1988 If it is dedicated, Emacs will not automatically change | |
1989 which buffer appears in it. | |
1990 The second argument is the new value for the dedication flag; | |
1991 non-nil means yes. | |
1992 */ | |
1993 (window, arg)) | |
1994 { | |
1995 struct window *w = decode_window (window); | |
1996 | |
1997 w->dedicated = NILP (arg) ? Qnil : Qt; | |
1998 | |
1999 return w->dedicated; | |
2000 } | |
2001 | |
2002 /* FSFmacs has window-display-table here. We have display table as a | |
2003 specifier. */ | |
2004 | |
2005 | |
2006 /* Record info on buffer window w is displaying | |
2007 when it is about to cease to display that buffer. */ | |
2008 static void | |
2009 unshow_buffer (struct window *w) | |
2010 { | |
2011 Lisp_Object buf = w->buffer; | |
844 | 2012 struct buffer *b = XBUFFER (buf); |
2013 | |
5050
6f2158fa75ed
Fix quick-build, use asserts() in place of ABORT()
Ben Wing <ben@xemacs.org>
parents:
4967
diff
changeset
|
2014 assert (b == XMARKER (w->pointm[CURRENT_DISP])->buffer); |
428 | 2015 |
2016 /* FSF disables this check, so I'll do it too. I hope it won't | |
2017 break things. --ben */ | |
2018 #if 0 | |
2019 if (w == XWINDOW (Fselected_window (Qnil)) | |
2020 || ! EQ (buf, XWINDOW (Fselected_window (Qnil))->buffer)) | |
2021 /* Do this except when the selected window's buffer | |
2022 is being removed from some other window. */ | |
2023 #endif | |
2024 /* last_window_start records the start position that this buffer | |
2025 had in the last window to be disconnected from it. | |
2026 Now that this statement is unconditional, | |
2027 it is possible for the buffer to be displayed in the | |
2028 selected window, while last_window_start reflects another | |
2029 window which was recently showing the same buffer. | |
2030 Some people might say that might be a good thing. Let's see. */ | |
2031 XBUFFER (buf)->last_window_start = | |
2032 marker_position (w->start[CURRENT_DISP]); | |
2033 | |
2034 /* Point in the selected window's buffer | |
2035 is actually stored in that buffer, and the window's pointm isn't used. | |
2036 So don't clobber point in that buffer. */ | |
2037 if (! EQ (buf, XWINDOW (Fselected_window (Qnil))->buffer)) | |
844 | 2038 BUF_SET_PT (b, |
2039 charbpos_clip_to_bounds | |
2040 (BUF_BEGV (b), | |
2041 marker_position (w->pointm[CURRENT_DISP]), | |
2042 BUF_ZV (b))); | |
2043 | |
2044 { | |
2045 Lisp_Object marker = Fgethash (buf, w->saved_point_cache, Qnil); | |
2046 int selected = EQ (wrap_window (w), Fselected_window (Qnil)); | |
2047 | |
2048 if (NILP (marker)) | |
2049 { | |
2050 marker = Fmake_marker (); | |
2051 Fputhash (buf, marker, w->saved_point_cache); | |
2052 } | |
2053 Fset_marker (marker, | |
2054 selected ? make_int (BUF_PT (b)) : w->pointm[CURRENT_DISP], | |
2055 buf); | |
2056 | |
2057 marker = Fgethash (buf, w->saved_last_window_start_cache, Qnil); | |
2058 | |
2059 if (NILP (marker)) | |
2060 { | |
2061 marker = Fmake_marker (); | |
2062 Fputhash (buf, marker, w->saved_last_window_start_cache); | |
2063 } | |
2064 Fset_marker (marker, w->start[CURRENT_DISP], buf); | |
2065 } | |
428 | 2066 } |
2067 | |
2068 /* Put REPLACEMENT into the window structure in place of OLD. */ | |
2069 static void | |
2070 replace_window (Lisp_Object old, Lisp_Object replacement) | |
2071 { | |
2072 Lisp_Object tem; | |
2073 struct window *o = XWINDOW (old), *p = XWINDOW (replacement); | |
2074 | |
2075 /* If OLD is its frame's root_window, then replacement is the new | |
2076 root_window for that frame. */ | |
2077 | |
2078 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame)))) | |
2079 FRAME_ROOT_WINDOW (XFRAME (o->frame)) = replacement; | |
2080 | |
2081 WINDOW_LEFT (p) = WINDOW_LEFT (o); | |
2082 WINDOW_TOP (p) = WINDOW_TOP (o); | |
2083 WINDOW_WIDTH (p) = WINDOW_WIDTH (o); | |
2084 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o); | |
2085 | |
2086 p->next = tem = o->next; | |
2087 if (!NILP (tem)) | |
2088 XWINDOW (tem)->prev = replacement; | |
2089 | |
2090 p->prev = tem = o->prev; | |
2091 if (!NILP (tem)) | |
2092 XWINDOW (tem)->next = replacement; | |
2093 | |
2094 p->parent = tem = o->parent; | |
2095 if (!NILP (tem)) | |
2096 { | |
2097 if (EQ (XWINDOW (tem)->vchild, old)) | |
2098 XWINDOW (tem)->vchild = replacement; | |
2099 if (EQ (XWINDOW (tem)->hchild, old)) | |
2100 XWINDOW (tem)->hchild = replacement; | |
2101 } | |
2102 | |
2103 /* #### Here, if replacement is a vertical combination | |
2104 and so is its new parent, we should make replacement's | |
2105 children be children of that parent instead. */ | |
442 | 2106 |
2107 ERROR_CHECK_SUBWINDOW_CACHE (p); | |
2108 } | |
2109 | |
2110 static void | |
2111 window_unmap_subwindows (struct window* w) | |
2112 { | |
2113 assert (!NILP (w->subwindow_instance_cache)); | |
2114 elisp_maphash (unmap_subwindow_instance_cache_mapper, | |
2115 w->subwindow_instance_cache, (void*)1); | |
428 | 2116 } |
2117 | |
2118 /* we're deleting W; set the structure of W to indicate this. */ | |
2119 | |
2120 static void | |
2121 mark_window_as_deleted (struct window *w) | |
2122 { | |
442 | 2123 /* The window instance cache is going away now, so need to get the |
2124 cachels reset by redisplay. */ | |
2125 MARK_FRAME_SUBWINDOWS_CHANGED (XFRAME (WINDOW_FRAME (w))); | |
2126 | |
2127 /* The cache is going away. If we leave unmapping to | |
2128 reset_subwindow_cachels then we get in a situation where the | |
2129 domain (the window) has been deleted but we still need access to | |
2130 its attributes in order to unmap windows properly. Since the | |
2131 subwindows are going to get GC'd anyway as a result of the domain | |
2132 going away, it is safer to just unmap them all while we know the | |
2133 domain is still valid. */ | |
2134 ERROR_CHECK_SUBWINDOW_CACHE (w); | |
2135 window_unmap_subwindows (w); | |
2136 | |
617 | 2137 /* Free the extra data structures attached to windows immediately so |
2138 they don't sit around consuming excess space. They will be | |
2139 reinitialized by the window-configuration code as necessary. */ | |
5127
a9c41067dd88
more cleanups, terminology clarification, lots of doc work
Ben Wing <ben@xemacs.org>
parents:
5126
diff
changeset
|
2140 finalize_window (wrap_window (w)); |
617 | 2141 |
1149 | 2142 /* Nobody should be accessing anything in this object any more, |
618 | 2143 and making them Qnil allows for better GC'ing in case a pointer |
2144 to the dead window continues to hang around. Zero all other | |
2145 structs in case someone tries to access something through them. | |
2146 | |
2147 (So, in point of fact, we zero out all of the "saved" slots, | |
2148 which are obviously restored from the window config, plus the | |
2149 slots which were already zeroed.) | |
617 | 2150 |
2151 As an example of why setting the values to Qnil is good, here | |
2152 is an old comment: | |
2153 | |
2154 In the loop | |
428 | 2155 (while t (split-window) (delete-window)) |
2156 we end up with a tree of deleted windows which are all connected | |
2157 through the `next' slot. This might not seem so bad, as they're | |
2158 deleted, and will presumably be GCed - but if even *one* of those | |
2159 windows is still being pointed to, by the user, or by a window | |
1149 | 2160 configuration, then *all* of those windows stick around. */ |
617 | 2161 |
618 | 2162 #define WINDOW_SLOT(slot) |
2163 #define WINDOW_SAVED_SLOT(slot, compare) w->slot = Qnil; | |
617 | 2164 #include "winslots.h" |
428 | 2165 |
618 | 2166 w->next = Qnil; |
2167 w->prev = Qnil; | |
2168 w->hchild = Qnil; | |
2169 w->vchild = Qnil; | |
2170 w->parent = Qnil; | |
2171 w->subwindow_instance_cache = Qnil; | |
2172 | |
428 | 2173 w->dead = 1; |
853 | 2174 note_object_deleted (wrap_window (w)); |
428 | 2175 } |
2176 | |
1207 | 2177 /* Check if window contains pwindow. */ |
2178 | |
2179 static int | |
2180 contains_window (Lisp_Object window, Lisp_Object pwindow) | |
2181 { | |
2182 while (!NILP (pwindow)) | |
2183 { | |
2184 if (EQ (window, pwindow)) | |
2185 return 1; | |
2186 pwindow = XWINDOW (pwindow)->parent; | |
2187 } | |
2188 return 0; | |
2189 } | |
2190 | |
428 | 2191 DEFUN ("delete-window", Fdelete_window, 0, 2, "", /* |
2192 Remove WINDOW from the display. Default is selected window. | |
444 | 2193 If window is the only one on its frame, the frame is deleted as well. |
428 | 2194 Normally, you cannot delete the last non-minibuffer-only frame (you must |
2195 use `save-buffers-kill-emacs' or `kill-emacs'). However, if optional | |
2196 second argument FORCE is non-nil, you can delete the last frame. (This | |
2197 will automatically call `save-buffers-kill-emacs'.) | |
2198 */ | |
2199 (window, force)) | |
2200 { | |
2201 /* This function can GC if this is the only window in the frame */ | |
2202 struct window *w; | |
2203 Lisp_Object parent; | |
2204 struct window *par; | |
2205 Lisp_Object frame; | |
2206 struct frame *f; | |
2207 struct device *d; | |
2208 | |
2209 /* Note: this function is called by other C code on non-leaf | |
2210 windows. */ | |
2211 | |
2212 /* Do the equivalent of decode_window() but don't error out on | |
2213 deleted window; it's OK to delete an already-deleted window. */ | |
2214 if (NILP (window)) | |
2215 window = Fselected_window (Qnil); | |
2216 else | |
2217 CHECK_WINDOW (window); | |
442 | 2218 |
428 | 2219 w = XWINDOW (window); |
2220 | |
2221 /* It's okay to delete an already-deleted window. */ | |
2222 if (! WINDOW_LIVE_P (w)) | |
2223 return Qnil; | |
2224 | |
853 | 2225 check_allowed_operation (OPERATION_DELETE_OBJECT, window, Qnil); |
2226 | |
428 | 2227 frame = WINDOW_FRAME (w); |
2228 f = XFRAME (frame); | |
2229 d = XDEVICE (FRAME_DEVICE (f)); | |
2230 | |
2231 if (TOP_LEVEL_WINDOW_P (w)) | |
2232 { | |
2233 if (NILP (memq_no_quit (frame, DEVICE_FRAME_LIST (d)))) | |
2234 /* this frame isn't fully initialized yet; don't blow up. */ | |
2235 return Qnil; | |
2236 | |
2237 if (MINI_WINDOW_P (XWINDOW (window))) | |
563 | 2238 signal_error (Qinvalid_operation, "Attempt to delete the minibuffer window", Qunbound); |
428 | 2239 |
2240 /* It has been suggested that it's a good thing for C-x 0 to have this | |
2241 behavior, but not such a good idea for #'delete-window to have it. | |
2242 Maybe C-x 0 should be bound to something else, or maybe frame | |
2243 deletion should only happen when this is called interactively. | |
2244 */ | |
2245 delete_frame_internal (f, !NILP (force), 0, 0); | |
2246 return Qnil; | |
2247 } | |
2248 | |
2249 /* At this point, we know the window has a parent. */ | |
2250 parent = w->parent; | |
2251 par = XWINDOW (parent); | |
2252 | |
2253 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f); | |
430 | 2254 /* It's quite likely that deleting a window will result in |
2255 subwindows needing to be deleted also (since they are cached | |
2256 per-window). So we mark them as changed, so that the cachels will | |
2257 get reset by redisplay and thus deleted subwindows can get | |
2258 GC'd. */ | |
2259 MARK_FRAME_SUBWINDOWS_CHANGED (f); | |
428 | 2260 |
2261 /* Are we trying to delete any frame's selected window? | |
2262 Note that we could be dealing with a non-leaf window | |
2263 where the selected window is one of our children. | |
2264 So, we check by scanning all the ancestors of the | |
2265 frame's selected window and comparing each one with | |
2266 WINDOW. */ | |
1207 | 2267 if (contains_window (window, FRAME_SELECTED_WINDOW (f))) |
2268 { | |
2269 Lisp_Object alternative; | |
2270 alternative = Fnext_window (window, Qlambda, Qnil, Qnil); | |
2271 | |
2272 /* #### */ | |
2273 /* If we're about to delete the selected window on the | |
2274 selected frame, then we should use Fselect_window to select | |
2275 the new window. On the other hand, if we're about to | |
2276 delete the selected window on any other frame, we shouldn't do | |
2277 anything but set the frame's selected_window slot. */ | |
2278 if (EQ (frame, Fselected_frame (Qnil))) | |
2279 Fselect_window (alternative, Qnil); | |
2280 else | |
2281 set_frame_selected_window (f, alternative); | |
2282 } | |
2283 | |
2284 /* Some display parameters (gutter display specifically) depend on | |
2285 FRAME_LAST_NONMINIBUF (f) to be set to a live window. Ensure that. */ | |
2286 if (contains_window (window, FRAME_LAST_NONMINIBUF_WINDOW (f))) | |
2287 f->last_nonminibuf_window = Fnext_window (window, Qlambda, Qnil, Qnil); | |
428 | 2288 |
2289 /* w->buffer is nil in a non-leaf window; in this case, | |
2290 get rid of the markers we maintain that point into that buffer. */ | |
2291 if (!NILP (w->buffer)) | |
2292 { | |
2293 unshow_buffer (w); | |
2294 unchain_marker (w->pointm[CURRENT_DISP]); | |
2295 unchain_marker (w->pointm[DESIRED_DISP]); | |
2296 unchain_marker (w->pointm[CMOTION_DISP]); | |
2297 unchain_marker (w->start[CURRENT_DISP]); | |
2298 unchain_marker (w->start[DESIRED_DISP]); | |
2299 unchain_marker (w->start[CMOTION_DISP]); | |
2300 unchain_marker (w->sb_point); | |
1149 | 2301 w->buffer = Qnil; |
428 | 2302 } |
2303 | |
2304 /* close up the hole in the sibling list */ | |
2305 if (!NILP (w->next)) | |
2306 XWINDOW (w->next)->prev = w->prev; | |
2307 if (!NILP (w->prev)) | |
2308 XWINDOW (w->prev)->next = w->next; | |
2309 if (EQ (window, par->hchild)) | |
2310 par->hchild = w->next; | |
2311 if (EQ (window, par->vchild)) | |
2312 par->vchild = w->next; | |
2313 | |
2314 /* Find one of our siblings to give our space to. */ | |
2315 { | |
2316 Lisp_Object sib = w->prev; | |
2317 if (NILP (sib)) | |
2318 { | |
2319 /* If w gives its space to its next sibling, that sibling needs | |
2320 to have its top/left side pulled back to where w's is. | |
2321 set_window_{height,width} will re-position the sibling's | |
2322 children. */ | |
2323 sib = w->next; | |
2324 WINDOW_TOP (XWINDOW (sib)) = WINDOW_TOP (w); | |
2325 WINDOW_LEFT (XWINDOW (sib)) = WINDOW_LEFT (w); | |
2326 } | |
2327 | |
2328 /* Stretch that sibling. */ | |
2329 if (!NILP (par->vchild)) | |
2330 set_window_pixheight | |
2331 (sib, (WINDOW_HEIGHT (XWINDOW (sib)) + WINDOW_HEIGHT (w)), 1); | |
2332 if (!NILP (par->hchild)) | |
2333 set_window_pixwidth | |
2334 (sib, (WINDOW_WIDTH (XWINDOW (sib)) + WINDOW_WIDTH (w)), 1); | |
2335 } | |
2336 | |
2337 /* If parent now has only one child, | |
2338 put the child into the parent's place. */ | |
2339 { | |
2340 Lisp_Object parchild = par->hchild; | |
2341 if (NILP (parchild)) | |
2342 parchild = par->vchild; | |
2343 if (NILP (XWINDOW (parchild)->next)) | |
2344 { | |
2345 replace_window (parent, parchild); | |
2346 mark_window_as_deleted (XWINDOW (parent)); | |
2347 } | |
2348 } | |
2349 | |
2350 /* Since we may be deleting combination windows, we must make sure that | |
2351 not only W but all its children have been marked as deleted. */ | |
2352 if (!NILP (w->hchild)) | |
2353 delete_all_subwindows (XWINDOW (w->hchild)); | |
2354 else if (!NILP (w->vchild)) | |
2355 delete_all_subwindows (XWINDOW (w->vchild)); | |
2356 | |
1752 | 2357 /* Warning: mark_window_as_deleted calls window_unmap_subwindows and |
2358 therefore redisplay, so it requires the mirror structure to be | |
2359 correct. We must dirty the mirror before it is called. */ | |
2360 f->mirror_dirty = 1; | |
2361 | |
428 | 2362 mark_window_as_deleted (w); |
2363 | |
2364 return Qnil; | |
2365 } | |
2366 | |
2367 | |
2368 DEFUN ("next-window", Fnext_window, 0, 4, 0, /* | |
442 | 2369 Return the next window after WINDOW in the canonical ordering of windows. |
428 | 2370 If omitted, WINDOW defaults to the selected window. |
2371 | |
2372 Optional second arg MINIBUF t means count the minibuffer window even | |
2373 if not active. MINIBUF nil or omitted means count the minibuffer iff | |
2374 it is active. MINIBUF neither t nor nil means not to count the | |
2375 minibuffer even if it is active. | |
2376 | |
2377 Several frames may share a single minibuffer; if the minibuffer | |
2378 counts, all windows on all frames that share that minibuffer count | |
2379 too. Therefore, `next-window' can be used to iterate through the | |
2380 set of windows even when the minibuffer is on another frame. If the | |
2381 minibuffer does not count, only windows from WINDOW's frame count. | |
2382 | |
444 | 2383 By default, only the windows in the selected frame are considered. |
2384 The optional argument WHICH-FRAMES changes this behavior: | |
2385 WHICH-FRAMES = `visible' means search windows on all visible frames. | |
448 | 2386 WHICH-FRAMES = 0 means search windows on all visible and iconified frames. |
444 | 2387 WHICH-FRAMES = t means search windows on all frames including invisible frames. |
2388 WHICH-FRAMES = a frame means search only windows on that frame. | |
2389 Anything else means restrict to the selected frame. | |
2390 | |
2391 The optional fourth argument WHICH-DEVICES further clarifies on which | |
2392 devices to search for frames as specified by WHICH-FRAMES. This value | |
2393 is only meaningful if WHICH-FRAMES is non-nil. | |
2394 If nil or omitted, search all devices on the selected console. | |
2395 If a device, only search that device. | |
2396 If a console, search all devices on that console. | |
2397 If a device type, search all devices of that type. | |
2398 If `window-system', search all window-system devices. | |
2399 Any other non-nil value means search all devices. | |
2400 | |
2401 If you use consistent values for MINIBUF, WHICH-FRAMES, and WHICH-DEVICES, | |
2402 you can use `next-window' to iterate through the entire cycle of | |
2403 acceptable windows, eventually ending up back at the window you started with. | |
428 | 2404 `previous-window' traverses the same cycle, in the reverse order. |
2405 */ | |
444 | 2406 (window, minibuf, which_frames, which_devices)) |
428 | 2407 { |
2408 Lisp_Object tem; | |
2409 Lisp_Object start_window; | |
2410 | |
2411 if (NILP (window)) | |
2412 window = Fselected_window (Qnil); | |
2413 else | |
2414 CHECK_LIVE_WINDOW (window); | |
2415 | |
2416 start_window = window; | |
2417 | |
2418 /* minibuf == nil may or may not include minibuffers. | |
2419 Decide if it does. */ | |
2420 if (NILP (minibuf)) | |
2421 minibuf = (minibuf_level ? minibuf_window : Qlambda); | |
2422 else if (! EQ (minibuf, Qt)) | |
2423 minibuf = Qlambda; | |
442 | 2424 /* Now `minibuf' is one of: |
2425 t => count all minibuffer windows | |
2426 lambda => count none of them | |
428 | 2427 or a specific minibuffer window (the active one) to count. */ |
2428 | |
444 | 2429 /* which_frames == nil doesn't specify which frames to include. */ |
2430 if (NILP (which_frames)) | |
2431 which_frames = (! EQ (minibuf, Qlambda) | |
428 | 2432 ? (FRAME_MINIBUF_WINDOW |
2433 (XFRAME | |
2434 (WINDOW_FRAME | |
2435 (XWINDOW (window))))) | |
2436 : Qnil); | |
444 | 2437 else if (EQ (which_frames, Qvisible)) |
428 | 2438 ; |
444 | 2439 else if (ZEROP (which_frames)) |
428 | 2440 ; |
444 | 2441 else if (FRAMEP (which_frames) && ! EQ (which_frames, Fwindow_frame (window))) |
2442 /* If which_frames is a frame and window arg isn't on that frame, just | |
428 | 2443 return the first window on the frame. */ |
444 | 2444 return frame_first_window (XFRAME (which_frames)); |
2445 else if (! EQ (which_frames, Qt)) | |
2446 which_frames = Qnil; | |
2447 /* Now `which_frames' is one of: | |
442 | 2448 t => search all frames |
2449 nil => search just the current frame | |
2450 visible => search just visible frames | |
2451 0 => search visible and iconified frames | |
2452 a window => search the frame that window belongs to. */ | |
428 | 2453 |
2454 /* Do this loop at least once, to get the next window, and perhaps | |
2455 again, if we hit the minibuffer and that is not acceptable. */ | |
2456 do | |
2457 { | |
2458 /* Find a window that actually has a next one. This loop | |
2459 climbs up the tree. */ | |
2460 while (tem = XWINDOW (window)->next, NILP (tem)) | |
2461 if (tem = XWINDOW (window)->parent, !NILP (tem)) | |
2462 window = tem; | |
2463 else /* window must be minibuffer window now */ | |
2464 { | |
2465 /* We've reached the end of this frame. | |
2466 Which other frames are acceptable? */ | |
2467 tem = WINDOW_FRAME (XWINDOW (window)); | |
2468 | |
444 | 2469 if (! NILP (which_frames)) |
428 | 2470 { |
442 | 2471 Lisp_Object tem1 = tem; |
444 | 2472 tem = next_frame (tem, which_frames, which_devices); |
442 | 2473 |
428 | 2474 /* In the case where the minibuffer is active, |
2475 and we include its frame as well as the selected one, | |
2476 next_frame may get stuck in that frame. | |
2477 If that happens, go back to the selected frame | |
2478 so we can complete the cycle. */ | |
2479 if (EQ (tem, tem1)) | |
793 | 2480 tem = wrap_frame (selected_frame ()); |
428 | 2481 } |
2482 | |
2483 tem = FRAME_ROOT_WINDOW (XFRAME (tem)); | |
2484 break; | |
2485 } | |
2486 | |
2487 window = tem; | |
2488 | |
2489 /* If we're in a combination window, find its first child and | |
2490 recurse on that. Otherwise, we've found the window we want. */ | |
2491 while (1) | |
2492 { | |
2493 if (!NILP (XWINDOW (window)->hchild)) | |
2494 window = XWINDOW (window)->hchild; | |
2495 else if (!NILP (XWINDOW (window)->vchild)) | |
2496 window = XWINDOW (window)->vchild; | |
2497 else break; | |
2498 } | |
2499 } | |
2500 /* Which windows are acceptable? | |
2501 Exit the loop and accept this window if | |
2502 this isn't a minibuffer window, | |
2503 or we're accepting all minibuffer windows, | |
2504 or this is the active minibuffer and we are accepting that one, or | |
2505 we've come all the way around and we're back at the original window. */ | |
2506 while (MINI_WINDOW_P (XWINDOW (window)) | |
2507 && ! EQ (minibuf, Qt) | |
2508 && ! EQ (minibuf, window) | |
2509 && ! EQ (window, start_window)); | |
2510 | |
2511 return window; | |
2512 } | |
2513 | |
2514 DEFUN ("previous-window", Fprevious_window, 0, 4, 0, /* | |
442 | 2515 Return the window preceding WINDOW in the canonical ordering of windows. |
428 | 2516 If omitted, WINDOW defaults to the selected window. |
2517 | |
2518 Optional second arg MINIBUF t means count the minibuffer window even | |
2519 if not active. MINIBUF nil or omitted means count the minibuffer iff | |
2520 it is active. MINIBUF neither t nor nil means not to count the | |
2521 minibuffer even if it is active. | |
2522 | |
2523 Several frames may share a single minibuffer; if the minibuffer | |
2524 counts, all windows on all frames that share that minibuffer count | |
2525 too. Therefore, `previous-window' can be used to iterate through | |
2526 the set of windows even when the minibuffer is on another frame. If | |
442 | 2527 the minibuffer does not count, only windows from WINDOW's frame count. |
2528 | |
444 | 2529 By default, only the windows in the selected frame are considered. |
2530 The optional argument WHICH-FRAMES changes this behavior: | |
2531 WHICH-FRAMES = `visible' means search windows on all visible frames. | |
448 | 2532 WHICH-FRAMES = 0 means search windows on all visible and iconified frames. |
444 | 2533 WHICH-FRAMES = t means search windows on all frames including invisible frames. |
2534 WHICH-FRAMES = a frame means search only windows on that frame. | |
2535 Anything else means restrict to the selected frame. | |
2536 | |
2537 The optional fourth argument WHICH-DEVICES further clarifies on which | |
2538 devices to search for frames as specified by WHICH-FRAMES. This value | |
2539 is only meaningful if WHICH-FRAMES is non-nil. | |
2540 If nil or omitted, search all devices on the selected console. | |
2541 If a device, only search that device. | |
2542 If a console, search all devices on that console. | |
2543 If a device type, search all devices of that type. | |
2544 If `window-system', search all window-system devices. | |
2545 Any other non-nil value means search all devices. | |
2546 | |
2547 If you use consistent values for MINIBUF, WHICH-FRAMES, and WHICH-DEVICES, | |
2548 you can use `previous-window' to iterate through the entire cycle of | |
2549 acceptable windows, eventually ending up back at the window you started with. | |
428 | 2550 `next-window' traverses the same cycle, in the reverse order. |
2551 */ | |
444 | 2552 (window, minibuf, which_frames, devices)) |
428 | 2553 { |
2554 Lisp_Object tem; | |
2555 Lisp_Object start_window; | |
2556 | |
2557 if (NILP (window)) | |
2558 window = Fselected_window (Qnil); | |
2559 else | |
2560 CHECK_LIVE_WINDOW (window); | |
2561 | |
2562 start_window = window; | |
2563 | |
2564 /* minibuf == nil may or may not include minibuffers. | |
2565 Decide if it does. */ | |
2566 if (NILP (minibuf)) | |
2567 minibuf = (minibuf_level ? minibuf_window : Qlambda); | |
2568 else if (! EQ (minibuf, Qt)) | |
2569 minibuf = Qlambda; | |
442 | 2570 /* Now `minibuf' is one of: |
2571 t => count all minibuffer windows | |
2572 lambda => count none of them | |
428 | 2573 or a specific minibuffer window (the active one) to count. */ |
2574 | |
444 | 2575 /* which_frames == nil doesn't specify which frames to include. |
428 | 2576 Decide which frames it includes. */ |
444 | 2577 if (NILP (which_frames)) |
2578 which_frames = (! EQ (minibuf, Qlambda) | |
428 | 2579 ? (FRAME_MINIBUF_WINDOW |
2580 (XFRAME | |
2581 (WINDOW_FRAME | |
2582 (XWINDOW (window))))) | |
2583 : Qnil); | |
444 | 2584 else if (EQ (which_frames, Qvisible)) |
428 | 2585 ; |
444 | 2586 else if (ZEROP (which_frames)) |
428 | 2587 ; |
444 | 2588 else if (FRAMEP (which_frames) && ! EQ (which_frames, Fwindow_frame (window))) |
2589 /* If which_frames is a frame and window arg isn't on that frame, just | |
428 | 2590 return the first window on the frame. */ |
444 | 2591 return frame_first_window (XFRAME (which_frames)); |
2592 else if (! EQ (which_frames, Qt)) | |
2593 which_frames = Qnil; | |
2594 /* Now `which_frames' is one of: | |
442 | 2595 t => search all frames |
2596 nil => search just the current frame | |
2597 visible => search just visible frames | |
2598 0 => search visible and iconified frames | |
2599 a window => search the frame that window belongs to. */ | |
428 | 2600 |
2601 /* Do this loop at least once, to get the next window, and perhaps | |
2602 again, if we hit the minibuffer and that is not acceptable. */ | |
2603 do | |
2604 { | |
2605 /* Find a window that actually has a next one. This loop | |
2606 climbs up the tree. */ | |
2607 while (tem = XWINDOW (window)->prev, NILP (tem)) | |
2608 if (tem = XWINDOW (window)->parent, !NILP (tem)) | |
2609 window = tem; | |
2610 else /* window must be minibuffer window now */ | |
2611 { | |
2612 /* We have found the top window on the frame. | |
2613 Which frames are acceptable? */ | |
2614 tem = WINDOW_FRAME (XWINDOW (window)); | |
2615 | |
444 | 2616 if (! NILP (which_frames)) |
442 | 2617 /* It's actually important that we use previous_frame here, |
428 | 2618 rather than next_frame. All the windows acceptable |
2619 according to the given parameters should form a ring; | |
2620 Fnext_window and Fprevious_window should go back and | |
2621 forth around the ring. If we use next_frame here, | |
2622 then Fnext_window and Fprevious_window take different | |
2623 paths through the set of acceptable windows. | |
2624 window_loop assumes that these `ring' requirement are | |
2625 met. */ | |
2626 { | |
442 | 2627 Lisp_Object tem1 = tem; |
444 | 2628 tem = previous_frame (tem, which_frames, devices); |
428 | 2629 /* In the case where the minibuffer is active, |
2630 and we include its frame as well as the selected one, | |
2631 next_frame may get stuck in that frame. | |
2632 If that happens, go back to the selected frame | |
2633 so we can complete the cycle. */ | |
2634 if (EQ (tem, tem1)) | |
793 | 2635 tem = wrap_frame (selected_frame ()); |
428 | 2636 } |
2637 | |
2638 /* If this frame has a minibuffer, find that window first, | |
2639 because it is conceptually the last window in that frame. */ | |
2640 if (FRAME_HAS_MINIBUF_P (XFRAME (tem))) | |
2641 tem = FRAME_MINIBUF_WINDOW (XFRAME (tem)); | |
2642 else | |
2643 tem = FRAME_ROOT_WINDOW (XFRAME (tem)); | |
2644 | |
2645 break; | |
2646 } | |
2647 | |
2648 window = tem; | |
2649 | |
2650 /* If we're in a combination window, find its first child and | |
2651 recurse on that. Otherwise, we've found the window we want. */ | |
2652 while (1) | |
2653 { | |
2654 if (!NILP (XWINDOW (window)->hchild)) | |
2655 window = XWINDOW (window)->hchild; | |
2656 else if (!NILP (XWINDOW (window)->vchild)) | |
2657 window = XWINDOW (window)->vchild; | |
2658 else break; | |
2659 while (tem = XWINDOW (window)->next, !NILP (tem)) | |
2660 window = tem; | |
2661 } | |
2662 } | |
2663 /* Which windows are acceptable? | |
2664 Exit the loop and accept this window if | |
2665 this isn't a minibuffer window, | |
2666 or we're accepting all minibuffer windows, | |
2667 or this is the active minibuffer and we are accepting that one, or | |
2668 we've come all the way around and we're back at the original window. */ | |
2669 while (MINI_WINDOW_P (XWINDOW (window)) | |
2670 && ! EQ (minibuf, Qt) | |
2671 && ! EQ (minibuf, window) | |
2672 && ! EQ (window, start_window)); | |
2673 | |
2674 return window; | |
2675 } | |
2676 | |
2677 DEFUN ("next-vertical-window", Fnext_vertical_window, 0, 1, 0, /* | |
2678 Return the next window which is vertically after WINDOW. | |
2679 */ | |
2680 (window)) | |
2681 { | |
2682 Lisp_Object root; | |
2683 struct window *w = decode_window (window); | |
793 | 2684 window = wrap_window (w); |
428 | 2685 |
2686 if (MINI_WINDOW_P (XWINDOW (window))) | |
2687 return Qnil; | |
2688 | |
2689 root = FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (XWINDOW (window)))); | |
2690 | |
2691 if (EQ (window, root)) | |
2692 { | |
2693 while (1) | |
2694 if (!NILP (XWINDOW (window)->hchild)) | |
2695 window = XWINDOW (window)->hchild; | |
2696 else if (!NILP (XWINDOW (window)->vchild)) | |
2697 window = XWINDOW (window)->vchild; | |
2698 else | |
2699 return window; | |
2700 } | |
2701 | |
2702 do | |
2703 { | |
2704 if (!NILP (XWINDOW (window)->parent) && | |
2705 !NILP (XWINDOW (XWINDOW (window)->parent)->vchild)) | |
2706 { | |
2707 if (!NILP (XWINDOW (window)->next)) | |
2708 return XWINDOW (window)->next; | |
2709 else | |
2710 window = XWINDOW (window)->parent; | |
2711 } | |
2712 else | |
2713 window = XWINDOW (window)->parent; | |
2714 } | |
2715 while (!EQ (window, root)); | |
2716 | |
2717 while (1) | |
2718 if (!NILP (XWINDOW (window)->hchild)) | |
2719 window = XWINDOW (window)->hchild; | |
2720 else if (!NILP (XWINDOW (window)->vchild)) | |
2721 window = XWINDOW (window)->vchild; | |
2722 else | |
2723 return window; | |
2724 } | |
2725 | |
2726 DEFUN ("other-window", Fother_window, 1, 3, "p", /* | |
444 | 2727 Select the COUNT'th different window on this frame. |
428 | 2728 All windows on current frame are arranged in a cyclic order. |
444 | 2729 This command selects the window COUNT steps away in that order. |
2730 A negative COUNT moves in the opposite order. | |
2731 | |
2732 By default, only the windows in the selected frame are considered. | |
2733 The optional argument WHICH-FRAMES changes this behavior: | |
2734 WHICH-FRAMES = `visible' means search windows on all visible frames. | |
448 | 2735 WHICH-FRAMES = 0 means search windows on all visible and iconified frames. |
444 | 2736 WHICH-FRAMES = t means search windows on all frames including invisible frames. |
2737 WHICH-FRAMES = a frame means search only windows on that frame. | |
2738 Anything else means restrict to the selected frame. | |
2739 | |
2740 The optional argument WHICH-DEVICES further clarifies on which devices | |
2741 to search for frames as specified by WHICH-FRAMES. This value is only | |
2742 meaningful if WHICH-FRAMES is non-nil. | |
2743 If nil or omitted, search all devices on the selected console. | |
2744 If a device, only search that device. | |
2745 If a console, search all devices on that console. | |
2746 If a device type, search all devices of that type. | |
2747 If `window-system', search all window-system devices. | |
2748 Any other non-nil value means search all devices. | |
428 | 2749 */ |
444 | 2750 (count, which_frames, which_devices)) |
428 | 2751 { |
2752 int i; | |
2753 Lisp_Object w; | |
2754 | |
444 | 2755 CHECK_INT (count); |
428 | 2756 w = Fselected_window (Qnil); |
444 | 2757 i = XINT (count); |
428 | 2758 |
2759 while (i > 0) | |
2760 { | |
444 | 2761 w = Fnext_window (w, Qnil, which_frames, which_devices); |
428 | 2762 i--; |
2763 } | |
2764 while (i < 0) | |
2765 { | |
444 | 2766 w = Fprevious_window (w, Qnil, which_frames, which_devices); |
428 | 2767 i++; |
2768 } | |
2769 Fselect_window (w, Qnil); | |
2770 return Qnil; | |
2771 } | |
2772 | |
2773 | |
2774 /* Look at all windows, performing an operation specified by TYPE | |
2775 with argument OBJ. | |
2776 | |
2777 If FRAMES is Qt, look at all frames, if Qnil, look at just the selected | |
2778 frame. If FRAMES is a frame, just look at windows on that frame. | |
2779 If MINI is non-zero, perform the operation on minibuffer windows too. | |
2780 */ | |
2781 | |
2782 enum window_loop | |
2783 { | |
2784 WINDOW_LOOP_UNUSED, | |
2785 GET_BUFFER_WINDOW, /* Arg is buffer */ | |
2786 GET_LRU_WINDOW, /* Arg is t for full-width windows only */ | |
2787 DELETE_OTHER_WINDOWS, /* Arg is window not to delete */ | |
2788 DELETE_BUFFER_WINDOWS, /* Arg is buffer */ | |
2789 GET_LARGEST_WINDOW, | |
2790 GET_BUFFER_WINDOW_COUNT, /* Arg is buffer */ | |
2791 GET_BUFFER_MRU_WINDOW /* Arg is buffer */ | |
2792 }; | |
2793 | |
2794 static Lisp_Object | |
2795 window_loop (enum window_loop type, | |
2796 Lisp_Object obj, | |
2797 int mini, | |
444 | 2798 Lisp_Object which_frames, |
428 | 2799 int dedicated_too, |
444 | 2800 Lisp_Object which_devices) |
428 | 2801 { |
448 | 2802 /* This function can GC if type == DELETE_BUFFER_WINDOWS */ |
428 | 2803 Lisp_Object w; |
2804 Lisp_Object best_window = Qnil; | |
2805 Lisp_Object next_window; | |
2806 Lisp_Object last_window; | |
2807 struct frame *frame; | |
2808 Lisp_Object frame_arg = Qt; | |
2809 int count = 0; /* for GET_BUFFER_WINDOW_COUNT */ | |
2810 /* #### I think the change of "precomputing" last_window and next_window | |
2811 * #### catch the lossage this is meant(?) to punt on... | |
2812 */ | |
2813 int lose_lose = 0; | |
2814 Lisp_Object devcons, concons; | |
2815 | |
2816 /* If we're only looping through windows on a particular frame, | |
2817 FRAME points to that frame. If we're looping through windows | |
2818 on all frames, FRAME is 0. */ | |
444 | 2819 if (FRAMEP (which_frames)) |
2820 frame = XFRAME (which_frames); | |
2821 else if (NILP (which_frames)) | |
428 | 2822 frame = selected_frame (); |
2823 else | |
2824 frame = 0; | |
442 | 2825 |
2826 /* FRAME_ARG is Qlambda to stick to one frame, | |
2827 Qvisible to consider all visible frames, | |
2828 or Qt otherwise. */ | |
428 | 2829 if (frame) |
2830 frame_arg = Qlambda; | |
444 | 2831 else if (ZEROP (which_frames)) |
2832 frame_arg = which_frames; | |
2833 else if (EQ (which_frames, Qvisible)) | |
2834 frame_arg = which_frames; | |
428 | 2835 |
2836 DEVICE_LOOP_NO_BREAK (devcons, concons) | |
2837 { | |
2838 Lisp_Object device = XCAR (devcons); | |
2839 Lisp_Object the_frame; | |
2840 | |
2841 if (frame) | |
793 | 2842 the_frame = wrap_frame (frame); |
428 | 2843 else |
2844 the_frame = DEVICE_SELECTED_FRAME (XDEVICE (device)); | |
2845 | |
2846 if (NILP (the_frame)) | |
2847 continue; | |
2848 | |
444 | 2849 if (!device_matches_device_spec (device, |
2850 NILP (which_devices) ? | |
2851 FRAME_CONSOLE (XFRAME (the_frame)) : | |
2852 which_devices)) | |
428 | 2853 continue; |
2854 | |
2855 /* Pick a window to start with. */ | |
2856 if (WINDOWP (obj)) | |
2857 w = obj; | |
2858 else | |
2859 w = FRAME_SELECTED_WINDOW (XFRAME (the_frame)); | |
2860 | |
2861 /* Figure out the last window we're going to mess with. Since | |
2862 Fnext_window, given the same options, is guaranteed to go in a | |
2863 ring, we can just use Fprevious_window to find the last one. | |
2864 | |
2865 We can't just wait until we hit the first window again, | |
2866 because it might be deleted. */ | |
2867 | |
707 | 2868 last_window = Fprevious_window (w, mini ? Qt : Qnil, frame_arg, device); |
428 | 2869 |
2870 best_window = Qnil; | |
2871 for (;;) | |
2872 { | |
2873 struct window *p = XWINDOW (w); | |
2874 | |
2875 /* Pick the next window now, since some operations will delete | |
2876 the current window. */ | |
442 | 2877 next_window = Fnext_window (w, mini ? Qt : Qnil, frame_arg, device); |
428 | 2878 |
2879 /* #### Still needed ?? */ | |
2880 /* Given the outstanding quality of the rest of this code, | |
2881 I feel no shame about putting this piece of shit in. */ | |
2882 if (++lose_lose >= 500) | |
707 | 2883 { |
2500 | 2884 /* Call to ABORT() added by Darryl Okahata (16 Nov. 2001), |
707 | 2885 at Ben's request, to catch any remaining bugs. |
2886 | |
2887 If you find that XEmacs is aborting here, and you | |
2888 need to be up and running ASAP, it should be safe to | |
2500 | 2889 comment out the following ABORT(), as long as you |
707 | 2890 leave the "break;" alone. */ |
2500 | 2891 ABORT(); |
707 | 2892 break; /* <--- KEEP THIS HERE! Do not delete! */ |
2893 } | |
428 | 2894 |
2895 /* Note that we do not pay attention here to whether | |
2896 the frame is visible, since Fnext_window skips non-visible frames | |
2897 if that is desired, under the control of frame_arg. */ | |
2898 if (! MINI_WINDOW_P (p) | |
2899 || (mini && minibuf_level > 0)) | |
2900 switch (type) | |
2901 { | |
2902 case GET_BUFFER_WINDOW: | |
2903 { | |
2904 if (XBUFFER (p->buffer) == XBUFFER (obj)) | |
2905 return w; | |
2906 break; | |
2907 } | |
2908 | |
2909 case GET_BUFFER_WINDOW_COUNT: | |
2910 { | |
2911 if (XBUFFER (p->buffer) == XBUFFER (obj)) | |
2912 count++; | |
2913 break; | |
2914 } | |
2915 | |
2916 case GET_LRU_WINDOW: | |
2917 { | |
2918 /* t as arg means consider only full-width windows */ | |
2919 if (!NILP (obj) | |
2920 && !window_full_width_p (p)) | |
2921 break; | |
2922 /* Ignore dedicated windows and minibuffers. */ | |
2923 if (MINI_WINDOW_P (p) | |
2924 || (dedicated_too ? 0 : !NILP (p->dedicated))) | |
2925 break; | |
2926 if (NILP (best_window) | |
2927 || (XINT (XWINDOW (best_window)->use_time) | |
2928 > XINT (p->use_time))) | |
2929 best_window = w; | |
2930 break; | |
2931 } | |
2932 | |
2933 case GET_BUFFER_MRU_WINDOW: | |
2934 { | |
2935 /* #### what about the first check in GET_LRU_WINDOW? */ | |
2936 /* Ignore dedicated windows and minibuffers. */ | |
2937 if (MINI_WINDOW_P (p) | |
2938 || (dedicated_too ? 0 : !NILP (p->dedicated))) | |
2939 break; | |
2940 | |
2941 if (XBUFFER (p->buffer) == XBUFFER (obj)) | |
2942 { | |
2943 if (NILP (best_window) | |
2944 || (XINT (XWINDOW (best_window)->use_time) | |
2945 < XINT (p->use_time))) | |
2946 best_window = w; | |
2947 } | |
2948 break; | |
2949 } | |
2950 | |
2951 case DELETE_OTHER_WINDOWS: | |
2952 { | |
2953 /* Don't delete the last window on a frame; this can | |
2954 happen when the minibuffer is selected, and would | |
2955 cause the frame to be deleted. */ | |
2956 if (p != XWINDOW (obj) && !TOP_LEVEL_WINDOW_P (XWINDOW (w))) | |
2957 Fdelete_window (w, Qnil); | |
2958 break; | |
2959 } | |
2960 | |
2961 case DELETE_BUFFER_WINDOWS: | |
2962 { | |
2963 if (EQ (p->buffer, obj)) | |
2964 { | |
2965 struct frame *f = XFRAME (WINDOW_FRAME (p)); | |
2966 | |
2967 /* If this window is dedicated, and in a frame | |
2968 of its own, kill the frame. */ | |
2969 if (EQ (w, FRAME_ROOT_WINDOW (f)) | |
2970 && !NILP (p->dedicated) | |
1979 | 2971 && (allow_deletion_of_last_visible_frame |
2972 || other_visible_frames (f))) | |
428 | 2973 { |
2974 /* Skip the other windows on this frame. | |
2975 There might be one, the minibuffer! */ | |
2976 if (! EQ (w, last_window)) | |
2977 while (f == XFRAME (WINDOW_FRAME | |
2978 (XWINDOW (next_window)))) | |
2979 { | |
2980 /* As we go, check for the end of the | |
2981 loop. We mustn't start going | |
2982 around a second time. */ | |
2983 if (EQ (next_window, last_window)) | |
2984 { | |
2985 last_window = w; | |
2986 break; | |
2987 } | |
2988 next_window = Fnext_window (next_window, | |
2989 mini ? Qt : Qnil, | |
2990 frame_arg, Qt); | |
2991 } | |
2992 /* Now we can safely delete the frame. */ | |
2993 Fdelete_frame (WINDOW_FRAME (p), Qnil); | |
2994 } | |
2995 else | |
2996 /* If we're deleting the buffer displayed in | |
2997 the only window on the frame, find a new | |
2998 buffer to display there. */ | |
2999 if (NILP (p->parent)) | |
3000 { | |
3001 Lisp_Object new_buffer; | |
3002 new_buffer = Fother_buffer (obj, Qnil, Qnil); | |
3003 if (NILP (new_buffer)) | |
3004 new_buffer = Fget_buffer_create (QSscratch); | |
440 | 3005 Fset_window_buffer (w, new_buffer, Qnil); |
428 | 3006 if (EQ (w, Fselected_window (Qnil))) |
3007 Fset_buffer (p->buffer); | |
3008 } | |
3009 else | |
3010 Fdelete_window (w, Qnil); | |
3011 } | |
3012 break; | |
3013 } | |
3014 | |
3015 case GET_LARGEST_WINDOW: | |
3016 { | |
3017 /* Ignore dedicated windows and minibuffers. */ | |
3018 if (MINI_WINDOW_P (p) | |
3019 || (dedicated_too ? 0 : !NILP (p->dedicated))) | |
3020 break; | |
3021 { | |
3022 /* write the check as follows to avoid tripping | |
3023 error_check_window() --ben */ | |
3024 struct window *b = NILP (best_window) ? 0 : | |
3025 XWINDOW (best_window); | |
3026 if (NILP (best_window) | |
3027 || ((WINDOW_HEIGHT (p) * WINDOW_WIDTH (p)) | |
3028 > (WINDOW_HEIGHT (b) * WINDOW_WIDTH (b)))) | |
3029 best_window = w; | |
3030 } | |
3031 break; | |
3032 } | |
3033 | |
3034 default: | |
2500 | 3035 ABORT (); |
428 | 3036 } |
3037 | |
3038 if (EQ (w, last_window)) | |
3039 break; | |
3040 | |
3041 w = next_window; | |
3042 } | |
3043 } | |
3044 | |
3045 return type == GET_BUFFER_WINDOW_COUNT ? make_int (count) : best_window; | |
3046 } | |
3047 | |
3048 #if 0 /* not currently used */ | |
3049 | |
3050 int | |
3051 buffer_window_count (struct buffer *b, struct frame *f) | |
3052 { | |
3053 Lisp_Object buffer, frame; | |
3054 | |
793 | 3055 frame = wrap_frame (f); |
3056 buffer = wrap_buffer (b); | |
428 | 3057 |
3058 return XINT (window_loop (GET_BUFFER_WINDOW_COUNT, buffer, 0, frame, 1, | |
3059 Qnil)); | |
3060 } | |
3061 | |
3062 int | |
3063 buffer_window_mru (struct window *w) | |
3064 { | |
3065 Lisp_Object window = | |
3066 window_loop (GET_BUFFER_MRU_WINDOW, w->buffer, 0, w->frame, 1, Qnil); | |
3067 | |
3068 if (NILP (window)) | |
3069 return 0; | |
3070 else if (XWINDOW (window) == w) | |
3071 return 1; | |
3072 else | |
3073 return 0; | |
3074 } | |
3075 | |
3076 #endif | |
3077 | |
3078 | |
3079 DEFUN ("get-lru-window", Fget_lru_window, 0, 2, 0, /* | |
3080 Return the window least recently selected or used for display. | |
444 | 3081 |
3082 By default, only the windows in the selected frame are considered. | |
3083 The optional argument WHICH-FRAMES changes this behavior: | |
3084 If optional argument WHICH-FRAMES is `visible', search all visible frames. | |
3085 If WHICH-FRAMES is 0, search all visible and iconified frames. | |
3086 If WHICH-FRAMES is t, search all frames. | |
3087 If WHICH-FRAMES is nil, search only the selected frame. | |
3088 If WHICH-FRAMES is a frame, search only that frame. | |
3089 | |
3090 The optional argument WHICH-DEVICES further clarifies on which devices | |
3091 to search for frames as specified by WHICH-FRAMES. This value is only | |
3092 meaningful if WHICH-FRAMES is non-nil. | |
3093 If nil or omitted, search all devices on the selected console. | |
3094 If a device, only search that device. | |
3095 If a console, search all devices on that console. | |
3096 If a device type, search all devices of that type. | |
3097 If `window-system', search all devices on window-system consoles. | |
3098 Any other non-nil value means search all devices. | |
428 | 3099 */ |
444 | 3100 (which_frames, which_devices)) |
428 | 3101 { |
3102 Lisp_Object w; | |
3103 /* First try for a non-dedicated window that is full-width */ | |
444 | 3104 w = window_loop (GET_LRU_WINDOW, Qt, 0, which_frames, 0, which_devices); |
428 | 3105 if (!NILP (w) && !EQ (w, Fselected_window (Qnil))) |
3106 return w; | |
3107 | |
3108 /* Then try for any non-dedicated window */ | |
444 | 3109 w = window_loop (GET_LRU_WINDOW, Qnil, 0, which_frames, 0, which_devices); |
428 | 3110 if (!NILP (w) && !EQ (w, Fselected_window (Qnil))) |
3111 return w; | |
3112 | |
3113 #if 0 | |
3114 /* FSFmacs never returns a dedicated window here. If we do, | |
3115 it makes `display-buffer' not work right. #### All of this | |
3116 shit is so disgusting and awful that it needs to be rethought | |
3117 from scratch. */ | |
3118 /* then try for a dedicated window that is full-width */ | |
444 | 3119 w = window_loop (GET_LRU_WINDOW, Qt, 0, which_frames, 1, which_devices); |
428 | 3120 if (!NILP (w) && !EQ (w, Fselected_window (Qnil))) |
3121 return w; | |
3122 | |
3123 /* If none of them, then all windows, dedicated or not. */ | |
444 | 3124 w = window_loop (GET_LRU_WINDOW, Qnil, 0, which_frames, 1, which_devices); |
428 | 3125 |
3126 /* At this point we damn well better have found something. */ | |
5050
6f2158fa75ed
Fix quick-build, use asserts() in place of ABORT()
Ben Wing <ben@xemacs.org>
parents:
4967
diff
changeset
|
3127 assert (!NILP (w)); |
428 | 3128 #endif |
3129 | |
3130 return w; | |
3131 } | |
3132 | |
3133 DEFUN ("get-largest-window", Fget_largest_window, 0, 2, 0, /* | |
3134 Return the window largest in area. | |
444 | 3135 |
3136 By default, only the windows in the selected frame are considered. | |
3137 The optional argument WHICH-FRAMES changes this behavior: | |
3138 If optional argument WHICH-FRAMES is `visible', search all visible frames. | |
3139 If WHICH-FRAMES is 0, search all visible and iconified frames. | |
3140 If WHICH-FRAMES is t, search all frames. | |
3141 If WHICH-FRAMES is nil, search only the selected frame. | |
3142 If WHICH-FRAMES is a frame, search only that frame. | |
3143 | |
3144 The optional argument WHICH-DEVICES further clarifies on which devices | |
3145 to search for frames as specified by WHICH-FRAMES. This value is only | |
3146 meaningful if WHICH-FRAMES is non-nil. | |
3147 If nil or omitted, search all devices on the selected console. | |
3148 If a device, only search that device. | |
3149 If a console, search all devices on that console. | |
3150 If a device type, search all devices of that type. | |
3151 If `window-system', search all devices on window-system consoles. | |
3152 Any other non-nil value means search all devices. | |
428 | 3153 */ |
444 | 3154 (which_frames, which_devices)) |
428 | 3155 { |
3156 /* Don't search dedicated windows because FSFmacs doesn't. | |
3157 This stuff is all black magic so don't try to apply common | |
3158 sense to it. */ | |
444 | 3159 return window_loop (GET_LARGEST_WINDOW, Qnil, 0, |
3160 which_frames, 0, which_devices); | |
428 | 3161 } |
3162 | |
3163 DEFUN ("get-buffer-window", Fget_buffer_window, 1, 3, 0, /* | |
3164 Return a window currently displaying BUFFER, or nil if none. | |
444 | 3165 |
3166 By default, only the windows in the selected frame are considered. | |
3167 The optional argument WHICH-FRAMES changes this behavior: | |
3168 If optional argument WHICH-FRAMES is `visible', search all visible frames. | |
3169 If WHICH-FRAMES is 0, search all visible and iconified frames. | |
3170 If WHICH-FRAMES is t, search all frames. | |
3171 If WHICH-FRAMES is nil, search only the selected frame. | |
3172 If WHICH-FRAMES is a frame, search only that frame. | |
3173 | |
3174 The optional argument WHICH-DEVICES further clarifies on which devices | |
3175 to search for frames as specified by WHICH-FRAMES. This value is only | |
3176 meaningful if WHICH-FRAMES is non-nil. | |
3177 If nil or omitted, search all devices on the selected console. | |
3178 If a device, only search that device. | |
3179 If a console, search all devices on that console. | |
3180 If a device type, search all devices of that type. | |
3181 If `window-system', search all devices on window-system consoles. | |
3182 Any other non-nil value means search all devices. | |
428 | 3183 */ |
444 | 3184 (buffer, which_frames, which_devices)) |
428 | 3185 { |
3186 buffer = Fget_buffer (buffer); | |
3187 if (BUFFERP (buffer)) | |
3188 /* Search dedicated windows too. (Doesn't matter here anyway.) */ | |
444 | 3189 return window_loop (GET_BUFFER_WINDOW, buffer, 1, |
3190 which_frames, 1, which_devices); | |
428 | 3191 else |
3192 return Qnil; | |
3193 } | |
3194 | |
3195 /* These functions used to be `buffer-left-margin-pixel-width', etc. | |
3196 but there is no sensible way to implement those functions, since | |
3197 you can't in general derive a window from a buffer. */ | |
3198 | |
3199 DEFUN ("window-left-margin-pixel-width", Fwindow_left_margin_pixel_width, | |
3200 0, 1, 0, /* | |
3201 Return the width in pixels of the left outside margin of window WINDOW. | |
3202 If WINDOW is nil, the selected window is assumed. | |
3203 */ | |
3204 (window)) | |
3205 { | |
3206 return make_int (window_left_margin_width (decode_window (window))); | |
3207 } | |
3208 | |
3209 DEFUN ("window-right-margin-pixel-width", Fwindow_right_margin_pixel_width, | |
3210 0, 1, 0, /* | |
3211 Return the width in pixels of the right outside margin of window WINDOW. | |
3212 If WINDOW is nil, the selected window is assumed. | |
3213 */ | |
3214 (window)) | |
3215 { | |
3216 return make_int (window_right_margin_width (decode_window (window))); | |
3217 } | |
3218 | |
3219 DEFUN ("delete-other-windows", Fdelete_other_windows, 0, 1, "", /* | |
3220 Make WINDOW (or the selected window) fill its frame. | |
3221 Only the frame WINDOW is on is affected. | |
3222 This function tries to reduce display jumps | |
3223 by keeping the text previously visible in WINDOW | |
3224 in the same place on the frame. Doing this depends on | |
3225 the value of (window-start WINDOW), so if calling this function | |
3226 in a program gives strange scrolling, make sure the window-start | |
3227 value is reasonable when this function is called. | |
3228 */ | |
3229 (window)) | |
3230 { | |
3231 struct window *w = decode_window (window); | |
1207 | 3232 struct buffer *b; |
665 | 3233 Charbpos start_pos; |
428 | 3234 int old_top = WINDOW_TOP (w); |
3235 | |
1207 | 3236 if (NILP (WINDOW_BUFFER (w))) |
3237 invalid_operation ("Can't delete other windows of combination", window); | |
3238 | |
793 | 3239 window = wrap_window (w); |
1207 | 3240 b = XBUFFER (WINDOW_BUFFER (w)); |
428 | 3241 |
3242 if (MINI_WINDOW_P (w) && old_top > 0) | |
563 | 3243 invalid_operation ("Can't expand minibuffer to full frame", Qunbound); |
428 | 3244 |
3245 /* Ignore dedicated windows. */ | |
3246 window_loop (DELETE_OTHER_WINDOWS, window, 0, w->frame, 0, Qnil); | |
3247 | |
3248 start_pos = marker_position (w->start[CURRENT_DISP]); | |
3249 | |
3250 /* Try to minimize scrolling, by setting the window start to the | |
3251 point which will cause the text at the old window start to be at | |
3252 the same place on the frame. But don't try to do this if the | |
3253 window start is outside the visible portion (as might happen when | |
3254 the display is not current, due to typeahead). */ | |
3255 if (start_pos >= BUF_BEGV (b) && start_pos <= BUF_ZV (b) | |
3256 && !MINI_WINDOW_P (w)) | |
3257 { | |
665 | 3258 Charbpos new_start = start_with_line_at_pixpos (w, start_pos, old_top); |
428 | 3259 |
3260 if (new_start >= BUF_BEGV (b) && new_start <= BUF_ZV (b)) | |
3261 { | |
3262 Fset_marker (w->start[CURRENT_DISP], make_int (new_start), | |
3263 w->buffer); | |
3264 w->start_at_line_beg = beginning_of_line_p (b, new_start); | |
3265 } | |
3266 /* We need to do this, so that the window-scroll-functions | |
3267 get called. */ | |
3268 w->force_start = 1; | |
3269 } | |
3270 | |
3271 return Qnil; | |
3272 } | |
3273 | |
3274 DEFUN ("delete-windows-on", Fdelete_windows_on, 1, 3, | |
3275 "bDelete windows on (buffer): ", /* | |
3276 Delete all windows showing BUFFER. | |
444 | 3277 |
3278 Optional second argument WHICH-FRAMES controls which frames are affected. | |
428 | 3279 If nil or omitted, delete all windows showing BUFFER in any frame. |
3280 If t, delete only windows showing BUFFER in the selected frame. | |
3281 If `visible', delete all windows showing BUFFER in any visible frame. | |
3282 If a frame, delete only windows showing BUFFER in that frame. | |
444 | 3283 Warning: WHICH-FRAMES has the same meaning as with `next-window', |
3284 except that the meanings of nil and t are reversed. | |
3285 | |
3286 The optional third argument WHICH-DEVICES further clarifies on which | |
3287 devices to search for frames as specified by WHICH-FRAMES. This value | |
3288 is only meaningful if WHICH-FRAMES is not t. | |
3289 If nil or omitted, search only the selected console. | |
3290 If a device, only search that device. | |
3291 If a console, search all devices on that console. | |
3292 If a device type, search all devices of that type. | |
3293 If `window-system', search all devices on a window system. | |
3294 Any other non-nil value means search all devices. | |
428 | 3295 */ |
444 | 3296 (buffer, which_frames, which_devices)) |
428 | 3297 { |
3298 /* This function can GC */ | |
444 | 3299 buffer = Fget_buffer (buffer); |
3300 CHECK_BUFFER (buffer); | |
3301 | |
3302 /* WHICH-FRAMES values t and nil mean the opposite of what | |
3303 window_loop expects. */ | |
3304 if (EQ (which_frames, Qnil)) | |
3305 which_frames = Qt; | |
3306 else if (EQ (which_frames, Qt)) | |
3307 which_frames = Qnil; | |
3308 | |
3309 /* Ignore dedicated windows. */ | |
3310 window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, | |
3311 which_frames, 0, which_devices); | |
428 | 3312 return Qnil; |
3313 } | |
3314 | |
448 | 3315 static Lisp_Object |
3316 list_windows (struct window *w, Lisp_Object value) | |
3317 { | |
3318 for (;;) | |
3319 { | |
3320 if (!NILP (w->hchild)) | |
3321 value = list_windows (XWINDOW (w->hchild), value); | |
3322 else if (!NILP (w->vchild)) | |
3323 value = list_windows (XWINDOW (w->vchild), value); | |
3324 else | |
3325 { | |
793 | 3326 Lisp_Object window = wrap_window (w); |
3327 | |
448 | 3328 value = Fcons (window, value); |
3329 } | |
3330 if (NILP (w->next)) | |
3331 break; | |
3332 w = XWINDOW (w->next); | |
3333 } | |
3334 return value; | |
3335 } | |
3336 | |
3337 static Lisp_Object | |
3338 list_all_windows (Lisp_Object frame_spec, Lisp_Object device_spec) | |
3339 { | |
3340 Lisp_Object devcons, concons; | |
3341 Lisp_Object retval = Qnil; | |
3342 | |
3343 DEVICE_LOOP_NO_BREAK (devcons, concons) | |
3344 { | |
3345 Lisp_Object frame_list, the_window; | |
3346 Lisp_Object device, tail; | |
3347 | |
3348 device = XCAR (devcons); | |
3349 frame_list = DEVICE_FRAME_LIST (XDEVICE (device)); | |
3350 | |
3351 LIST_LOOP (tail, frame_list) | |
3352 { | |
3353 if ((NILP (frame_spec) | |
3354 && !EQ (XCAR (tail), DEVICE_SELECTED_FRAME (XDEVICE (device)))) | |
3355 || (EQ (frame_spec, Qvisible) | |
3356 && !FRAME_VISIBLE_P (XFRAME (XCAR (tail)))) | |
3357 || (FRAMEP (frame_spec) | |
3358 && !EQ (frame_spec, XCAR (tail))) | |
3359 || (!NILP (frame_spec) | |
3360 && !device_matches_device_spec (device, | |
3361 NILP (device_spec) ? | |
3362 Vselected_console : | |
3363 device_spec))) | |
3364 continue; | |
3365 the_window = FRAME_ROOT_WINDOW (XFRAME (XCAR (tail))); | |
3366 retval = list_windows (XWINDOW (the_window), retval); | |
3367 } | |
3368 } | |
3369 return Fnreverse (retval); | |
3370 } | |
3371 | |
444 | 3372 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows, 1, 3, |
428 | 3373 "bReplace buffer in windows: ", /* |
3374 Replace BUFFER with some other buffer in all windows showing it. | |
444 | 3375 |
3376 Optional second argument WHICH-FRAMES controls which frames are affected. | |
3377 If nil or omitted, all frames are affected. | |
3378 If t, only the selected frame is affected. | |
3379 If `visible', all visible frames are affected. | |
3380 If a frame, only that frame is affected. | |
3381 Warning: WHICH-FRAMES has the same meaning as with `next-window', | |
3382 except that the meanings of nil and t are reversed. | |
3383 | |
3384 The optional third argument WHICH-DEVICES further clarifies on which | |
3385 devices to search for frames as specified by WHICH-FRAMES. This value | |
3386 is only meaningful if WHICH-FRAMES is not t. | |
3387 If nil or omitted, search only the selected console. | |
3388 If a device, only search that device. | |
3389 If a console, search all devices on that console. | |
3390 If a device type, search all devices of that type. | |
3391 If `window-system', search all devices on a window system. | |
3392 Any other non-nil value means search all devices. | |
428 | 3393 */ |
444 | 3394 (buffer, which_frames, which_devices)) |
428 | 3395 { |
3396 /* This function can GC */ | |
448 | 3397 Lisp_Object window_list; |
3398 Lisp_Object tail; | |
3399 struct gcpro gcpro1, gcpro2; | |
3400 | |
444 | 3401 if (EQ (which_frames, Qnil)) |
3402 which_frames = Qt; | |
3403 else if (EQ (which_frames, Qt)) | |
3404 which_frames = Qnil; | |
448 | 3405 window_list = list_all_windows (which_frames, which_devices); |
3406 | |
3407 buffer = Fget_buffer (buffer); | |
3408 CHECK_BUFFER (buffer); | |
3409 | |
3410 GCPRO2 (window_list, buffer); | |
3411 LIST_LOOP (tail, window_list) | |
3412 { | |
3413 Lisp_Object window = XCAR (tail); | |
3414 if (!MINI_WINDOW_P (XWINDOW (window)) | |
3415 && EQ (XWINDOW (window)->buffer, buffer)) | |
3416 { | |
3417 Lisp_Object another_buffer = Fother_buffer (buffer, Qnil, Qnil); | |
3418 Lisp_Object frame = WINDOW_FRAME (XWINDOW (window)); | |
3419 if (NILP (another_buffer)) | |
3420 another_buffer = Fget_buffer_create (QSscratch); | |
3421 if (!NILP (XWINDOW (window)->dedicated) | |
3422 && EQ (window, | |
3423 FRAME_ROOT_WINDOW (XFRAME (frame))) | |
1979 | 3424 && (allow_deletion_of_last_visible_frame |
3425 || other_visible_frames (XFRAME (frame)))) | |
448 | 3426 { |
3427 delete_frame_internal (XFRAME (frame), 0, 0, 0); /* GC */ | |
3428 } | |
3429 else | |
3430 { | |
3431 Fset_window_buffer (window, another_buffer, Qnil); | |
3432 if (EQ (window, Fselected_window (Qnil))) | |
3433 Fset_buffer (XWINDOW (window)->buffer); | |
3434 } | |
3435 } | |
3436 } | |
3437 UNGCPRO; | |
428 | 3438 return Qnil; |
3439 } | |
3440 | |
3441 /* The smallest acceptable dimensions for a window. Anything smaller | |
3442 might crash Emacs. */ | |
3443 #define MIN_SAFE_WINDOW_WIDTH (2) | |
3444 #define MIN_SAFE_WINDOW_HEIGHT (2) | |
3445 | |
3446 /* Make sure that window_min_height and window_min_width are | |
3447 not too small; if they are, set them to safe minima. */ | |
3448 | |
3449 static void | |
3450 check_min_window_sizes (void) | |
3451 { | |
3452 /* Smaller values might permit a crash. */ | |
3453 if (window_min_width < MIN_SAFE_WINDOW_WIDTH) | |
3454 window_min_width = MIN_SAFE_WINDOW_WIDTH; | |
3455 if (window_min_height < MIN_SAFE_WINDOW_HEIGHT) | |
3456 window_min_height = MIN_SAFE_WINDOW_HEIGHT; | |
3457 } | |
3458 | |
440 | 3459 static int |
3460 frame_min_height (struct frame *frame) | |
3461 { | |
3462 /* For height, we have to see whether the frame has a minibuffer, and | |
3463 whether it wants a modeline. */ | |
3464 return (FRAME_MINIBUF_ONLY_P (frame) ? MIN_SAFE_WINDOW_HEIGHT - 1 | |
3465 : (! FRAME_HAS_MINIBUF_P (frame)) ? MIN_SAFE_WINDOW_HEIGHT | |
3466 : 2 * MIN_SAFE_WINDOW_HEIGHT - 1); | |
3467 } | |
3468 | |
3469 /* Return non-zero if both frame sizes are less than or equal to | |
3470 minimal allowed values. ROWS and COLS are in characters */ | |
5047
07dcc7000bbf
put width before height consistently, fix a real bug found in the process
Ben Wing <ben@xemacs.org>
parents:
5043
diff
changeset
|
3471 static int |
07dcc7000bbf
put width before height consistently, fix a real bug found in the process
Ben Wing <ben@xemacs.org>
parents:
5043
diff
changeset
|
3472 frame_size_valid_p (struct frame *frame, int cols, int rows) |
440 | 3473 { |
3474 return (rows >= frame_min_height (frame) | |
3475 && cols >= MIN_SAFE_WINDOW_WIDTH); | |
3476 } | |
3477 | |
3478 /* Return non-zero if both frame sizes are less than or equal to | |
3479 minimal allowed values. WIDTH and HEIGHT are in pixels */ | |
3480 int | |
3481 frame_pixsize_valid_p (struct frame *frame, int width, int height) | |
3482 { | |
3483 int rows, cols; | |
5043 | 3484 pixel_to_char_size (frame, width, height, &cols, &rows); |
5047
07dcc7000bbf
put width before height consistently, fix a real bug found in the process
Ben Wing <ben@xemacs.org>
parents:
5043
diff
changeset
|
3485 return frame_size_valid_p (frame, cols, rows); |
440 | 3486 } |
3487 | |
428 | 3488 /* If *ROWS or *COLS are too small a size for FRAME, set them to the |
3489 minimum allowable size. */ | |
3490 void | |
5047
07dcc7000bbf
put width before height consistently, fix a real bug found in the process
Ben Wing <ben@xemacs.org>
parents:
5043
diff
changeset
|
3491 check_frame_size (struct frame *frame, int *cols, int *rows) |
428 | 3492 { |
440 | 3493 int min_height = frame_min_height (frame); |
5043 | 3494 int min_pixwidth, min_pixheight; |
3495 int min_geomwidth, min_geomheight; | |
3496 | |
3497 /* There is no char_to_frame_unit_size(). This can be done with | |
3498 frame_conversion_internal(), but that's currently static, and we can | |
3499 do it fine with two steps, as follows. */ | |
3500 char_to_pixel_size (frame, MIN_SAFE_WINDOW_WIDTH, min_height, | |
3501 &min_pixwidth, &min_pixheight); | |
3502 pixel_to_frame_unit_size (frame, min_pixwidth, min_pixheight, | |
3503 &min_geomwidth, &min_geomheight); | |
3504 if (*rows < min_geomheight) | |
3505 *rows = min_geomheight; | |
3506 if (*cols < min_geomwidth) | |
3507 *cols = min_geomwidth; | |
428 | 3508 } |
3509 | |
3510 /* Normally the window is deleted if it gets too small. | |
3511 nodelete nonzero means do not do this. | |
3512 (The caller should check later and do so if appropriate) */ | |
3513 static void | |
3514 set_window_pixsize (Lisp_Object window, int new_pixsize, int nodelete, | |
3515 int set_height) | |
3516 { | |
3517 struct window *w = XWINDOW (window); | |
3518 struct frame *f = XFRAME (w->frame); | |
3519 struct window *c; | |
3520 int old_pixsize = (set_height ? WINDOW_HEIGHT (w) : WINDOW_WIDTH (w)); | |
3521 Lisp_Object child, minor_kid, major_kid; | |
3522 int minsize; | |
3523 int line_size; | |
3524 int defheight, defwidth; | |
3525 | |
5047
07dcc7000bbf
put width before height consistently, fix a real bug found in the process
Ben Wing <ben@xemacs.org>
parents:
5043
diff
changeset
|
3526 default_face_width_and_height (window, &defwidth, &defheight); |
428 | 3527 line_size = (set_height ? defheight : defwidth); |
3528 | |
3529 check_min_window_sizes (); | |
3530 | |
3531 minsize = (set_height ? window_min_height : window_min_width); | |
3532 minsize *= line_size; | |
3533 | |
3534 if (!nodelete | |
3535 && !TOP_LEVEL_WINDOW_P (w) | |
4375
74e0e1131e01
Update window-size computation.
Mike Sperber <sperber@deinprogramm.de>
parents:
3707
diff
changeset
|
3536 && (new_pixsize + window_modeline_height (w)) < minsize) |
428 | 3537 { |
3538 Fdelete_window (window, Qnil); | |
3539 return; | |
3540 } | |
3541 | |
3542 SET_LAST_MODIFIED (w, 0); | |
3543 SET_LAST_FACECHANGE (w); | |
3544 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f); /* multiple windows affected */ | |
3545 if (set_height) | |
3546 { | |
3547 WINDOW_HEIGHT (w) = new_pixsize; | |
3548 major_kid = w->vchild; | |
3549 minor_kid = w->hchild; | |
3550 } | |
3551 else | |
3552 { | |
3553 WINDOW_WIDTH (w) = new_pixsize; | |
3554 major_kid = w->hchild; | |
3555 minor_kid = w->vchild; | |
3556 } | |
3557 | |
3558 if (!NILP (minor_kid)) | |
3559 { | |
3560 for (child = minor_kid; !NILP (child); child = XWINDOW (child)->next) | |
3561 { | |
3562 if (set_height) | |
3563 WINDOW_TOP (XWINDOW (child)) = WINDOW_TOP (w); | |
3564 else | |
3565 WINDOW_LEFT (XWINDOW (child)) = WINDOW_LEFT (w); | |
3566 | |
3567 set_window_pixsize (child, new_pixsize, nodelete, set_height); | |
3568 } | |
3569 } | |
3570 else if (!NILP (major_kid)) | |
3571 { | |
3572 int last_pos, last_old_pos, pos, old_pos, first; | |
3573 int pixel_adj_left = new_pixsize - old_pixsize; | |
3574 int div_val = old_pixsize << 1; | |
3575 | |
3576 /* | |
3577 * Previously we bailed out here if there was no size change. | |
3578 * (pixel_adj_left == 0) But this broke toolbar updates. If a | |
3579 * toolbar appears or disappears, windows may not change size, | |
3580 * but their top and left coordinates need to be updated. | |
3581 * | |
3582 * So we don't bail until after the loop below. | |
3583 */ | |
3584 | |
3585 last_pos = first = (set_height ? WINDOW_TOP (w) : WINDOW_LEFT (w)); | |
3586 last_old_pos = 0; | |
3587 | |
3588 for (child = major_kid; !NILP (child); child = c->next) | |
3589 { | |
3590 c = XWINDOW (child); | |
3591 | |
3592 if (set_height) | |
3593 { | |
3594 old_pos = last_old_pos + WINDOW_HEIGHT (c); | |
3595 WINDOW_TOP (c) = last_pos; | |
3596 } | |
3597 else | |
3598 { | |
3599 old_pos = last_old_pos + WINDOW_WIDTH (c); | |
3600 WINDOW_LEFT (c) = last_pos; | |
3601 } | |
3602 | |
3603 pos = (((old_pos * new_pixsize) << 1) + old_pixsize) / div_val; | |
3604 /* All but the last window should have a height which is | |
3605 a multiple of the default line height. */ | |
3606 if (!NILP (c->next)) | |
4446
c32b3d10c56b
Fix problem with `resize-minibuffer-mode'.
Mike Sperber <sperber@deinprogramm.de>
parents:
4375
diff
changeset
|
3607 { |
c32b3d10c56b
Fix problem with `resize-minibuffer-mode'.
Mike Sperber <sperber@deinprogramm.de>
parents:
4375
diff
changeset
|
3608 /* |
c32b3d10c56b
Fix problem with `resize-minibuffer-mode'.
Mike Sperber <sperber@deinprogramm.de>
parents:
4375
diff
changeset
|
3609 * Round up when we're shrinking, down when we're growing |
c32b3d10c56b
Fix problem with `resize-minibuffer-mode'.
Mike Sperber <sperber@deinprogramm.de>
parents:
4375
diff
changeset
|
3610 * to make sure that pairs of grow / shrink meant to |
c32b3d10c56b
Fix problem with `resize-minibuffer-mode'.
Mike Sperber <sperber@deinprogramm.de>
parents:
4375
diff
changeset
|
3611 * cancel out actually do cancel out. |
c32b3d10c56b
Fix problem with `resize-minibuffer-mode'.
Mike Sperber <sperber@deinprogramm.de>
parents:
4375
diff
changeset
|
3612 */ |
c32b3d10c56b
Fix problem with `resize-minibuffer-mode'.
Mike Sperber <sperber@deinprogramm.de>
parents:
4375
diff
changeset
|
3613 if (pixel_adj_left < 0) |
c32b3d10c56b
Fix problem with `resize-minibuffer-mode'.
Mike Sperber <sperber@deinprogramm.de>
parents:
4375
diff
changeset
|
3614 pos = ((pos + line_size -1) / line_size) * line_size; |
c32b3d10c56b
Fix problem with `resize-minibuffer-mode'.
Mike Sperber <sperber@deinprogramm.de>
parents:
4375
diff
changeset
|
3615 else |
c32b3d10c56b
Fix problem with `resize-minibuffer-mode'.
Mike Sperber <sperber@deinprogramm.de>
parents:
4375
diff
changeset
|
3616 pos = (pos / line_size) * line_size; |
c32b3d10c56b
Fix problem with `resize-minibuffer-mode'.
Mike Sperber <sperber@deinprogramm.de>
parents:
4375
diff
changeset
|
3617 } |
428 | 3618 |
3619 /* Avoid confusion: don't delete child if it becomes too small */ | |
3620 set_window_pixsize (child, pos + first - last_pos, 1, set_height); | |
3621 | |
3622 last_pos = pos + first; | |
3623 last_old_pos = old_pos; | |
3624 } | |
3625 | |
3626 /* Sometimes we may get called with our old size. In that case | |
3627 we don't need to do anything else. */ | |
3628 if (!pixel_adj_left) | |
3629 return; | |
3630 | |
3631 /* Now delete any children that became too small. */ | |
3632 if (!nodelete) | |
3633 for (child = major_kid; !NILP (child); child = XWINDOW (child)->next) | |
3634 { | |
3635 if (set_height) | |
3636 set_window_pixheight (child, WINDOW_HEIGHT (XWINDOW (child)), 0); | |
3637 else | |
3638 set_window_pixwidth (child, WINDOW_WIDTH (XWINDOW (child)), 0); | |
3639 } | |
3640 } | |
3641 } | |
3642 | |
3643 /* Set the height of WINDOW and all its inferiors. */ | |
3644 void | |
3645 set_window_pixheight (Lisp_Object window, int new_pixheight, int nodelete) | |
3646 { | |
3647 set_window_pixsize (window, new_pixheight, nodelete, 1); | |
3648 } | |
3649 | |
3650 /* Recursively set width of WINDOW and its inferiors. */ | |
3651 void | |
3652 set_window_pixwidth (Lisp_Object window, int new_pixwidth, int nodelete) | |
3653 { | |
3654 set_window_pixsize (window, new_pixwidth, nodelete, 0); | |
3655 } | |
3656 | |
3657 | |
3658 static int window_select_count; | |
3659 | |
440 | 3660 DEFUN ("set-window-buffer", Fset_window_buffer, 2, 3, 0, /* |
428 | 3661 Make WINDOW display BUFFER as its contents. |
3662 BUFFER can be a buffer or buffer name. | |
440 | 3663 |
442 | 3664 With non-nil optional argument NORECORD, do not modify the |
440 | 3665 global or per-frame buffer ordering. |
428 | 3666 */ |
440 | 3667 (window, buffer, norecord)) |
428 | 3668 { |
3669 Lisp_Object tem; | |
3670 struct window *w = decode_window (window); | |
448 | 3671 int old_buffer_local_face_property = 0; |
428 | 3672 |
3673 buffer = Fget_buffer (buffer); | |
3674 CHECK_BUFFER (buffer); | |
3675 | |
3676 if (!BUFFER_LIVE_P (XBUFFER (buffer))) | |
563 | 3677 invalid_operation ("Attempt to display deleted buffer", Qunbound); |
428 | 3678 |
3679 tem = w->buffer; | |
3680 if (NILP (tem)) | |
563 | 3681 invalid_operation ("Window is deleted", Qunbound); |
428 | 3682 else if (EQ (tem, buffer)) |
3683 return Qnil; | |
3684 else if (! EQ (tem, Qt)) /* w->buffer is t when the window | |
3685 is first being set up. */ | |
3686 { | |
3687 if (!NILP (w->dedicated) && !EQ (tem, buffer)) | |
563 | 3688 signal_error (Qinvalid_operation, "Window is dedicated to buffer", tem); |
428 | 3689 |
448 | 3690 old_buffer_local_face_property = |
3691 XBUFFER (w->buffer)->buffer_local_face_property; | |
428 | 3692 unshow_buffer (w); |
3693 } | |
3694 | |
3695 w->buffer = buffer; | |
3696 w->window_end_pos[CURRENT_DISP] = 0; | |
3697 w->hscroll = 0; | |
3698 w->modeline_hscroll = 0; | |
844 | 3699 #if 0 /* pre point caches */ |
428 | 3700 Fset_marker (w->pointm[CURRENT_DISP], |
3701 make_int (BUF_PT (XBUFFER (buffer))), | |
3702 buffer); | |
3703 set_marker_restricted (w->start[CURRENT_DISP], | |
3704 make_int (XBUFFER (buffer)->last_window_start), | |
3705 buffer); | |
844 | 3706 #else |
3707 { | |
3708 Lisp_Object marker = Fgethash (buffer, w->saved_point_cache, Qnil); | |
3709 Lisp_Object newpoint = | |
3710 !NILP (marker) ? make_int (marker_position (marker)) : | |
3711 make_int (BUF_PT (XBUFFER (buffer))); | |
3712 /* Previously, we had in here set-window-point, which did one of the | |
3713 following two, but not both. However, that could result in pointm | |
3714 being in a different buffer from the window's buffer! Probably | |
3715 not a travesty since it always occurred when the window was | |
3716 selected, meaning its value of point was ignored in favor of the | |
3717 buffer's; but it tripped an assert() in unshow_buffer(). */ | |
3718 set_marker_restricted (w->pointm[CURRENT_DISP], newpoint, buffer); | |
3719 if (EQ (wrap_window (w), Fselected_window (Qnil))) | |
3720 Fgoto_char (newpoint, buffer); /* this will automatically clip to | |
3721 accessible */ | |
3722 marker = Fgethash (buffer, w->saved_last_window_start_cache, Qnil); | |
3723 set_marker_restricted (w->start[CURRENT_DISP], | |
3724 !NILP (marker) ? | |
3725 make_int (marker_position (marker)) : | |
3726 make_int (XBUFFER (buffer)->last_window_start), | |
3727 buffer); | |
3728 } | |
3729 #endif | |
3730 | |
428 | 3731 Fset_marker (w->sb_point, w->start[CURRENT_DISP], buffer); |
3732 /* set start_at_line_beg correctly. GE */ | |
844 | 3733 w->start_at_line_beg = |
3734 beginning_of_line_p (XBUFFER (buffer), | |
3735 marker_position (w->start[CURRENT_DISP])); | |
3736 w->force_start = 0; /* XEmacs fix */ | |
428 | 3737 SET_LAST_MODIFIED (w, 1); |
3738 SET_LAST_FACECHANGE (w); | |
3739 MARK_WINDOWS_CHANGED (w); | |
448 | 3740 { |
3741 int new_buffer_local_face_property = | |
3742 XBUFFER (w->buffer)->buffer_local_face_property; | |
3743 | |
3744 if (new_buffer_local_face_property | |
3745 || new_buffer_local_face_property != old_buffer_local_face_property) | |
3746 MARK_WINDOW_FACES_CHANGED (w); | |
3747 } | |
428 | 3748 recompute_all_cached_specifiers_in_window (w); |
3749 if (EQ (window, Fselected_window (Qnil))) | |
3750 { | |
440 | 3751 if (NILP (norecord)) |
3752 Frecord_buffer (buffer); | |
3753 | |
428 | 3754 Fset_buffer (buffer); |
3755 } | |
3756 return Qnil; | |
3757 } | |
3758 | |
3759 DEFUN ("select-window", Fselect_window, 1, 2, 0, /* | |
3760 Select WINDOW. Most editing will apply to WINDOW's buffer. | |
3761 The main editor command loop selects the buffer of the selected window | |
3762 before each command. | |
3763 | |
442 | 3764 With non-nil optional argument NORECORD, do not modify the |
428 | 3765 global or per-frame buffer ordering. |
3766 */ | |
3767 (window, norecord)) | |
3768 { | |
3769 struct window *w; | |
3770 Lisp_Object old_selected_window = Fselected_window (Qnil); | |
3771 | |
3772 CHECK_LIVE_WINDOW (window); | |
3773 w = XWINDOW (window); | |
3774 | |
3775 /* we have already caught dead-window errors */ | |
3776 if (!NILP (w->hchild) || !NILP (w->vchild)) | |
563 | 3777 invalid_operation ("Trying to select non-leaf window", Qunbound); |
428 | 3778 |
3779 w->use_time = make_int (++window_select_count); | |
442 | 3780 |
428 | 3781 if (EQ (window, old_selected_window)) |
3782 return window; | |
3783 | |
3784 /* deselect the old window, if it exists (it might not exist if | |
3785 the selected device has no frames, which occurs at startup) */ | |
3786 if (!NILP (old_selected_window)) | |
3787 { | |
3788 struct window *ow = XWINDOW (old_selected_window); | |
3789 | |
3790 Fset_marker (ow->pointm[CURRENT_DISP], | |
3791 make_int (BUF_PT (XBUFFER (ow->buffer))), | |
3792 ow->buffer); | |
3793 | |
3794 MARK_WINDOWS_CHANGED (ow); | |
3795 } | |
3796 | |
3797 /* now select the window's frame */ | |
3798 set_frame_selected_window (XFRAME (WINDOW_FRAME (w)), window); | |
3799 | |
3800 select_frame_1 (WINDOW_FRAME (w)); | |
3801 | |
3802 /* also select the window's buffer */ | |
3803 if (NILP (norecord)) | |
3804 Frecord_buffer (w->buffer); | |
3805 Fset_buffer (w->buffer); | |
3806 | |
3807 /* Go to the point recorded in the window. | |
3808 This is important when the buffer is in more | |
3809 than one window. It also matters when | |
3810 redisplay_window has altered point after scrolling, | |
3811 because it makes the change only in the window. */ | |
3812 { | |
665 | 3813 Charbpos new_point = marker_position (w->pointm[CURRENT_DISP]); |
428 | 3814 if (new_point < BUF_BEGV (current_buffer)) |
3815 new_point = BUF_BEGV (current_buffer); | |
3816 else if (new_point > BUF_ZV (current_buffer)) | |
3817 new_point = BUF_ZV (current_buffer); | |
3818 | |
3819 BUF_SET_PT (current_buffer, new_point); | |
3820 } | |
3821 | |
3822 MARK_WINDOWS_CHANGED (w); | |
3823 | |
3824 return window; | |
3825 } | |
3826 | |
3827 Lisp_Object | |
3828 display_buffer (Lisp_Object buffer, Lisp_Object not_this_window_p, | |
3829 Lisp_Object override_frame) | |
3830 { | |
3831 return call3 (Qdisplay_buffer, buffer, not_this_window_p, override_frame); | |
3832 } | |
3833 | |
3834 void | |
3835 temp_output_buffer_show (Lisp_Object buf, Lisp_Object same_frame) | |
3836 { | |
3837 /* This function can GC */ | |
3838 Lisp_Object window; | |
3839 struct window *w; | |
3840 struct buffer *b = XBUFFER (buf); | |
3841 | |
3842 BUF_SAVE_MODIFF (XBUFFER (buf)) = BUF_MODIFF (b); | |
3843 widen_buffer (b, 0); | |
3844 BUF_SET_PT (b, BUF_BEG (b)); | |
3845 | |
3846 if (!NILP (Vtemp_buffer_show_function)) | |
3847 call1 (Vtemp_buffer_show_function, buf); | |
3848 else | |
3849 { | |
3850 window = display_buffer (buf, Qnil, same_frame); | |
3851 | |
3852 if (!EQ (XWINDOW (window)->frame, Fselected_frame (Qnil))) | |
3853 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window))); | |
3854 | |
3855 Vminibuffer_scroll_window = window; | |
3856 w = XWINDOW (window); | |
3857 w->hscroll = 0; | |
3858 w->modeline_hscroll = 0; | |
3859 set_marker_restricted (w->start[CURRENT_DISP], make_int (1), buf); | |
3860 set_marker_restricted (w->pointm[CURRENT_DISP], make_int (1), buf); | |
3861 set_marker_restricted (w->sb_point, make_int (1), buf); | |
3862 } | |
3863 } | |
3864 | |
3865 static void | |
3866 make_dummy_parent (Lisp_Object window) | |
3867 { | |
3868 struct window *o = XWINDOW (window); | |
5127
a9c41067dd88
more cleanups, terminology clarification, lots of doc work
Ben Wing <ben@xemacs.org>
parents:
5126
diff
changeset
|
3869 Lisp_Object obj = ALLOC_NORMAL_LISP_OBJECT (window); |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3078
diff
changeset
|
3870 struct window *p = XWINDOW (obj); |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3078
diff
changeset
|
3871 |
5127
a9c41067dd88
more cleanups, terminology clarification, lots of doc work
Ben Wing <ben@xemacs.org>
parents:
5126
diff
changeset
|
3872 copy_lisp_object (obj, window); |
428 | 3873 |
3874 /* Don't copy the pointers to the line start cache or the face | |
3875 instances. */ | |
3876 p->line_start_cache = Dynarr_new (line_start_cache); | |
3092 | 3877 #ifdef NEW_GC |
3878 p->face_cachels = Dynarr_lisp_new (face_cachel, | |
3879 &lrecord_face_cachel_dynarr, | |
3880 &lrecord_face_cachel); | |
3881 p->glyph_cachels = Dynarr_lisp_new (glyph_cachel, | |
3882 &lrecord_glyph_cachel_dynarr, | |
3883 &lrecord_glyph_cachel); | |
3884 #else /* not NEW_GC */ | |
428 | 3885 p->face_cachels = Dynarr_new (face_cachel); |
3886 p->glyph_cachels = Dynarr_new (glyph_cachel); | |
3092 | 3887 #endif /* not NEW_GC */ |
442 | 3888 p->subwindow_instance_cache = |
450 | 3889 make_image_instance_cache_hash_table (); |
428 | 3890 |
3891 /* Put new into window structure in place of window */ | |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3078
diff
changeset
|
3892 replace_window (window, obj); |
428 | 3893 |
3894 o->next = Qnil; | |
3895 o->prev = Qnil; | |
3896 o->vchild = Qnil; | |
3897 o->hchild = Qnil; | |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3078
diff
changeset
|
3898 o->parent = obj; |
428 | 3899 |
3900 p->start[CURRENT_DISP] = Qnil; | |
3901 p->start[DESIRED_DISP] = Qnil; | |
3902 p->start[CMOTION_DISP] = Qnil; | |
3903 p->pointm[CURRENT_DISP] = Qnil; | |
3904 p->pointm[DESIRED_DISP] = Qnil; | |
3905 p->pointm[CMOTION_DISP] = Qnil; | |
3906 p->sb_point = Qnil; | |
844 | 3907 p->saved_point_cache = make_saved_buffer_point_cache (); |
3908 p->saved_last_window_start_cache = make_saved_buffer_point_cache (); | |
428 | 3909 p->buffer = Qnil; |
3910 } | |
3911 | |
3912 DEFUN ("split-window", Fsplit_window, 0, 3, "", /* | |
3913 Split WINDOW, putting SIZE lines in the first of the pair. | |
444 | 3914 WINDOW defaults to the selected one and SIZE to half its size. |
707 | 3915 If optional third arg HORFLAG is non-nil, split side by side and put |
3916 SIZE columns in the first of the pair. The newly created window is | |
3917 returned. | |
428 | 3918 */ |
444 | 3919 (window, size, horflag)) |
428 | 3920 { |
3025 | 3921 Lisp_Object new_; |
428 | 3922 struct window *o, *p; |
3923 struct frame *f; | |
444 | 3924 int csize; |
428 | 3925 int psize; |
3926 | |
3927 if (NILP (window)) | |
3928 window = Fselected_window (Qnil); | |
3929 else | |
3930 CHECK_LIVE_WINDOW (window); | |
3931 | |
3932 o = XWINDOW (window); | |
3933 f = XFRAME (WINDOW_FRAME (o)); | |
3934 | |
444 | 3935 if (NILP (size)) |
428 | 3936 { |
3937 if (!NILP (horflag)) | |
3938 /* In the new scheme, we are symmetric with respect to separators | |
3939 so there is no need to do weird things here. */ | |
3940 { | |
956 | 3941 psize = (WINDOW_WIDTH (o) + window_divider_width (o)) >> 1; |
444 | 3942 csize = window_pixel_width_to_char_width (o, psize, 0); |
428 | 3943 } |
3944 else | |
3945 { | |
3946 psize = WINDOW_HEIGHT (o) >> 1; | |
444 | 3947 csize = window_pixel_height_to_char_height (o, psize, 1); |
428 | 3948 } |
3949 } | |
3950 else | |
3951 { | |
444 | 3952 CHECK_INT (size); |
3953 csize = XINT (size); | |
428 | 3954 if (!NILP (horflag)) |
444 | 3955 psize = window_char_width_to_pixel_width (o, csize, 0); |
428 | 3956 else |
444 | 3957 psize = window_char_height_to_pixel_height (o, csize, 1); |
428 | 3958 } |
3959 | |
3960 if (MINI_WINDOW_P (o)) | |
563 | 3961 invalid_operation ("Attempt to split minibuffer window", Qunbound); |
428 | 3962 else if (FRAME_NO_SPLIT_P (XFRAME (WINDOW_FRAME (o)))) |
563 | 3963 invalid_operation ("Attempt to split unsplittable frame", Qunbound); |
428 | 3964 |
3965 check_min_window_sizes (); | |
3966 | |
3967 if (NILP (horflag)) | |
3968 { | |
444 | 3969 if (csize < window_min_height) |
563 | 3970 signal_error (Qinvalid_operation, "Window height too small (after splitting)", make_int (csize)); |
444 | 3971 if (csize + window_min_height > window_char_height (o, 1)) |
563 | 3972 signal_error (Qinvalid_operation, "Window height too small (after splitting)", |
3973 make_int (window_char_height (o, 1) - csize)); | |
428 | 3974 if (NILP (o->parent) |
3975 || NILP (XWINDOW (o->parent)->vchild)) | |
3976 { | |
3977 make_dummy_parent (window); | |
448 | 3978 #if 0 |
3979 /* #### I can't understand why you have to reset face | |
3980 cachels here. This can cause crash so let's disable it | |
3981 and see the difference. See redisplay-tests.el --yh */ | |
428 | 3982 reset_face_cachels (XWINDOW (window)); |
448 | 3983 #endif |
3025 | 3984 new_ = o->parent; |
3985 XWINDOW (new_)->vchild = window; | |
428 | 3986 XFRAME (o->frame)->mirror_dirty = 1; |
3987 } | |
3988 } | |
3989 else | |
3990 { | |
444 | 3991 if (csize < window_min_width) |
563 | 3992 signal_error (Qinvalid_operation, "Window width too small (after splitting)", make_int (csize)); |
444 | 3993 if (csize + window_min_width > window_char_width (o, 0)) |
563 | 3994 signal_error (Qinvalid_operation, "Window width too small (after splitting)", |
3995 make_int (window_char_width (o, 0) - csize)); | |
428 | 3996 if (NILP (o->parent) |
3997 || NILP (XWINDOW (o->parent)->hchild)) | |
3998 { | |
3999 make_dummy_parent (window); | |
448 | 4000 #if 0 |
4001 /* #### See above. */ | |
428 | 4002 reset_face_cachels (XWINDOW (window)); |
448 | 4003 #endif |
3025 | 4004 new_ = o->parent; |
4005 XWINDOW (new_)->hchild = window; | |
428 | 4006 XFRAME (o->frame)->mirror_dirty = 1; |
4007 } | |
4008 } | |
4009 | |
4010 /* Now we know that window's parent is a vertical combination | |
4011 if we are dividing vertically, or a horizontal combination | |
4012 if we are making side-by-side windows */ | |
4013 | |
4014 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f); | |
3025 | 4015 new_ = allocate_window (); |
4016 p = XWINDOW (new_); | |
428 | 4017 |
4018 p->frame = o->frame; | |
4019 p->next = o->next; | |
4020 if (!NILP (p->next)) | |
3025 | 4021 XWINDOW (p->next)->prev = new_; |
428 | 4022 p->prev = window; |
3025 | 4023 o->next = new_; |
428 | 4024 p->parent = o->parent; |
4025 p->buffer = Qt; | |
4026 | |
4027 reset_face_cachels (p); | |
4028 reset_glyph_cachels (p); | |
4029 | |
4030 | |
4031 /* Apportion the available frame space among the two new windows */ | |
4032 | |
4033 if (!NILP (horflag)) | |
4034 { | |
4035 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o); | |
4036 WINDOW_TOP (p) = WINDOW_TOP (o); | |
4037 WINDOW_WIDTH (p) = WINDOW_WIDTH (o) - psize; | |
4038 WINDOW_WIDTH (o) = psize; | |
4039 WINDOW_LEFT (p) = WINDOW_LEFT (o) + psize; | |
4040 } | |
4041 else | |
4042 { | |
4043 WINDOW_LEFT (p) = WINDOW_LEFT (o); | |
4044 WINDOW_WIDTH (p) = WINDOW_WIDTH (o); | |
4045 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o) - psize; | |
4046 WINDOW_HEIGHT (o) = psize; | |
4047 WINDOW_TOP (p) = WINDOW_TOP (o) + psize; | |
4048 } | |
4049 | |
4050 XFRAME (p->frame)->mirror_dirty = 1; | |
853 | 4051 |
3025 | 4052 note_object_created (new_); |
853 | 4053 |
428 | 4054 /* do this last (after the window is completely initialized and |
4055 the mirror-dirty flag is set) so that specifier recomputation | |
4056 caused as a result of this will work properly and not abort. */ | |
3025 | 4057 Fset_window_buffer (new_, o->buffer, Qt); |
4058 return new_; | |
428 | 4059 } |
4060 | |
4061 | |
4062 DEFUN ("enlarge-window", Fenlarge_window, 1, 3, "_p", /* | |
444 | 4063 Make the selected window COUNT lines taller. |
4064 From program, optional second arg HORIZONTALP non-nil means grow | |
4065 sideways COUNT columns, and optional third arg WINDOW specifies the | |
4066 window to change instead of the selected window. | |
428 | 4067 */ |
444 | 4068 (count, horizontalp, window)) |
4069 { | |
4070 CHECK_INT (count); | |
4071 change_window_height (window, XINT (count), horizontalp, /* inpixels */ 0); | |
428 | 4072 return Qnil; |
4073 } | |
4074 | |
4075 DEFUN ("enlarge-window-pixels", Fenlarge_window_pixels, 1, 3, "_p", /* | |
444 | 4076 Make the selected window COUNT pixels taller. |
4077 From program, optional second arg HORIZONTALP non-nil means grow | |
4078 sideways COUNT pixels, and optional third arg WINDOW specifies the | |
4079 window to change instead of the selected window. | |
428 | 4080 */ |
444 | 4081 (count, horizontalp, window)) |
4082 { | |
4083 CHECK_INT (count); | |
4084 change_window_height (window, XINT (count), horizontalp, /* inpixels */ 1); | |
428 | 4085 return Qnil; |
4086 } | |
4087 | |
4088 DEFUN ("shrink-window", Fshrink_window, 1, 3, "_p", /* | |
444 | 4089 Make the selected window COUNT lines shorter. |
4090 From program, optional second arg HORIZONTALP non-nil means shrink | |
4091 sideways COUNT columns, and optional third arg WINDOW specifies the | |
4092 window to change instead of the selected window. | |
428 | 4093 */ |
444 | 4094 (count, horizontalp, window)) |
4095 { | |
4096 CHECK_INT (count); | |
4097 change_window_height (window, -XINT (count), horizontalp, /* inpixels */ 0); | |
428 | 4098 return Qnil; |
4099 } | |
4100 | |
4101 DEFUN ("shrink-window-pixels", Fshrink_window_pixels, 1, 3, "_p", /* | |
444 | 4102 Make the selected window COUNT pixels smaller. |
4103 From program, optional second arg HORIZONTALP non-nil means shrink | |
4104 sideways COUNT pixels, and optional third arg WINDOW specifies the | |
4105 window to change instead of the selected window. | |
428 | 4106 */ |
444 | 4107 (count, horizontalp, window)) |
4108 { | |
4109 CHECK_INT (count); | |
4110 change_window_height (window, -XINT (count), horizontalp, /* inpixels */ 1); | |
428 | 4111 return Qnil; |
4112 } | |
4113 | |
4114 static int | |
4115 window_pixel_height_to_char_height (struct window *w, int pixel_height, | |
4116 int include_gutters_p) | |
4117 { | |
4118 int avail_height; | |
4119 int defheight, defwidth; | |
3687 | 4120 int char_height = 0; |
793 | 4121 Lisp_Object window = wrap_window (w); |
4122 | |
428 | 4123 |
4124 avail_height = (pixel_height - | |
4125 (include_gutters_p ? 0 : | |
442 | 4126 window_top_window_gutter_height (w) + |
4127 window_bottom_window_gutter_height (w))); | |
428 | 4128 |
5047
07dcc7000bbf
put width before height consistently, fix a real bug found in the process
Ben Wing <ben@xemacs.org>
parents:
5043
diff
changeset
|
4129 default_face_width_and_height (window, &defwidth, &defheight); |
428 | 4130 |
3687 | 4131 if (defheight) |
4132 char_height = avail_height / defheight; | |
428 | 4133 |
4134 /* It's the calling function's responsibility to check these values | |
4135 and make sure they're not out of range. | |
4136 | |
4137 #### We need to go through the calling functions and actually | |
4138 do this. */ | |
4139 return max (0, char_height); | |
4140 } | |
4141 | |
4142 static int | |
4143 window_char_height_to_pixel_height (struct window *w, int char_height, | |
4144 int include_gutters_p) | |
4145 { | |
4146 int avail_height; | |
4147 int defheight, defwidth; | |
4148 int pixel_height; | |
4149 | |
793 | 4150 Lisp_Object window = wrap_window (w); |
4151 | |
428 | 4152 |
5047
07dcc7000bbf
put width before height consistently, fix a real bug found in the process
Ben Wing <ben@xemacs.org>
parents:
5043
diff
changeset
|
4153 default_face_width_and_height (window, &defwidth, &defheight); |
428 | 4154 |
4155 avail_height = char_height * defheight; | |
4156 pixel_height = (avail_height + | |
4157 (include_gutters_p ? 0 : | |
442 | 4158 window_top_window_gutter_height (w) + |
4159 window_bottom_window_gutter_height (w))); | |
428 | 4160 |
4161 /* It's the calling function's responsibility to check these values | |
4162 and make sure they're not out of range. | |
4163 | |
4164 #### We need to go through the calling functions and actually | |
4165 do this. */ | |
4166 return max (0, pixel_height); | |
4167 } | |
4168 | |
4169 /* Return number of default lines of text can fit in the window W. | |
4170 If INCLUDE_GUTTERS_P is 1, include "gutter" space (modeline plus | |
4171 horizontal scrollbar) in the space that is used for the calculation. | |
442 | 4172 This doesn't include space used by the frame gutters. |
428 | 4173 */ |
4174 int | |
4175 window_char_height (struct window *w, int include_gutters_p) | |
4176 { | |
442 | 4177 return window_pixel_height_to_char_height (w, window_pixel_height (w), |
428 | 4178 include_gutters_p); |
4179 } | |
4180 | |
4181 /* | |
4182 * Return number of lines currently displayed in window w. If | |
4183 * end-of-buffer is displayed then the area below end-of-buffer is assume | |
4184 * to be blank lines of default height. | |
4185 * Does not include the modeline. | |
4186 */ | |
4187 int | |
4188 window_displayed_height (struct window *w) | |
4189 { | |
4190 struct buffer *b = XBUFFER (w->buffer); | |
4191 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP); | |
4192 int num_lines; | |
4193 Charcount end_pos = (BUF_Z (b) - w->window_end_pos[CURRENT_DISP] > BUF_ZV (b) | |
4194 ? -1 | |
4195 : w->window_end_pos[CURRENT_DISP]); | |
4196 | |
4197 if (!Dynarr_length (dla)) | |
4198 return window_char_height (w, 0); | |
4199 | |
4200 num_lines = Dynarr_length (dla); | |
4201 | |
4202 /* #### Document and assert somewhere that w->window_end_pos == -1 | |
4203 indicates that end-of-buffer is being displayed. */ | |
4204 if (end_pos == -1) | |
4205 { | |
4967 | 4206 struct display_line *dl = Dynarr_begin (dla); |
428 | 4207 int ypos1 = dl->ypos + dl->descent; |
4208 int ypos2 = WINDOW_TEXT_BOTTOM (w); | |
4209 Lisp_Object window; | |
4210 int defheight, defwidth; | |
4211 | |
793 | 4212 window = wrap_window (w); |
428 | 4213 |
4214 if (dl->modeline) | |
4215 { | |
4216 num_lines--; | |
4217 | |
4218 if (Dynarr_length (dla) == 1) | |
4219 ypos1 = WINDOW_TEXT_TOP (w); | |
4220 else | |
4221 { | |
4222 dl = Dynarr_atp (dla, Dynarr_length (dla) - 1); | |
4223 /* If this line is clipped then we know that there is no | |
4224 blank room between eob and the modeline. If we are | |
4225 scrolling on clipped lines just know off the clipped | |
4226 line and return .*/ | |
4227 if (scroll_on_clipped_lines && dl->clip) | |
4228 return num_lines - 1; | |
4229 ypos1 = dl->ypos + dl->descent - dl->clip; | |
4230 } | |
4231 } | |
4232 | |
5047
07dcc7000bbf
put width before height consistently, fix a real bug found in the process
Ben Wing <ben@xemacs.org>
parents:
5043
diff
changeset
|
4233 default_face_width_and_height (window, &defwidth, &defheight); |
428 | 4234 /* #### This probably needs to know about the clipping area once a |
4235 final definition is decided on. */ | |
3707 | 4236 if (defheight) |
4237 num_lines += ((ypos2 - ypos1) / defheight); | |
428 | 4238 } |
4239 else | |
4240 { | |
4967 | 4241 if (num_lines > 1 && Dynarr_begin (dla)->modeline) |
428 | 4242 num_lines--; |
4243 | |
4244 if (scroll_on_clipped_lines | |
4245 && Dynarr_atp (dla, Dynarr_length (dla) - 1)->clip) | |
4246 num_lines--; | |
4247 } | |
4248 | |
4249 return num_lines; | |
4250 } | |
4251 | |
4252 static int | |
4253 window_pixel_width (Lisp_Object window) | |
4254 { | |
4255 return WINDOW_WIDTH (XWINDOW (window)); | |
4256 } | |
4257 | |
442 | 4258 /* Calculate the pixel of a window, optionally including margin space |
4259 but no vertical gutters. */ | |
428 | 4260 static int |
4261 window_pixel_width_to_char_width (struct window *w, int pixel_width, | |
4262 int include_margins_p) | |
4263 { | |
4264 int avail_width; | |
3676 | 4265 int char_width = 0; |
428 | 4266 int defheight, defwidth; |
793 | 4267 Lisp_Object window = wrap_window (w); |
4268 | |
428 | 4269 |
4270 avail_width = (pixel_width - | |
4271 window_left_gutter_width (w, 0) - | |
4272 window_right_gutter_width (w, 0) - | |
4273 (include_margins_p ? 0 : window_left_margin_width (w)) - | |
4274 (include_margins_p ? 0 : window_right_margin_width (w))); | |
4275 | |
5047
07dcc7000bbf
put width before height consistently, fix a real bug found in the process
Ben Wing <ben@xemacs.org>
parents:
5043
diff
changeset
|
4276 default_face_width_and_height (window, &defwidth, &defheight); |
428 | 4277 |
3676 | 4278 if (defwidth) |
4279 char_width = (avail_width / defwidth); | |
428 | 4280 |
4281 /* It's the calling function's responsibility to check these values | |
4282 and make sure they're not out of range. | |
4283 | |
4284 #### We need to go through the calling functions and actually | |
4285 do this. */ | |
4286 return max (0, char_width); | |
4287 } | |
4288 | |
4289 static int | |
4290 window_char_width_to_pixel_width (struct window *w, int char_width, | |
4291 int include_margins_p) | |
4292 { | |
4293 int avail_width; | |
4294 int pixel_width; | |
4295 int defheight, defwidth; | |
793 | 4296 Lisp_Object window = wrap_window (w); |
4297 | |
428 | 4298 |
5047
07dcc7000bbf
put width before height consistently, fix a real bug found in the process
Ben Wing <ben@xemacs.org>
parents:
5043
diff
changeset
|
4299 default_face_width_and_height (window, &defwidth, &defheight); |
428 | 4300 |
4301 avail_width = char_width * defwidth; | |
4302 pixel_width = (avail_width + | |
442 | 4303 window_left_window_gutter_width (w, 0) + |
4304 window_right_window_gutter_width (w, 0) + | |
428 | 4305 (include_margins_p ? 0 : window_left_margin_width (w)) + |
4306 (include_margins_p ? 0 : window_right_margin_width (w))); | |
4307 | |
4308 /* It's the calling function's responsibility to check these values | |
4309 and make sure they're not out of range. | |
4310 | |
4311 #### We need to go through the calling functions and actually | |
4312 do this. */ | |
4313 return max (0, pixel_width); | |
4314 } | |
4315 | |
4316 /* This returns the usable space which doesn't include space needed by | |
4317 scrollbars or divider lines. */ | |
4318 int | |
4319 window_char_width (struct window *w, int include_margins_p) | |
4320 { | |
4321 return window_pixel_width_to_char_width (w, WINDOW_WIDTH (w), | |
4322 include_margins_p); | |
4323 } | |
4324 | |
4325 #define MINSIZE(w) \ | |
4326 (widthflag \ | |
4327 ? window_min_width * defwidth \ | |
4328 : (defheight * (MINI_WINDOW_P (XWINDOW (w)) ? 1 : window_min_height))) | |
4329 | |
4330 #define CURBEG(w) \ | |
4331 *(widthflag ? (int *) &WINDOW_LEFT (w) : (int *) &WINDOW_TOP (w)) | |
4332 | |
4333 #define CURSIZE(w) \ | |
4334 *(widthflag ? (int *) &WINDOW_WIDTH (w) : (int *) &WINDOW_HEIGHT (w)) | |
4335 | |
4336 #define CURCHARSIZE(w) \ | |
4337 (widthflag ? window_char_width (w, 0) : window_char_height (w, 1)) | |
4338 | |
4339 #define MINCHARSIZE(window) \ | |
4340 (widthflag ? window_min_width : MINI_WINDOW_P (XWINDOW (window)) \ | |
4341 ? 1 : window_min_height) | |
4342 | |
442 | 4343 static int |
4344 window_pixheight (Lisp_Object w) | |
4345 { | |
4346 return window_pixel_height (XWINDOW (w)); | |
4347 } | |
4348 | |
428 | 4349 /* Unlike set_window_pixheight, this function |
4350 also changes the heights of the siblings so as to | |
4351 keep everything consistent. */ | |
4352 | |
4353 static void | |
444 | 4354 change_window_height (Lisp_Object window, int delta, Lisp_Object horizontalp, |
428 | 4355 int inpixels) |
4356 { | |
444 | 4357 struct window *win = decode_window (window); |
4358 int widthflag = !NILP (horizontalp); | |
428 | 4359 Lisp_Object parent; |
4360 struct window *w; | |
4361 struct frame *f; | |
4362 int *sizep; | |
4363 int (*sizefun) (Lisp_Object) = (widthflag | |
4364 ? window_pixel_width | |
442 | 4365 : window_pixheight); |
428 | 4366 void (*setsizefun) (Lisp_Object, int, int) = (widthflag |
4367 ? set_window_pixwidth | |
4368 : set_window_pixheight); | |
4369 int dim; | |
4370 int defheight, defwidth; | |
4371 | |
4372 if (delta == 0) | |
4373 return; | |
4374 | |
4375 check_min_window_sizes (); | |
4376 | |
793 | 4377 window = wrap_window (win); |
428 | 4378 f = XFRAME (win->frame); |
4379 if (EQ (window, FRAME_ROOT_WINDOW (f))) | |
563 | 4380 invalid_operation ("Won't change only window", Qunbound); |
428 | 4381 |
5047
07dcc7000bbf
put width before height consistently, fix a real bug found in the process
Ben Wing <ben@xemacs.org>
parents:
5043
diff
changeset
|
4382 default_face_width_and_height (window, &defwidth, &defheight); |
428 | 4383 |
4384 while (1) | |
4385 { | |
4386 w = XWINDOW (window); | |
4387 parent = w->parent; | |
4388 if (NILP (parent)) | |
4389 { | |
4390 if (widthflag) | |
3078 | 4391 { |
4392 int new_pixsize; | |
4393 sizep = &CURSIZE (w); | |
3466 | 4394 dim = CURCHARSIZE (w); |
3078 | 4395 new_pixsize = inpixels?(*sizep + delta):(dim+delta); |
4396 set_window_pixsize (window, new_pixsize, 0, 0); | |
4397 return; | |
4398 } | |
428 | 4399 break; |
4400 } | |
4401 if (widthflag | |
4402 ? !NILP (XWINDOW (parent)->hchild) | |
4403 : !NILP (XWINDOW (parent)->vchild)) | |
4404 break; | |
4405 window = parent; | |
4406 } | |
4407 | |
4408 sizep = &CURSIZE (w); | |
4409 dim = CURCHARSIZE (w); | |
4410 | |
4411 if ((inpixels && (*sizep + delta) < MINSIZE (window)) || | |
4412 (!inpixels && (dim + delta) < MINCHARSIZE (window))) | |
4413 { | |
4414 if (MINI_WINDOW_P (XWINDOW (window))) | |
4415 return; | |
4416 else if (!NILP (parent)) | |
4417 { | |
4418 Fdelete_window (window, Qnil); | |
4419 return; | |
4420 } | |
4421 } | |
4422 | |
4423 if (!inpixels) | |
4424 delta *= (widthflag ? defwidth : defheight); | |
4425 | |
4426 { | |
4427 int maxdelta; | |
4428 | |
4429 maxdelta = ((!NILP (parent)) | |
4430 ? (*sizefun) (parent) - *sizep | |
4431 : ((!NILP (w->next)) | |
4432 ? (*sizefun) (w->next) - MINSIZE (w->next) | |
4433 : ((!NILP (w->prev)) | |
4434 ? (*sizefun) (w->prev) - MINSIZE (w->prev) | |
4435 /* This is a frame with only one window, | |
4436 a minibuffer-only or a minibufferless frame. */ | |
4437 : (delta = 0)))); | |
4438 | |
4439 if (delta > maxdelta) | |
4440 /* This case traps trying to make the minibuffer | |
4441 the full frame, or make the only window aside from the | |
4442 minibuffer the full frame. */ | |
4443 delta = maxdelta; | |
4444 | |
4445 if (delta == 0) | |
4446 return; | |
4447 | |
4448 #if 0 /* FSFmacs */ | |
4449 /* #### Chuck: is this correct? */ | |
4450 if (*sizep + delta < MINSIZE (window)) | |
4451 { | |
4452 Fdelete_window (window); | |
4453 return; | |
4454 } | |
4455 #endif | |
4456 } | |
4457 | |
4458 if (!NILP (w->next) && | |
4459 (*sizefun) (w->next) - delta >= (int) MINSIZE (w->next)) | |
4460 { | |
4461 CURBEG (XWINDOW (w->next)) += delta; | |
4462 (*setsizefun) (w->next, (*sizefun) (w->next) - delta, 0); | |
4463 (*setsizefun) (window, *sizep + delta, 0); | |
4464 } | |
4465 else if (!NILP (w->prev) && | |
4466 (*sizefun) (w->prev) - delta >= (int) MINSIZE (w->prev)) | |
4467 { | |
4468 (*setsizefun) (w->prev, (*sizefun) (w->prev) - delta, 0); | |
4469 CURBEG (w) -= delta; | |
4470 (*setsizefun) (window, *sizep + delta, 0); | |
4471 } | |
4472 else | |
4473 { | |
4474 int delta1; | |
4475 int opht = (*sizefun) (parent); | |
4476 | |
4477 /* If trying to grow this window to or beyond size of the parent, | |
4478 make delta1 so big that, on shrinking back down, | |
4479 all the siblings end up with less than one line and are deleted. */ | |
4480 if (opht <= *sizep + delta) | |
4481 delta1 = opht * opht * 2; | |
4482 /* Otherwise, make delta1 just right so that if we add delta1 | |
4483 lines to this window and to the parent, and then shrink | |
4484 the parent back to its original size, the new proportional | |
4485 size of this window will increase by delta. */ | |
4486 else | |
4487 delta1 = (delta * opht * 100) / ((opht - *sizep - delta) * 100); | |
4488 | |
4489 /* Add delta1 lines or columns to this window, and to the parent, | |
4490 keeping things consistent while not affecting siblings. */ | |
4491 CURSIZE (XWINDOW (parent)) = opht + delta1; | |
4492 (*setsizefun) (window, *sizep + delta1, 0); | |
4493 | |
4494 /* Squeeze out delta1 lines or columns from our parent, | |
4495 shrinking this window and siblings proportionately. | |
4496 This brings parent back to correct size. | |
4497 Delta1 was calculated so this makes this window the desired size, | |
4498 taking it all out of the siblings. */ | |
4499 (*setsizefun) (parent, opht, 0); | |
4500 } | |
4501 | |
4502 SET_LAST_MODIFIED (w, 0); | |
4503 SET_LAST_FACECHANGE (w); | |
4504 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f); | |
4505 /* overkill maybe, but better to be correct */ | |
4506 MARK_FRAME_GUTTERS_CHANGED (f); | |
4507 } | |
4508 #undef MINSIZE | |
4509 #undef CURBEG | |
4510 #undef CURSIZE | |
4511 #undef CURCHARSIZE | |
4512 #undef MINCHARSIZE | |
4513 | |
4514 | |
4515 | |
444 | 4516 /* Scroll contents of window WINDOW up COUNT lines. |
4517 If COUNT < (top line height / average line height) then we just adjust | |
4518 the top clip. */ | |
428 | 4519 void |
444 | 4520 window_scroll (Lisp_Object window, Lisp_Object count, int direction, |
578 | 4521 Error_Behavior errb) |
428 | 4522 { |
4523 struct window *w = XWINDOW (window); | |
4524 struct buffer *b = XBUFFER (w->buffer); | |
4525 int selected = EQ (window, Fselected_window (Qnil)); | |
4526 int value = 0; | |
4527 Lisp_Object point, tem; | |
4528 display_line_dynarr *dla; | |
4529 int fheight, fwidth, modeline = 0; | |
4530 struct display_line* dl; | |
4531 | |
4532 if (selected) | |
4533 point = make_int (BUF_PT (b)); | |
4534 else | |
4535 { | |
665 | 4536 Charbpos pos = marker_position (w->pointm[CURRENT_DISP]); |
428 | 4537 |
4538 if (pos < BUF_BEGV (b)) | |
4539 pos = BUF_BEGV (b); | |
4540 else if (pos > BUF_ZV (b)) | |
4541 pos = BUF_ZV (b); | |
4542 | |
4543 point = make_int (pos); | |
4544 } | |
4545 | |
4546 /* Always set force_start so that redisplay_window will run | |
4547 the window-scroll-functions. */ | |
4548 w->force_start = 1; | |
4549 | |
4550 /* #### When the fuck does this happen? I'm so glad that history has | |
4551 completely documented the behavior of the scrolling functions under | |
4552 all circumstances. */ | |
1708 | 4553 tem = Fpos_visible_in_window_p (point, window, Qnil); |
428 | 4554 if (NILP (tem)) |
4555 { | |
4556 Fvertical_motion (make_int (-window_char_height (w, 0) / 2), | |
4557 window, Qnil); | |
4558 Fset_marker (w->start[CURRENT_DISP], point, w->buffer); | |
4559 w->start_at_line_beg = beginning_of_line_p (b, XINT (point)); | |
4560 WINDOW_TEXT_TOP_CLIP (w) = 0; | |
4561 MARK_WINDOWS_CHANGED (w); | |
4562 } | |
4563 | |
444 | 4564 if (!NILP (count)) |
428 | 4565 { |
444 | 4566 if (EQ (count, Qminus)) |
428 | 4567 direction *= -1; |
4568 else | |
4569 { | |
444 | 4570 count = Fprefix_numeric_value (count); |
4571 value = XINT (count) * direction; | |
428 | 4572 |
4573 if (!value) | |
4574 return; /* someone just made a pointless call */ | |
4575 } | |
4576 } | |
4577 | |
4578 /* If the user didn't specify how far to scroll then we have to figure it | |
4579 out by ourselves. */ | |
444 | 4580 if (NILP (count) || EQ (count, Qminus)) |
428 | 4581 { |
4582 /* Going forwards is easy. If that is what we are doing then just | |
4583 set value and the section which handles the user specifying a | |
4584 positive value will work. */ | |
4585 if (direction == 1) | |
4586 { | |
4587 value = window_displayed_height (w) - next_screen_context_lines; | |
4588 value = (value < 1 ? 1 : value); | |
4589 } | |
4590 | |
4591 /* Going backwards is hard. We can't use the same loop used if the | |
4592 user specified a negative value because we care about | |
4593 next_screen_context_lines. In a variable height world you don't | |
4594 know how many lines above you can actually be displayed and still | |
4595 have the context lines appear. So we leave value set to 0 and add | |
4596 a separate section to deal with this. */ | |
4597 | |
4598 } | |
4599 | |
4600 if (direction == 1 && !value) | |
4601 { | |
4602 return; | |
4603 } | |
4604 | |
4605 /* Determine parameters to test for partial line scrolling with. */ | |
4606 dla = window_display_lines (w, CURRENT_DISP); | |
4607 | |
4608 if (INTP (Vwindow_pixel_scroll_increment)) | |
4609 fheight = XINT (Vwindow_pixel_scroll_increment); | |
440 | 4610 else if (!NILP (Vwindow_pixel_scroll_increment)) |
5047
07dcc7000bbf
put width before height consistently, fix a real bug found in the process
Ben Wing <ben@xemacs.org>
parents:
5043
diff
changeset
|
4611 default_face_width_and_height (window, &fwidth, &fheight); |
438 | 4612 |
428 | 4613 if (Dynarr_length (dla) >= 1) |
4967 | 4614 modeline = Dynarr_begin (dla)->modeline; |
428 | 4615 |
4616 dl = Dynarr_atp (dla, modeline); | |
438 | 4617 |
428 | 4618 if (value > 0) |
4619 { | |
4620 /* Go for partial display line scrolling. This just means bumping | |
4621 the clip by a reasonable amount and redisplaying, everything else | |
4622 remains unchanged. */ | |
4623 if (!NILP (Vwindow_pixel_scroll_increment) | |
4624 && | |
4625 Dynarr_length (dla) >= (1 + modeline) | |
4626 && | |
458 | 4627 (dl->ascent - dl->top_clip) > fheight * value) |
428 | 4628 { |
4629 WINDOW_TEXT_TOP_CLIP (w) += value * fheight; | |
4630 MARK_WINDOWS_CHANGED (w); | |
4631 } | |
4632 else | |
4633 { | |
4634 int vtarget; | |
665 | 4635 Charbpos startp, old_start; |
438 | 4636 |
428 | 4637 if (WINDOW_TEXT_TOP_CLIP (w)) |
4638 { | |
4639 WINDOW_TEXT_TOP_CLIP (w) = 0; | |
4640 MARK_WINDOWS_CHANGED (w); | |
4641 } | |
4642 | |
4643 old_start = marker_position (w->start[CURRENT_DISP]); | |
4644 startp = vmotion (w, old_start, value, &vtarget); | |
438 | 4645 |
428 | 4646 if (vtarget < value && |
4647 (w->window_end_pos[CURRENT_DISP] == -1 | |
4648 || (BUF_Z (b) - w->window_end_pos[CURRENT_DISP] > BUF_ZV (b)))) | |
4649 { | |
563 | 4650 maybe_signal_error_1 (Qend_of_buffer, Qnil, Qwindow, errb); |
428 | 4651 return; |
4652 } | |
4653 else | |
4654 { | |
4655 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp), | |
4656 w->buffer); | |
4657 w->force_start = 1; | |
4658 w->start_at_line_beg = beginning_of_line_p (b, startp); | |
4659 MARK_WINDOWS_CHANGED (w); | |
438 | 4660 |
1708 | 4661 if (!point_would_be_visible (w, startp, XINT (point), 0)) |
844 | 4662 Fset_window_point (wrap_window (w), make_int (startp)); |
428 | 4663 } |
4664 } | |
4665 } | |
4666 else if (value < 0) | |
4667 { | |
4668 /* Go for partial display line scrolling. This just means bumping | |
4669 the clip by a reasonable amount and redisplaying, everything else | |
4670 remains unchanged. */ | |
4671 if (!NILP (Vwindow_pixel_scroll_increment) | |
4672 && | |
4673 Dynarr_length (dla) >= (1 + modeline) | |
4674 && | |
4675 (dl->ascent - dl->top_clip) - fheight * value < | |
4676 (dl->ascent + dl->descent - dl->clip) | |
4677 && | |
4678 WINDOW_TEXT_TOP_CLIP (w) + value * fheight > 0) | |
4679 { | |
4680 WINDOW_TEXT_TOP_CLIP (w) += value * fheight; | |
4681 MARK_WINDOWS_CHANGED (w); | |
4682 } | |
4683 else | |
4684 { | |
4685 int vtarget; | |
665 | 4686 Charbpos startp, old_start; |
438 | 4687 |
428 | 4688 if (WINDOW_TEXT_TOP_CLIP (w)) |
4689 { | |
4690 WINDOW_TEXT_TOP_CLIP (w) = 0; | |
4691 MARK_WINDOWS_CHANGED (w); | |
4692 } | |
438 | 4693 |
428 | 4694 old_start = marker_position (w->start[CURRENT_DISP]); |
4695 startp = vmotion (w, old_start, value, &vtarget); | |
438 | 4696 |
428 | 4697 if (vtarget > value |
4698 && marker_position (w->start[CURRENT_DISP]) == BUF_BEGV (b)) | |
4699 { | |
563 | 4700 maybe_signal_error_1 (Qbeginning_of_buffer, Qnil, Qwindow, errb); |
428 | 4701 return; |
4702 } | |
4703 else | |
4704 { | |
4705 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp), | |
4706 w->buffer); | |
4707 w->force_start = 1; | |
4708 w->start_at_line_beg = beginning_of_line_p (b, startp); | |
4709 MARK_WINDOWS_CHANGED (w); | |
438 | 4710 |
440 | 4711 /* #### Scroll back by less than a line. This code was |
4712 originally for scrolling over large pixmaps and it | |
4713 loses when a line being *exposed* at the top of the | |
4714 window is bigger than the current one. However, for | |
4715 pixel based scrolling in general we can guess that | |
4716 the line we are going to display is probably the same | |
4717 size as the one we are on. In that instance we can | |
4718 have a reasonable stab at a suitable top clip. Fixing | |
4719 this properly is hard (and probably slow) as we would | |
4720 have to call redisplay to figure out the exposed line | |
4721 size. */ | |
4722 if (!NILP (Vwindow_pixel_scroll_increment) | |
4723 && Dynarr_length (dla) >= (1 + modeline) | |
4724 && dl->ascent + fheight * value > 0) | |
4725 { | |
4726 WINDOW_TEXT_TOP_CLIP (w) = (dl->ascent + fheight * value); | |
4727 } | |
4728 | |
1708 | 4729 if (!point_would_be_visible (w, startp, XINT (point), 0)) |
428 | 4730 { |
665 | 4731 Charbpos new_point; |
438 | 4732 |
428 | 4733 if (MINI_WINDOW_P (w)) |
4734 new_point = startp; | |
4735 else | |
4736 new_point = start_of_last_line (w, startp); | |
438 | 4737 |
844 | 4738 Fset_window_point (wrap_window (w), make_int (new_point)); |
428 | 4739 } |
4740 } | |
4741 } | |
4742 } | |
4743 else /* value == 0 && direction == -1 */ | |
4744 { | |
4745 if (WINDOW_TEXT_TOP_CLIP (w)) | |
4746 { | |
4747 WINDOW_TEXT_TOP_CLIP (w) = 0; | |
4748 MARK_WINDOWS_CHANGED (w); | |
4749 } | |
4750 if (marker_position (w->start[CURRENT_DISP]) == BUF_BEGV (b)) | |
4751 { | |
563 | 4752 maybe_signal_error_1 (Qbeginning_of_buffer, Qnil, Qwindow, errb); |
428 | 4753 return; |
4754 } | |
4755 else | |
4756 { | |
4757 int vtarget; | |
4758 int movement = next_screen_context_lines - 1; | |
665 | 4759 Charbpos old_startp = marker_position (w->start[CURRENT_DISP]); |
4760 Charbpos bottom = vmotion (w, old_startp, movement, &vtarget); | |
4761 Charbpos startp = | |
428 | 4762 start_with_point_on_display_line (w, bottom, |
4763 -1 - (movement - vtarget)); | |
4764 | |
4765 if (startp >= old_startp) | |
4766 startp = vmotion (w, old_startp, -1, NULL); | |
4767 | |
4768 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp), | |
4769 w->buffer); | |
4770 w->force_start = 1; | |
4771 w->start_at_line_beg = beginning_of_line_p (b, startp); | |
4772 MARK_WINDOWS_CHANGED (w); | |
4773 | |
1708 | 4774 if (!point_would_be_visible (w, startp, XINT (point), 0)) |
428 | 4775 { |
665 | 4776 Charbpos new_point = start_of_last_line (w, startp); |
428 | 4777 |
844 | 4778 Fset_window_point (wrap_window (w), make_int (new_point)); |
428 | 4779 } |
4780 } | |
4781 } | |
4782 } | |
4783 | |
4784 DEFUN ("scroll-up", Fscroll_up, 0, 1, "_P", /* | |
444 | 4785 Scroll text of current window up COUNT lines; or near full screen if no arg. |
428 | 4786 A near full screen is `next-screen-context-lines' less than a full screen. |
444 | 4787 Negative COUNT means scroll downward. |
428 | 4788 When calling from a program, supply an integer as argument or nil. |
4789 On attempt to scroll past end of buffer, `end-of-buffer' is signaled. | |
4790 On attempt to scroll past beginning of buffer, `beginning-of-buffer' is | |
4791 signaled. | |
462 | 4792 |
4793 The characters that are moved over may be added to the current selection | |
4794 \(i.e. active region) if the Shift key is held down, a motion key is used | |
4795 to invoke this command, and `shifted-motion-keys-select-region' is t; see | |
4796 the documentation for this variable for more details. | |
428 | 4797 */ |
444 | 4798 (count)) |
4799 { | |
4800 window_scroll (Fselected_window (Qnil), count, 1, ERROR_ME); | |
428 | 4801 return Qnil; |
4802 } | |
4803 | |
4804 DEFUN ("scroll-down", Fscroll_down, 0, 1, "_P", /* | |
444 | 4805 Scroll text of current window down COUNT lines; or near full screen if no arg. |
428 | 4806 A near full screen is `next-screen-context-lines' less than a full screen. |
444 | 4807 Negative COUNT means scroll upward. |
428 | 4808 When calling from a program, supply a number as argument or nil. |
4809 On attempt to scroll past end of buffer, `end-of-buffer' is signaled. | |
4810 On attempt to scroll past beginning of buffer, `beginning-of-buffer' is | |
4811 signaled. | |
462 | 4812 |
4813 The characters that are moved over may be added to the current selection | |
4814 \(i.e. active region) if the Shift key is held down, a motion key is used | |
4815 to invoke this command, and `shifted-motion-keys-select-region' is t; see | |
4816 the documentation for this variable for more details. | |
428 | 4817 */ |
444 | 4818 (count)) |
4819 { | |
4820 window_scroll (Fselected_window (Qnil), count, -1, ERROR_ME); | |
428 | 4821 return Qnil; |
4822 } | |
4823 | |
4824 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, 0, 0, 0, /* | |
4825 Return the other window for "other window scroll" commands. | |
4826 If in the minibuffer, `minibuffer-scroll-window' if non-nil | |
4827 specifies the window. | |
4828 If `other-window-scroll-buffer' is non-nil, a window | |
4829 showing that buffer is used. | |
4830 */ | |
4831 ()) | |
4832 { | |
4833 Lisp_Object window; | |
4834 Lisp_Object selected_window = Fselected_window (Qnil); | |
4835 | |
4836 if (MINI_WINDOW_P (XWINDOW (selected_window)) | |
4837 && !NILP (Vminibuffer_scroll_window)) | |
4838 window = Vminibuffer_scroll_window; | |
4839 /* If buffer is specified, scroll that buffer. */ | |
4840 else if (!NILP (Vother_window_scroll_buffer)) | |
4841 { | |
4842 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil, Qnil); | |
4843 if (NILP (window)) | |
4844 window = display_buffer (Vother_window_scroll_buffer, Qt, Qnil); | |
4845 } | |
4846 else | |
4847 { | |
4848 /* Nothing specified; look for a neighboring window on the same | |
4849 frame. */ | |
4850 window = Fnext_window (selected_window, Qnil, Qnil, Qnil); | |
4851 | |
4852 if (EQ (window, selected_window)) | |
4853 /* That didn't get us anywhere; look for a window on another | |
4854 visible frame. */ | |
4855 do | |
4856 window = Fnext_window (window, Qnil, Qt, Qnil); | |
4857 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window)))) | |
4858 && ! EQ (window, selected_window)); | |
4859 } | |
4860 | |
4861 CHECK_LIVE_WINDOW (window); | |
4862 | |
4863 if (EQ (window, selected_window)) | |
563 | 4864 invalid_operation ("There is no other window", Qunbound); |
428 | 4865 |
4866 return window; | |
4867 } | |
4868 | |
4869 DEFUN ("scroll-other-window", Fscroll_other_window, 0, 1, "_P", /* | |
444 | 4870 Scroll next window upward COUNT lines; or near full frame if no arg. |
428 | 4871 The next window is the one below the current one; or the one at the top |
444 | 4872 if the current one is at the bottom. Negative COUNT means scroll downward. |
428 | 4873 When calling from a program, supply a number as argument or nil. |
4874 | |
4875 If in the minibuffer, `minibuffer-scroll-window' if non-nil | |
4876 specifies the window to scroll. | |
4877 If `other-window-scroll-buffer' is non-nil, scroll the window | |
4878 showing that buffer, popping the buffer up if necessary. | |
4879 */ | |
444 | 4880 (count)) |
4881 { | |
4882 window_scroll (Fother_window_for_scrolling (), count, 1, ERROR_ME); | |
428 | 4883 return Qnil; |
4884 } | |
4885 | |
4886 DEFUN ("scroll-left", Fscroll_left, 0, 1, "_P", /* | |
444 | 4887 Scroll selected window display COUNT columns left. |
4888 Default for COUNT is window width minus 2. | |
462 | 4889 |
4890 The characters that are moved over may be added to the current selection | |
4891 \(i.e. active region) if the Shift key is held down, a motion key is used | |
4892 to invoke this command, and `shifted-motion-keys-select-region' is t; see | |
4893 the documentation for this variable for more details. | |
428 | 4894 */ |
444 | 4895 (count)) |
428 | 4896 { |
4897 Lisp_Object window = Fselected_window (Qnil); | |
4898 struct window *w = XWINDOW (window); | |
444 | 4899 int n = (NILP (count) ? |
4900 window_char_width (w, 0) - 2 : | |
4901 XINT (Fprefix_numeric_value (count))); | |
4902 | |
4903 return Fset_window_hscroll (window, make_int (w->hscroll + n)); | |
428 | 4904 } |
4905 | |
4906 DEFUN ("scroll-right", Fscroll_right, 0, 1, "_P", /* | |
444 | 4907 Scroll selected window display COUNT columns right. |
4908 Default for COUNT is window width minus 2. | |
462 | 4909 |
4910 The characters that are moved over may be added to the current selection | |
4911 \(i.e. active region) if the Shift key is held down, a motion key is used | |
4912 to invoke this command, and `shifted-motion-keys-select-region' is t; see | |
4913 the documentation for this variable for more details. | |
428 | 4914 */ |
444 | 4915 (count)) |
428 | 4916 { |
4917 Lisp_Object window = Fselected_window (Qnil); | |
4918 struct window *w = XWINDOW (window); | |
444 | 4919 int n = (NILP (count) ? |
4920 window_char_width (w, 0) - 2 : | |
4921 XINT (Fprefix_numeric_value (count))); | |
4922 | |
4923 return Fset_window_hscroll (window, make_int (w->hscroll - n)); | |
428 | 4924 } |
4925 | |
4926 DEFUN ("center-to-window-line", Fcenter_to_window_line, 0, 2, "_P", /* | |
4927 Center point in WINDOW. With N, put point on line N. | |
4928 The desired position of point is always relative to the window. | |
4929 If WINDOW is nil, the selected window is used. | |
4930 */ | |
4931 (n, window)) | |
4932 { | |
4933 struct window *w = decode_window (window); | |
4934 struct buffer *b = XBUFFER (w->buffer); | |
665 | 4935 Charbpos opoint = BUF_PT (b); |
4936 Charbpos startp; | |
428 | 4937 |
4938 if (NILP (n)) | |
4939 startp = start_with_line_at_pixpos (w, opoint, window_half_pixpos (w)); | |
4940 else | |
4941 { | |
4942 n = Fprefix_numeric_value (n); | |
4943 CHECK_INT (n); | |
4944 startp = start_with_point_on_display_line (w, opoint, XINT (n)); | |
4945 } | |
4946 | |
4947 Fset_marker (w->start[CURRENT_DISP], make_int (startp), w->buffer); | |
4948 | |
4949 w->start_at_line_beg = beginning_of_line_p (b, startp); | |
4950 w->force_start = 1; | |
4951 MARK_WINDOWS_CHANGED (w); | |
4952 return Qnil; | |
4953 } | |
4954 | |
4955 DEFUN ("move-to-window-line", Fmove_to_window_line, 1, 2, "_P", /* | |
4956 Position point relative to WINDOW. | |
4957 With no argument, position text at center of window. | |
4958 An argument specifies window line; zero means top of window, | |
4959 negative means relative to bottom of window. | |
4960 If WINDOW is nil, the selected window is used. | |
4961 */ | |
4962 (arg, window)) | |
4963 { | |
4964 struct window *w; | |
4965 struct buffer *b; | |
4966 int height; | |
665 | 4967 Charbpos start, new_point; |
428 | 4968 int selected; |
4969 | |
4970 /* Don't use decode_window() because we need the new value of | |
4971 WINDOW. */ | |
4972 if (NILP (window)) | |
4973 window = Fselected_window (Qnil); | |
4974 else | |
4975 CHECK_LIVE_WINDOW (window); | |
4976 w = XWINDOW (window); | |
4977 b = XBUFFER (w->buffer); | |
4978 | |
4979 height = window_displayed_height (w); | |
4980 selected = EQ (window, Fselected_window (w->frame)); | |
4981 | |
4982 if (NILP (arg)) | |
4983 { | |
4984 int retval; | |
4985 | |
4986 if (XINT (w->last_modified[CURRENT_DISP]) >= BUF_MODIFF (b) | |
4987 && XINT (w->last_facechange[CURRENT_DISP]) >= BUF_FACECHANGE (b)) | |
4988 { | |
4989 new_point = point_at_center (w, CURRENT_DISP, 0, 0); | |
4990 | |
844 | 4991 /* #### Here we are checking the selected window of the frame |
4992 instead of the selected window period. Elsewhere we check | |
4993 the selected window of the device. What a mess! */ | |
428 | 4994 if (selected) |
4995 BUF_SET_PT (b, new_point); | |
4996 else | |
4997 Fset_window_point (window, make_int (new_point)); | |
4998 | |
4999 retval = line_at_center (w, CURRENT_DISP, 0, 0); | |
5000 } | |
5001 else | |
5002 { | |
5003 start = marker_position (w->start[CURRENT_DISP]); | |
5004 if (start < BUF_BEGV (b)) | |
5005 start = BUF_BEGV (b); | |
5006 else if (start > BUF_ZV (b)) | |
5007 start = BUF_ZV (b); | |
5008 | |
5009 if (selected) | |
5010 new_point = BUF_PT (b); | |
5011 else | |
5012 new_point = marker_position (w->pointm[CURRENT_DISP]); | |
5013 | |
5014 new_point = point_at_center (w, CMOTION_DISP, start, BUF_PT (b)); | |
5015 | |
5016 if (selected) | |
5017 BUF_SET_PT (b, new_point); | |
5018 else | |
5019 Fset_window_point (window, make_int (new_point)); | |
5020 | |
5021 retval = line_at_center (w, CMOTION_DISP, start, BUF_PT (b)); | |
5022 } | |
5023 | |
5024 return make_int (retval); | |
5025 } | |
5026 else | |
5027 { | |
5028 /* #### Is this going to work right when at eob? */ | |
5029 arg = Fprefix_numeric_value (arg); | |
5030 if (XINT (arg) < 0) | |
793 | 5031 arg = make_int (XINT (arg) + height); |
428 | 5032 } |
5033 | |
5034 start = marker_position (w->start[CURRENT_DISP]); | |
5035 if (start < BUF_BEGV (b) || start > BUF_ZV (b)) | |
5036 { | |
5037 if (selected) | |
5038 new_point = BUF_PT (b); | |
5039 else | |
5040 new_point = marker_position (w->pointm[CURRENT_DISP]); | |
5041 | |
5042 new_point = vmotion (XWINDOW (window), new_point, -height / 2, 0); | |
5043 | |
5044 if (selected) | |
5045 BUF_SET_PT (b, new_point); | |
5046 else | |
5047 Fset_window_point (window, make_int (new_point)); | |
5048 | |
5049 Fset_marker (w->start[CURRENT_DISP], make_int (new_point), | |
5050 w->buffer); | |
5051 w->start_at_line_beg = beginning_of_line_p (b, new_point); | |
5052 w->force_start = 1; | |
5053 } | |
5054 else | |
5055 { | |
5056 if (selected) | |
5057 BUF_SET_PT (b, start); | |
5058 else | |
5059 Fset_window_point (window, make_int (start)); | |
5060 } | |
5061 | |
5062 if (selected) | |
5063 return Fvertical_motion (arg, window, Qnil); | |
5064 else | |
5065 { | |
5066 int vpos; | |
5067 new_point = vmotion (XWINDOW (window), | |
5068 marker_position (w->pointm[CURRENT_DISP]), | |
5069 XINT (arg), &vpos); | |
5070 Fset_window_point (window, make_int (new_point)); | |
5071 return make_int (vpos); | |
5072 } | |
5073 } | |
5074 | |
5075 | |
5076 static int | |
5077 map_windows_1 (Lisp_Object window, | |
5078 int (*mapfun) (struct window *w, void *closure), | |
5079 void *closure) | |
5080 { | |
5081 for (; !NILP (window); window = XWINDOW (window)->next) | |
5082 { | |
5083 int retval; | |
5084 struct window *w = XWINDOW (window); | |
5085 | |
5086 if (!NILP (w->vchild)) | |
5087 retval = map_windows_1 (w->vchild, mapfun, closure); | |
5088 else if (!NILP (w->hchild)) | |
5089 retval = map_windows_1 (w->hchild, mapfun, closure); | |
5090 else | |
5091 retval = (mapfun) (w, closure); | |
5092 | |
5093 if (retval) | |
5094 return retval; | |
5095 } | |
5096 | |
5097 return 0; | |
5098 } | |
5099 | |
5100 /* Map MAPFUN over the windows in F. CLOSURE is passed to each | |
5101 invocation of MAPFUN. If any invocation of MAPFUN returns | |
5102 non-zero, the mapping is halted. Otherwise, map_windows() maps | |
5103 over all windows in F. | |
5104 | |
800 | 5105 If F is null, map over all frames on all devices and consoles. |
5106 | |
428 | 5107 If MAPFUN creates or deletes windows, the behavior is undefined. */ |
5108 | |
5109 int | |
5110 map_windows (struct frame *f, int (*mapfun) (struct window *w, void *closure), | |
5111 void *closure) | |
5112 { | |
5113 if (f) | |
5114 return map_windows_1 (FRAME_ROOT_WINDOW (f), mapfun, closure); | |
5115 else | |
5116 { | |
5117 Lisp_Object frmcons, devcons, concons; | |
5118 | |
5119 FRAME_LOOP_NO_BREAK(frmcons, devcons, concons) | |
5120 { | |
5121 int v = map_windows_1 (FRAME_ROOT_WINDOW (XFRAME (XCAR (frmcons))), | |
5122 mapfun, closure); | |
5123 if (v) | |
5124 return v; | |
5125 } | |
5126 } | |
5127 | |
5128 return 0; | |
5129 } | |
5130 | |
5131 | |
5132 static void | |
2286 | 5133 modeline_shadow_thickness_changed (Lisp_Object UNUSED (specifier), |
5134 struct window *w, | |
5135 Lisp_Object UNUSED (oldval)) | |
428 | 5136 { |
5137 w->shadow_thickness_changed = 1; | |
5138 MARK_WINDOWS_CHANGED (w); | |
5139 } | |
5140 | |
5141 static void | |
2286 | 5142 vertical_divider_changed_in_window (Lisp_Object UNUSED (specifier), |
428 | 5143 struct window *w, |
2286 | 5144 Lisp_Object UNUSED (oldval)) |
428 | 5145 { |
5146 MARK_WINDOWS_CHANGED (w); | |
5147 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (XFRAME (WINDOW_FRAME (w))); | |
5148 } | |
5149 | |
5150 /* also used in scrollbar.c */ | |
5151 void | |
2286 | 5152 some_window_value_changed (Lisp_Object UNUSED (specifier), |
5153 struct window *w, | |
5154 Lisp_Object UNUSED (oldval)) | |
428 | 5155 { |
5156 MARK_WINDOWS_CHANGED (w); | |
5157 } | |
5158 | |
5159 #ifdef MEMORY_USAGE_STATS | |
5160 | |
5161 struct window_stats | |
5162 { | |
5163 int face; | |
5164 int glyph; | |
5165 #ifdef HAVE_SCROLLBARS | |
5166 int scrollbar; | |
5167 #endif | |
5168 int line_start; | |
5169 int other_redisplay; | |
5170 int other; | |
5171 }; | |
5172 | |
5173 static void | |
5174 compute_window_mirror_usage (struct window_mirror *mir, | |
5175 struct window_stats *stats, | |
5176 struct overhead_stats *ovstats) | |
5177 { | |
5178 if (!mir) | |
5179 return; | |
5127
a9c41067dd88
more cleanups, terminology clarification, lots of doc work
Ben Wing <ben@xemacs.org>
parents:
5126
diff
changeset
|
5180 stats->other += lisp_object_storage_size (wrap_window_mirror (mir), ovstats); |
428 | 5181 #ifdef HAVE_SCROLLBARS |
5182 { | |
5183 struct device *d = XDEVICE (FRAME_DEVICE (mir->frame)); | |
5184 | |
5185 stats->scrollbar += | |
5186 compute_scrollbar_instance_usage (d, mir->scrollbar_vertical_instance, | |
5187 ovstats); | |
5188 stats->scrollbar += | |
5189 compute_scrollbar_instance_usage (d, mir->scrollbar_horizontal_instance, | |
5190 ovstats); | |
5191 } | |
5192 #endif /* HAVE_SCROLLBARS */ | |
5193 stats->other_redisplay += | |
5194 compute_display_line_dynarr_usage (mir->current_display_lines, ovstats); | |
5195 stats->other_redisplay += | |
5196 compute_display_line_dynarr_usage (mir->desired_display_lines, ovstats); | |
5197 } | |
5198 | |
5199 static void | |
5200 compute_window_usage (struct window *w, struct window_stats *stats, | |
5201 struct overhead_stats *ovstats) | |
5202 { | |
5203 xzero (*stats); | |
5127
a9c41067dd88
more cleanups, terminology clarification, lots of doc work
Ben Wing <ben@xemacs.org>
parents:
5126
diff
changeset
|
5204 stats->other += lisp_object_storage_size (wrap_window (w), ovstats); |
428 | 5205 stats->face += compute_face_cachel_usage (w->face_cachels, ovstats); |
5206 stats->glyph += compute_glyph_cachel_usage (w->glyph_cachels, ovstats); | |
5207 stats->line_start += | |
5208 compute_line_start_cache_dynarr_usage (w->line_start_cache, ovstats); | |
5209 compute_window_mirror_usage (find_window_mirror (w), stats, ovstats); | |
5210 } | |
5211 | |
5212 DEFUN ("window-memory-usage", Fwindow_memory_usage, 1, 1, 0, /* | |
5213 Return stats about the memory usage of window WINDOW. | |
5214 The values returned are in the form of an alist of usage types and byte | |
5215 counts. The byte counts attempt to encompass all the memory used | |
5216 by the window (separate from the memory logically associated with a | |
5217 buffer or frame), including internal structures and any malloc() | |
5218 overhead associated with them. In practice, the byte counts are | |
5219 underestimated because certain memory usage is very hard to determine | |
5220 \(e.g. the amount of memory used inside the Xt library or inside the | |
5221 X server) and because there is other stuff that might logically | |
5222 be associated with a window, buffer, or frame (e.g. window configurations, | |
5223 glyphs) but should not obviously be included in the usage counts. | |
5224 | |
5225 Multiple slices of the total memory usage may be returned, separated | |
5226 by a nil. Each slice represents a particular view of the memory, a | |
5227 particular way of partitioning it into groups. Within a slice, there | |
5228 is no overlap between the groups of memory, and each slice collectively | |
5229 represents all the memory concerned. | |
5230 */ | |
5231 (window)) | |
5232 { | |
5233 struct window_stats stats; | |
5234 struct overhead_stats ovstats; | |
5235 Lisp_Object val = Qnil; | |
5236 | |
5237 CHECK_WINDOW (window); /* dead windows should be allowed, no? */ | |
5238 xzero (ovstats); | |
5239 compute_window_usage (XWINDOW (window), &stats, &ovstats); | |
5240 | |
5241 val = acons (Qface_cache, make_int (stats.face), val); | |
5242 val = acons (Qglyph_cache, make_int (stats.glyph), val); | |
5243 #ifdef HAVE_SCROLLBARS | |
5244 val = acons (Qscrollbar_instances, make_int (stats.scrollbar), val); | |
5245 #endif | |
5246 val = acons (Qline_start_cache, make_int (stats.line_start), val); | |
5247 val = acons (Qother_redisplay, make_int (stats.other_redisplay), val); | |
5248 val = acons (Qother, make_int (stats.other), val); | |
5249 val = Fcons (Qnil, val); | |
5250 val = acons (Qactually_requested, make_int (ovstats.was_requested), val); | |
5251 val = acons (Qmalloc_overhead, make_int (ovstats.malloc_overhead), val); | |
5252 val = acons (Qdynarr_overhead, make_int (ovstats.dynarr_overhead), val); | |
5253 | |
5254 return Fnreverse (val); | |
5255 } | |
5256 | |
5257 #endif /* MEMORY_USAGE_STATS */ | |
5258 | |
5259 /* Mark all subwindows of a window as deleted. The argument | |
5260 W is actually the subwindow tree of the window in question. */ | |
5261 | |
5262 void | |
5263 delete_all_subwindows (struct window *w) | |
5264 { | |
5265 if (!NILP (w->next)) delete_all_subwindows (XWINDOW (w->next)); | |
5266 if (!NILP (w->vchild)) delete_all_subwindows (XWINDOW (w->vchild)); | |
5267 if (!NILP (w->hchild)) delete_all_subwindows (XWINDOW (w->hchild)); | |
5268 | |
5269 mark_window_as_deleted (w); | |
5270 } | |
5271 | |
1149 | 5272 |
2289 | 5273 static int |
5274 get_current_pixel_pos (Lisp_Object window, Lisp_Object pos, | |
5275 struct window **w, | |
5276 struct rune **rb, struct display_line **dl) | |
428 | 5277 { |
2289 | 5278 display_line_dynarr *dla; |
5279 struct display_block *db = NULL; | |
5280 int x, y; | |
5281 | |
5282 *rb = NULL; | |
5283 *dl = NULL; | |
5284 *w = decode_window (window); | |
5285 dla = window_display_lines (*w, CURRENT_DISP); | |
5286 x = (*w)->last_point_x[CURRENT_DISP]; | |
5287 y = (*w)->last_point_y[CURRENT_DISP]; | |
5288 if (MINI_WINDOW_P (*w)) | |
5289 return 0; | |
428 | 5290 |
5291 if (y<0 || x<0 || y >= Dynarr_length (dla) || !NILP (pos)) | |
5292 { | |
5293 int first_line, i; | |
665 | 5294 Charbpos point; |
428 | 5295 |
5296 if (NILP (pos)) | |
5297 pos = Fwindow_point (window); | |
438 | 5298 |
428 | 5299 CHECK_INT (pos); |
5300 point = XINT (pos); | |
5301 | |
4967 | 5302 if (Dynarr_length (dla) && Dynarr_begin (dla)->modeline) |
428 | 5303 first_line = 1; |
5304 else | |
5305 first_line = 0; | |
5306 | |
5307 for (i = first_line; i < Dynarr_length (dla); i++) | |
5308 { | |
2289 | 5309 *dl = Dynarr_atp (dla, i); |
428 | 5310 /* find the vertical location first */ |
2289 | 5311 if (point >= (*dl)->charpos && point <= (*dl)->end_charpos) |
428 | 5312 { |
2289 | 5313 db = get_display_block_from_line (*dl, TEXT); |
428 | 5314 for (i = 0; i < Dynarr_length (db->runes); i++) |
5315 { | |
2289 | 5316 *rb = Dynarr_atp (db->runes, i); |
2290 | 5317 if (point <= (*rb)->charpos) |
826 | 5318 goto found_charpos; |
428 | 5319 } |
2289 | 5320 return 0; |
428 | 5321 } |
5322 } | |
2289 | 5323 return 0; |
826 | 5324 found_charpos: |
428 | 5325 ; |
5326 } | |
5327 else | |
5328 { | |
442 | 5329 /* optimized case */ |
2289 | 5330 *dl = Dynarr_atp (dla, y); |
5331 db = get_display_block_from_line (*dl, TEXT); | |
428 | 5332 |
5333 if (x >= Dynarr_length (db->runes)) | |
2289 | 5334 return 0; |
5335 | |
5336 *rb = Dynarr_atp (db->runes, x); | |
428 | 5337 } |
5338 | |
2289 | 5339 return 1; |
5340 } | |
5341 | |
5342 DEFUN ("current-pixel-column", Fcurrent_pixel_column, 0, 2, 0, /* | |
5343 Return the horizontal pixel position of point POS in window. | |
5344 Beginning of line is column 0. If WINDOW is nil, the current window | |
5345 is assumed. If POS is nil, point is assumed. Note that POS must be | |
5346 visible for a non-nil result to be returned. This is calculated using | |
5347 the redisplay display tables; because of this, the returned value will | |
5348 only be correct if the redisplay tables are up-to-date. Use | |
5349 \"(sit-for 0)\" to insure that they are; however, if WINDOW is part of | |
5350 a new frame, use the following instead: | |
5351 (while (not (frame-visible-p frame)) (sleep-for .5)) | |
5352 */ | |
5353 (window, pos)) | |
5354 { | |
5355 struct window* w; | |
5356 struct display_line *dl; | |
5357 struct rune* rb; | |
5358 | |
5359 if (!get_current_pixel_pos(window, pos, &w, &rb, &dl)) | |
5360 return Qnil; | |
5361 | |
428 | 5362 return make_int (rb->xpos - WINDOW_LEFT (w)); |
5363 } | |
5364 | |
2289 | 5365 DEFUN ("current-pixel-row", Fcurrent_pixel_row, 0, 2, 0, /* |
5366 Return the vertical pixel position of point POS in window. Top of | |
5367 window is row 0. If WINDOW is nil, the current window is assumed. If | |
5368 POS is nil, point is assumed. Note that POS must be visible for a | |
5369 non-nil result to be returned. This is calculated using the redisplay | |
5370 display tables; because of this, the returned value will only be | |
5371 correct if the redisplay tables are up-to-date. Use \"(sit-for 0)\" | |
5372 to insure that they are; however, if WINDOW is part of a new frame, | |
5373 use the following instead: | |
5374 (while (not (frame-visible-p frame)) (sleep-for .5)) | |
5375 */ | |
5376 (window, pos)) | |
5377 { | |
5378 struct window* w; | |
5379 struct display_line *dl; | |
5380 struct rune* rb; | |
5381 | |
5382 if (!get_current_pixel_pos(window, pos, &w, &rb, &dl)) | |
5383 return Qnil; | |
5384 | |
5385 return make_int (dl->ypos - dl->ascent - WINDOW_TOP (w)); | |
5386 } | |
5387 | |
428 | 5388 |
5389 #ifdef DEBUG_XEMACS | |
5390 /* This is short and simple in elisp, but... it was written to debug | |
5391 problems purely on the C side. That is where we need to call it so | |
5392 here it is. */ | |
5393 static void | |
5394 debug_print_window (Lisp_Object window, int level) | |
5395 { | |
5396 int i; | |
5397 Lisp_Object child = Fwindow_first_vchild (window); | |
5398 | |
5399 if (NILP (child)) | |
5400 child = Fwindow_first_hchild (window); | |
5401 | |
5402 for (i = level; i > 0; i--) | |
442 | 5403 stderr_out ("\t"); |
5404 | |
5405 stderr_out ("#<window"); | |
428 | 5406 { |
5407 Lisp_Object buffer = XWINDOW (window)->buffer; | |
5408 if (!NILP (buffer) && BUFFERP (buffer)) | |
442 | 5409 stderr_out (" on %s", XSTRING_DATA (XBUFFER (buffer)->name)); |
428 | 5410 } |
442 | 5411 stderr_out (" 0x%x>", XWINDOW (window)->header.uid); |
428 | 5412 |
5413 while (!NILP (child)) | |
5414 { | |
5415 debug_print_window (child, level + 1); | |
5416 child = Fwindow_next_child (child); | |
5417 } | |
5418 } | |
5419 | |
5420 void debug_print_windows (struct frame *f); | |
5421 void | |
5422 debug_print_windows (struct frame *f) | |
5423 { | |
5424 debug_print_window (f->root_window, 0); | |
5425 putc ('\n', stderr); | |
5426 } | |
5427 #endif /* DEBUG_XEMACS */ | |
5428 | |
5429 | |
5430 /************************************************************************/ | |
5431 /* initialization */ | |
5432 /************************************************************************/ | |
5433 | |
5434 void | |
5435 syms_of_window (void) | |
5436 { | |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3078
diff
changeset
|
5437 INIT_LISP_OBJECT (window); |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3078
diff
changeset
|
5438 INIT_LISP_OBJECT (window_mirror); |
3092 | 5439 #ifdef NEW_GC |
5118
e0db3c197671
merge up to latest default branch, doesn't compile yet
Ben Wing <ben@xemacs.org>
diff
changeset
|
5440 INIT_LISP_OBJECT (face_cachel); |
e0db3c197671
merge up to latest default branch, doesn't compile yet
Ben Wing <ben@xemacs.org>
diff
changeset
|
5441 INIT_LISP_OBJECT (face_cachel_dynarr); |
e0db3c197671
merge up to latest default branch, doesn't compile yet
Ben Wing <ben@xemacs.org>
diff
changeset
|
5442 INIT_LISP_OBJECT (glyph_cachel); |
e0db3c197671
merge up to latest default branch, doesn't compile yet
Ben Wing <ben@xemacs.org>
diff
changeset
|
5443 INIT_LISP_OBJECT (glyph_cachel_dynarr); |
3092 | 5444 #endif /* NEW_GC */ |
442 | 5445 |
563 | 5446 DEFSYMBOL (Qwindowp); |
5447 DEFSYMBOL (Qwindow_live_p); | |
5448 DEFSYMBOL (Qdisplay_buffer); | |
428 | 5449 |
5450 #ifdef MEMORY_USAGE_STATS | |
563 | 5451 DEFSYMBOL (Qface_cache); |
5452 DEFSYMBOL (Qglyph_cache); | |
5453 DEFSYMBOL (Qline_start_cache); | |
428 | 5454 #ifdef HAVE_SCROLLBARS |
563 | 5455 DEFSYMBOL (Qscrollbar_instances); |
428 | 5456 #endif |
563 | 5457 DEFSYMBOL (Qother_redisplay); |
428 | 5458 /* Qother in general.c */ |
5459 #endif | |
5460 | |
707 | 5461 DEFSYMBOL (Qtruncate_partial_width_windows); |
1149 | 5462 DEFSYMBOL (Qcurrent_window_configuration); |
5463 DEFSYMBOL (Qset_window_configuration); | |
707 | 5464 |
428 | 5465 DEFSUBR (Fselected_window); |
5466 DEFSUBR (Flast_nonminibuf_window); | |
5467 DEFSUBR (Fminibuffer_window); | |
5468 DEFSUBR (Fwindow_minibuffer_p); | |
5469 DEFSUBR (Fwindowp); | |
5470 DEFSUBR (Fwindow_live_p); | |
5471 DEFSUBR (Fwindow_first_hchild); | |
5472 DEFSUBR (Fwindow_first_vchild); | |
5473 DEFSUBR (Fwindow_next_child); | |
5474 DEFSUBR (Fwindow_previous_child); | |
5475 DEFSUBR (Fwindow_parent); | |
5476 DEFSUBR (Fwindow_lowest_p); | |
5477 DEFSUBR (Fwindow_truncated_p); | |
5478 DEFSUBR (Fwindow_highest_p); | |
5479 DEFSUBR (Fwindow_leftmost_p); | |
5480 DEFSUBR (Fwindow_rightmost_p); | |
5481 DEFSUBR (Fpos_visible_in_window_p); | |
5482 DEFSUBR (Fwindow_buffer); | |
5483 DEFSUBR (Fwindow_frame); | |
5484 DEFSUBR (Fwindow_height); | |
5485 DEFSUBR (Fwindow_displayed_height); | |
5486 DEFSUBR (Fwindow_width); | |
442 | 5487 DEFSUBR (Fwindow_full_width); |
428 | 5488 DEFSUBR (Fwindow_pixel_height); |
5489 DEFSUBR (Fwindow_pixel_width); | |
442 | 5490 DEFSUBR (Fwindow_text_area_height); |
428 | 5491 DEFSUBR (Fwindow_text_area_pixel_height); |
5492 DEFSUBR (Fwindow_displayed_text_pixel_height); | |
5493 DEFSUBR (Fwindow_text_area_pixel_width); | |
5494 DEFSUBR (Fwindow_hscroll); | |
438 | 5495 DEFSUBR (Fset_window_hscroll); |
428 | 5496 DEFSUBR (Fmodeline_hscroll); |
5497 DEFSUBR (Fset_modeline_hscroll); | |
5498 DEFSUBR (Fwindow_pixel_edges); | |
5499 DEFSUBR (Fwindow_text_area_pixel_edges); | |
5500 DEFSUBR (Fwindow_point); | |
5501 DEFSUBR (Fwindow_start); | |
5502 DEFSUBR (Fwindow_end); | |
442 | 5503 DEFSUBR (Fwindow_last_line_visible_height); |
428 | 5504 DEFSUBR (Fset_window_point); |
5505 DEFSUBR (Fset_window_start); | |
5506 DEFSUBR (Fwindow_dedicated_p); | |
5507 DEFSUBR (Fset_window_dedicated_p); | |
5508 DEFSUBR (Fnext_window); | |
5509 DEFSUBR (Fprevious_window); | |
5510 DEFSUBR (Fnext_vertical_window); | |
5511 DEFSUBR (Fother_window); | |
5512 DEFSUBR (Fget_lru_window); | |
5513 DEFSUBR (Fget_largest_window); | |
5514 DEFSUBR (Fget_buffer_window); | |
5515 DEFSUBR (Fwindow_left_margin_pixel_width); | |
5516 DEFSUBR (Fwindow_right_margin_pixel_width); | |
5517 DEFSUBR (Fdelete_other_windows); | |
5518 DEFSUBR (Fdelete_windows_on); | |
5519 DEFSUBR (Freplace_buffer_in_windows); | |
5520 DEFSUBR (Fdelete_window); | |
5521 DEFSUBR (Fset_window_buffer); | |
5522 DEFSUBR (Fselect_window); | |
5523 DEFSUBR (Fsplit_window); | |
5524 DEFSUBR (Fenlarge_window); | |
5525 DEFSUBR (Fenlarge_window_pixels); | |
5526 DEFSUBR (Fshrink_window); | |
5527 DEFSUBR (Fshrink_window_pixels); | |
5528 DEFSUBR (Fscroll_up); | |
5529 DEFSUBR (Fscroll_down); | |
5530 DEFSUBR (Fscroll_left); | |
5531 DEFSUBR (Fscroll_right); | |
5532 DEFSUBR (Fother_window_for_scrolling); | |
5533 DEFSUBR (Fscroll_other_window); | |
5534 DEFSUBR (Fcenter_to_window_line); | |
5535 DEFSUBR (Fmove_to_window_line); | |
5536 #ifdef MEMORY_USAGE_STATS | |
5537 DEFSUBR (Fwindow_memory_usage); | |
5538 #endif | |
5539 DEFSUBR (Fcurrent_pixel_column); | |
2289 | 5540 DEFSUBR (Fcurrent_pixel_row); |
428 | 5541 } |
5542 | |
5543 void | |
5544 reinit_vars_of_window (void) | |
5545 { | |
5546 /* Make sure all windows get marked */ | |
5547 minibuf_window = Qnil; | |
5548 staticpro_nodump (&minibuf_window); | |
5549 } | |
5550 | |
5551 void | |
5552 vars_of_window (void) | |
5553 { | |
5554 DEFVAR_BOOL ("scroll-on-clipped-lines", &scroll_on_clipped_lines /* | |
5555 *Non-nil means to scroll if point lands on a line which is clipped. | |
5556 */ ); | |
5557 scroll_on_clipped_lines = 1; | |
5558 | |
5559 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function /* | |
5560 Non-nil means call as function to display a help buffer. | |
5561 The function is called with one argument, the buffer to be displayed. | |
5562 Used by `with-output-to-temp-buffer'. | |
5563 If this function is used, then it must do the entire job of showing | |
5564 the buffer; `temp-buffer-show-hook' is not run unless this function runs it. | |
442 | 5565 \(`temp-buffer-show-hook' is obsolete. Do not use in new code.) |
428 | 5566 */ ); |
5567 Vtemp_buffer_show_function = Qnil; | |
5568 | |
5569 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuffer_scroll_window /* | |
5570 Non-nil means it is the window that \\<minibuffer-local-map>\\[scroll-other-window] in minibuffer should scroll. | |
5571 */ ); | |
5572 Vminibuffer_scroll_window = Qnil; | |
5573 | |
5574 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer /* | |
5575 If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window. | |
5576 */ ); | |
5577 Vother_window_scroll_buffer = Qnil; | |
5578 | |
5579 DEFVAR_LISP ("window-pixel-scroll-increment", &Vwindow_pixel_scroll_increment /* | |
5580 *Number of pixels to scroll by per requested line. | |
5581 If nil then normal line scrolling occurs regardless of line height. | |
5582 If t then scrolling is done in increments equal to the height of the default face. | |
5583 */ ); | |
5584 Vwindow_pixel_scroll_increment = Qt; | |
5585 | |
5586 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines /* | |
5587 *Number of lines of continuity when scrolling by screenfuls. | |
5588 */ ); | |
5589 next_screen_context_lines = 2; | |
5590 | |
5591 DEFVAR_INT ("window-min-height", &window_min_height /* | |
5592 *Delete any window less than this tall (including its modeline). | |
5593 */ ); | |
5594 window_min_height = 4; | |
5595 | |
5596 DEFVAR_INT ("window-min-width", &window_min_width /* | |
5597 *Delete any window less than this wide. | |
5598 */ ); | |
5599 window_min_width = 10; | |
5600 } | |
5601 | |
5602 void | |
5603 specifier_vars_of_window (void) | |
5604 { | |
5605 DEFVAR_SPECIFIER ("modeline-shadow-thickness", &Vmodeline_shadow_thickness /* | |
5606 *How thick to draw 3D shadows around modelines. | |
5607 If this is set to 0, modelines will be the traditional 2D. Sizes above | |
5608 10 will be accepted but the maximum thickness that will be drawn is 10. | |
5609 This is a specifier; use `set-specifier' to change it. | |
5610 */ ); | |
5611 Vmodeline_shadow_thickness = Fmake_specifier (Qinteger); | |
5612 /* The initial value for modeline-shadow-thickness is 2, but if the | |
5613 user removes all specifications we provide a fallback value of 0, | |
5614 which is probably what was expected. */ | |
5615 set_specifier_fallback (Vmodeline_shadow_thickness, | |
5616 list1 (Fcons (Qnil, Qzero))); | |
5617 Fadd_spec_to_specifier (Vmodeline_shadow_thickness, make_int (2), | |
5618 Qnil, Qnil, Qnil); | |
5619 set_specifier_caching (Vmodeline_shadow_thickness, | |
438 | 5620 offsetof (struct window, modeline_shadow_thickness), |
428 | 5621 modeline_shadow_thickness_changed, |
444 | 5622 0, 0, 0); |
428 | 5623 |
5624 DEFVAR_SPECIFIER ("has-modeline-p", &Vhas_modeline_p /* | |
5625 *Whether the modeline should be displayed. | |
5626 This is a specifier; use `set-specifier' to change it. | |
5627 */ ); | |
5628 Vhas_modeline_p = Fmake_specifier (Qboolean); | |
5629 set_specifier_fallback (Vhas_modeline_p, | |
5630 list1 (Fcons (Qnil, Qt))); | |
5631 set_specifier_caching (Vhas_modeline_p, | |
438 | 5632 offsetof (struct window, has_modeline_p), |
428 | 5633 /* #### It's strange that we need a special |
5634 flag to indicate that the shadow-thickness | |
5635 has changed, but not one to indicate that | |
5636 the modeline has been turned off or on. */ | |
5637 some_window_value_changed, | |
444 | 5638 0, 0, 0); |
428 | 5639 |
5640 DEFVAR_SPECIFIER ("vertical-divider-always-visible-p", | |
5641 &Vvertical_divider_always_visible_p /* | |
5642 *Should XEmacs always display vertical dividers between windows. | |
5643 | |
5644 When this is non-nil, vertical dividers are always shown, and are | |
5645 draggable. When it is nil, vertical dividers are shown only when | |
5646 there are no scrollbars in between windows, and are not draggable. | |
5647 | |
5648 This is a specifier; use `set-specifier' to change it. | |
5649 */ ); | |
5650 Vvertical_divider_always_visible_p = Fmake_specifier (Qboolean); | |
5651 set_specifier_fallback (Vvertical_divider_always_visible_p, | |
5652 list1 (Fcons (Qnil, Qt))); | |
5653 set_specifier_caching (Vvertical_divider_always_visible_p, | |
438 | 5654 offsetof (struct window, |
5655 vertical_divider_always_visible_p), | |
428 | 5656 vertical_divider_changed_in_window, |
444 | 5657 0, 0, 0); |
428 | 5658 |
5659 DEFVAR_SPECIFIER ("vertical-divider-shadow-thickness", &Vvertical_divider_shadow_thickness /* | |
5660 *How thick to draw 3D shadows around vertical dividers. | |
5661 This is a specifier; use `set-specifier' to change it. | |
5662 */ ); | |
5663 Vvertical_divider_shadow_thickness = Fmake_specifier (Qinteger); | |
5664 set_specifier_fallback (Vvertical_divider_shadow_thickness, | |
5665 list1 (Fcons (Qnil, Qzero))); | |
5666 Fadd_spec_to_specifier (Vvertical_divider_shadow_thickness, make_int (2), | |
5667 Qnil, Qnil, Qnil); | |
5668 set_specifier_caching (Vvertical_divider_shadow_thickness, | |
438 | 5669 offsetof (struct window, |
5670 vertical_divider_shadow_thickness), | |
428 | 5671 vertical_divider_changed_in_window, |
444 | 5672 0, 0, 0); |
428 | 5673 DEFVAR_SPECIFIER ("vertical-divider-line-width", &Vvertical_divider_line_width /* |
5674 *The width of the vertical dividers, not including shadows. | |
5675 | |
5676 For TTY windows, divider line is always one character wide. When | |
5677 instance of this specifier is zero in a TTY window, no divider is | |
5678 drawn at all between windows. When non-zero, a one character wide | |
5679 divider is displayed. | |
5680 | |
5681 This is a specifier; use `set-specifier' to change it. | |
5682 */ ); | |
5683 | |
5684 Vvertical_divider_line_width = Fmake_specifier (Qnatnum); | |
5685 { | |
5686 Lisp_Object fb = Qnil; | |
5687 #ifdef HAVE_TTY | |
5688 fb = Fcons (Fcons (list1 (Qtty), make_int (1)), fb); | |
5689 #endif | |
462 | 5690 #ifdef HAVE_GTK |
5691 fb = Fcons (Fcons (list1 (Qgtk), make_int (3)), fb); | |
5692 #endif | |
428 | 5693 #ifdef HAVE_X_WINDOWS |
5694 fb = Fcons (Fcons (list1 (Qx), make_int (3)), fb); | |
5695 #endif | |
5696 #ifdef HAVE_MS_WINDOWS | |
5697 /* #### This should be made magic and made to obey system settings */ | |
5698 fb = Fcons (Fcons (list1 (Qmswindows), make_int (3)), fb); | |
5699 #endif | |
5700 set_specifier_fallback (Vvertical_divider_line_width, fb); | |
5701 } | |
5702 set_specifier_caching (Vvertical_divider_line_width, | |
438 | 5703 offsetof (struct window, |
5704 vertical_divider_line_width), | |
428 | 5705 vertical_divider_changed_in_window, |
444 | 5706 0, 0, 0); |
428 | 5707 |
5708 DEFVAR_SPECIFIER ("vertical-divider-spacing", &Vvertical_divider_spacing /* | |
5709 *How much space to leave around the vertical dividers. | |
5710 | |
5711 In TTY windows, spacing is always zero, and the value of this | |
5712 specifier is ignored. | |
5713 | |
5714 This is a specifier; use `set-specifier' to change it. | |
5715 */ ); | |
5716 Vvertical_divider_spacing = Fmake_specifier (Qnatnum); | |
5717 { | |
5718 Lisp_Object fb = Qnil; | |
5719 #ifdef HAVE_TTY | |
5720 fb = Fcons (Fcons (list1 (Qtty), Qzero), fb); | |
5721 #endif | |
5722 #ifdef HAVE_X_WINDOWS | |
5723 /* #### 3D dividers look great on MS Windows with spacing = 0. | |
5724 Should not the same value be the fallback under X? - kkm */ | |
5725 fb = Fcons (Fcons (list1 (Qx), make_int (2)), fb); | |
5726 #endif | |
462 | 5727 #ifdef HAVE_GTK |
5728 fb = Fcons (Fcons (list1 (Qgtk), Qzero), fb); | |
5729 #endif | |
428 | 5730 #ifdef HAVE_MS_WINDOWS |
5731 fb = Fcons (Fcons (list1 (Qmswindows), Qzero), fb); | |
5732 #endif | |
5733 set_specifier_fallback (Vvertical_divider_spacing, fb); | |
5734 } | |
5735 set_specifier_caching (Vvertical_divider_spacing, | |
438 | 5736 offsetof (struct window, vertical_divider_spacing), |
428 | 5737 vertical_divider_changed_in_window, |
444 | 5738 0, 0, 0); |
5739 } |